From d51498e5b9505cdb9320cdde665a3a13732e2e41 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Mon, 23 Dec 2019 19:10:48 +0300 Subject: [PATCH 001/160] help2man 1.47.11 --- system/base/help2man/pspec.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/system/base/help2man/pspec.xml b/system/base/help2man/pspec.xml index 1bc502e7..39633e54 100644 --- a/system/base/help2man/pspec.xml +++ b/system/base/help2man/pspec.xml @@ -12,7 +12,7 @@ app:console GNU utility to convert program --help output to a man page Help2man is a tool which generate man page from help text of programs. - http://ftp.gnu.org/gnu/help2man/help2man-1.47.3.tar.xz + http://ftp.gnu.org/gnu/help2man/help2man-1.47.11.tar.xz perl-Locale-gettext @@ -37,6 +37,13 @@ + + 2019-12-23 + 1.47.11 + Version bump + Idris Kalp + idriskalp@gmail.com + 2018-07-15 1.47.3 From bba6d34b277a87bcbea3baa6213b263942e3205d Mon Sep 17 00:00:00 2001 From: idriskalp Date: Mon, 23 Dec 2019 19:12:07 +0300 Subject: [PATCH 002/160] flex rebuild --- system/devel/flex/pspec.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/system/devel/flex/pspec.xml b/system/devel/flex/pspec.xml index 610f3ed6..6b3b58ef 100644 --- a/system/devel/flex/pspec.xml +++ b/system/devel/flex/pspec.xml @@ -37,6 +37,13 @@ + + 2019-12-23 + 2.6.4 + Rebuild. + Idris Kalp + idriskalp@gmail.com + 2018-07-30 2.6.4 From 6664ee9a2c2de4dfb8fb117c51010430880b1bd8 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Mon, 23 Dec 2019 19:13:50 +0300 Subject: [PATCH 003/160] bc rebuild --- system/base/bc/pspec.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/system/base/bc/pspec.xml b/system/base/bc/pspec.xml index ef56c63e..016ffc56 100644 --- a/system/base/bc/pspec.xml +++ b/system/base/bc/pspec.xml @@ -42,6 +42,13 @@ + + 2019-12-23 + 1.07.1 + Rebuild + Idris Kalp + idriskalp@gmail.com + 2018-07-30 1.07.1 From bd02dea80da50d62017a6247793c1b389a883a35 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Mon, 23 Dec 2019 19:27:47 +0300 Subject: [PATCH 004/160] elfutils 0.178 --- system/devel/elfutils/pspec.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/system/devel/elfutils/pspec.xml b/system/devel/elfutils/pspec.xml index fe35c02e..49ba223e 100644 --- a/system/devel/elfutils/pspec.xml +++ b/system/devel/elfutils/pspec.xml @@ -13,7 +13,7 @@ library Libraries/utilities to handle ELF objects elfutils contains libraries and utilities to handle ELF objects and is a replacement for libelf. - ftp://sourceware.org/pub/elfutils/0.176/elfutils-0.176.tar.bz2 + ftp://sourceware.org/pub/elfutils/0.178/elfutils-0.178.tar.bz2 bzip2 xz-devel @@ -58,6 +58,13 @@ + + 2019-12-23 + 0.178 + Version bump. + Idris Kalp + idriskalp@gmail.com + 2019-04-23 0.176 From 99cffeaddce9a7853e9b701fdd656f29f9ace732 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Mon, 23 Dec 2019 19:31:27 +0300 Subject: [PATCH 005/160] elfutils fix --- system/devel/elfutils/actions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/devel/elfutils/actions.py b/system/devel/elfutils/actions.py index 2a73dbeb..03a4ae95 100644 --- a/system/devel/elfutils/actions.py +++ b/system/devel/elfutils/actions.py @@ -15,7 +15,7 @@ def setup(): # themselves, and they use -Werror. - options ='-disable-nls --program-prefix=\"eu-\" --with-zlib' + options ='-disable-nls --program-prefix=\"eu-\" --with-zlib --disable-debuginfod' if get.buildTYPE() == "emul32": shelltools.export("PKG_CONFIG_PATH","/usr/lib32/pkgconfig") From 10384002a10c2624ee892ce357fa33fa6047a196 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Mon, 23 Dec 2019 19:31:57 +0300 Subject: [PATCH 006/160] glpk 4.65 --- system/devel/glpk/pspec.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/system/devel/glpk/pspec.xml b/system/devel/glpk/pspec.xml index 83c3705d..6c44caea 100644 --- a/system/devel/glpk/pspec.xml +++ b/system/devel/glpk/pspec.xml @@ -12,7 +12,7 @@ library GNU Linear Programming Kit The GLPK (GNU Linear Programming Kit) package is intended for solving large-scale linear programming (LP), mixed integer programming (MIP), and other related problems. It is a set of routines written in ANSI C and organized in the form of a callable library. - mirrors://gnu/glpk/glpk-4.61.tar.gz + mirrors://gnu/glpk/glpk-4.65.tar.gz gmp-devel @@ -42,6 +42,13 @@ + + 2019-12-23 + 4.65 + Version bump + Idris Kalp + idriskalp@gmail.com + 2018-07-15 4.61 From 9d513569a669a72e9cc987086eae7c19f9a543d4 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Mon, 23 Dec 2019 19:37:00 +0300 Subject: [PATCH 007/160] bzip2 fix --- system/base/bzip2/actions.py | 2 ++ system/base/bzip2/pspec.xml | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/system/base/bzip2/actions.py b/system/base/bzip2/actions.py index 926e7bb5..30d60cd3 100755 --- a/system/base/bzip2/actions.py +++ b/system/base/bzip2/actions.py @@ -10,6 +10,8 @@ from pisi.actionsapi import get libversion = get.srcVERSION() +NoStrip = ["/"] + def build(): autotools.make('CC=%s AR=%s RANLIB=%s CFLAGS="%s -D_FILE_OFFSET_BITS=64 -fPIC"' % (get.CC(), get.AR(), get.RANLIB(), get.CFLAGS())) autotools.make('CFLAGS="%s -D_FILE_OFFSET_BITS=64 -fPIC" -f Makefile-libbz2_so' % get.CFLAGS()) diff --git a/system/base/bzip2/pspec.xml b/system/base/bzip2/pspec.xml index 0c55ed72..5c3654d5 100755 --- a/system/base/bzip2/pspec.xml +++ b/system/base/bzip2/pspec.xml @@ -39,6 +39,13 @@ + + 2019-12-13 + 1.0.8 + Version bump + Idris Kalp + idriskalp@gmail.com + 2019-12-13 1.0.8 From d4899e2fbec39fc401dfd92be163a66bfc202db6 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Mon, 23 Dec 2019 19:46:05 +0300 Subject: [PATCH 008/160] bzip2 revert --- system/base/bzip2/actions.py | 3 -- system/base/bzip2/pspec.xml | 85 ------------------------------------ 2 files changed, 88 deletions(-) delete mode 100755 system/base/bzip2/pspec.xml diff --git a/system/base/bzip2/actions.py b/system/base/bzip2/actions.py index 30d60cd3..904fb9af 100755 --- a/system/base/bzip2/actions.py +++ b/system/base/bzip2/actions.py @@ -10,8 +10,6 @@ from pisi.actionsapi import get libversion = get.srcVERSION() -NoStrip = ["/"] - def build(): autotools.make('CC=%s AR=%s RANLIB=%s CFLAGS="%s -D_FILE_OFFSET_BITS=64 -fPIC"' % (get.CC(), get.AR(), get.RANLIB(), get.CFLAGS())) autotools.make('CFLAGS="%s -D_FILE_OFFSET_BITS=64 -fPIC" -f Makefile-libbz2_so' % get.CFLAGS()) @@ -42,7 +40,6 @@ def install(): pisitools.dosym("libbz2.so.1", "/lib/libbz2.so") pisitools.dosym("libbz2.so.%s" % libversion, "/lib/libbz2.so.1") - pisitools.dohtml("manual.html") pisitools.dodoc("README", "CHANGES", "bzip2.txt") diff --git a/system/base/bzip2/pspec.xml b/system/base/bzip2/pspec.xml deleted file mode 100755 index 5c3654d5..00000000 --- a/system/base/bzip2/pspec.xml +++ /dev/null @@ -1,85 +0,0 @@ - - - - - bzip2 - http://www.bzip.org/ - - PisiLinux Community - admins@pisilinux.org - - BZIP2 - app:console - A high-quality data compressor - bzip2 is high-quality data compressor. It typically compresses files to within 10% to 15% of the best available techniques (the PPM family of statistical compressors), whilst being around twice as fast at compression and six times faster at decompression. - https://sourceware.org/pub/bzip2/bzip2-1.0.8.tar.gz - - bzip2-1.0.2-progress.patch - - bzip2-1.0.4-makefile-CFLAGS.patch - - bzip2-1.0.6-nselectors-upper-bound-check.patch - - - bzip2-1.0.8-saneso.patch - bzip2-1.0.8-manpath.patch - - - - - bzip2 - - /bin - /lib - /usr/lib - /usr/share/doc - /usr/share/man - /usr/include - - - - - - 2019-12-13 - 1.0.8 - Version bump - Idris Kalp - idriskalp@gmail.com - - - 2019-12-13 - 1.0.8 - Version bump - Idris Kalp - idriskalp@gmail.com - - - 2018-07-15 - 1.0.6 - Rebuild - Ertuğrul Erata - ertugrulerata@gmail.com - - - 2017-01-07 - 1.0.6 - Version bump. - Ertuğrul Erata - ertugrulerata@gmail.com - - - 2016-04-27 - 1.0.6 - Release Bump - PisiLinux Community - admin@pisilinux.org - - - 2016-02-28 - 1.0.6 - First release - Ertuğrul Erata - ertugrulerata@gmail.com - - - From b77bdee79dbde89d78510808fd52cd12598ceb65 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Mon, 23 Dec 2019 19:49:05 +0300 Subject: [PATCH 009/160] elfutils 0.178 fix --- system/devel/elfutils/actions.py | 2 +- system/devel/elfutils/pspec.xml | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/system/devel/elfutils/actions.py b/system/devel/elfutils/actions.py index 03a4ae95..b64a2383 100644 --- a/system/devel/elfutils/actions.py +++ b/system/devel/elfutils/actions.py @@ -31,7 +31,7 @@ def setup(): --enable-thread-safety \ --with-bzlib \ --with-lzma" - + #shelltools.export("LDFLAGS", "-L/lib -lbz2") autotools.configure(options) def build(): diff --git a/system/devel/elfutils/pspec.xml b/system/devel/elfutils/pspec.xml index 49ba223e..efc5f0e5 100644 --- a/system/devel/elfutils/pspec.xml +++ b/system/devel/elfutils/pspec.xml @@ -28,13 +28,14 @@ zlib bzip2 libgcc - + xz-devel + zlib-devel /usr/bin /usr/lib /usr/share/doc + /usr/share/man /usr/include From fea4096cac68136549461c2c8d70e0279b2076e7 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Wed, 25 Dec 2019 16:50:14 +0300 Subject: [PATCH 010/160] gcc 9.2.1 --- system/devel/gcc/actions.py | 1 + system/devel/gcc/pspec.xml | 19 +++++++++++++------ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/system/devel/gcc/actions.py b/system/devel/gcc/actions.py index 6310391a..e7f28ffa 100755 --- a/system/devel/gcc/actions.py +++ b/system/devel/gcc/actions.py @@ -52,6 +52,7 @@ def setup(): --enable-plugin \ --with-linker-hash-style=gnu \ --with-pkgversion="Pisi Linux" \ + --with-isl \ --disable-werror \ --enable-checking=release \ --enable-install-libiberty \ diff --git a/system/devel/gcc/pspec.xml b/system/devel/gcc/pspec.xml index 9db69210..7e0f370c 100755 --- a/system/devel/gcc/pspec.xml +++ b/system/devel/gcc/pspec.xml @@ -14,11 +14,11 @@ library The GNU Compiler Collection, includes C, C++, Objective-C and Fortran compilers The GNU Compiler Collection includes front ends for C, C++, Objective-C, Fortran, as well as libraries for these languages - http://ftp.gnu.org/gnu/gcc/gcc-9.2.0/gcc-9.2.0.tar.xz - https://ftp.gnu.org/gnu/mpfr/mpfr-4.0.2.tar.xz - http://ftp.gnu.org/pub/gnu/mpc/mpc-1.1.0.tar.gz - http://isl.gforge.inria.fr/isl-0.21.tar.bz2 - mirrors://gnu/gmp/gmp-6.1.2.tar.xz + https://sourceforge.net/projects/pisilinux/files/source/gcc-9.2.1.tar.xz + https://ftp.gnu.org/gnu/mpfr/mpfr-4.0.2.tar.xz + ftp://ftp.gnu.org/gnu/mpc/mpc-1.1.0.tar.gz + http://isl.gforge.inria.fr/isl-0.21.tar.bz2 + mirrors://gnu/gmp/gmp-6.1.2.tar.xz binutils bison @@ -30,7 +30,7 @@ sed texinfo gmp-devel - ppl + zlib-devel elfutils @@ -137,6 +137,13 @@ + + 2019-12-25 + 9.2.1 + Version bump with new toolchain. + Idris Kalp + idriskalp@gmail.com + 2019-12-13 9.2.0 From d5121f7be39f9b2d872219ee6e5e0e2a2adad399 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Wed, 25 Dec 2019 18:29:33 +0300 Subject: [PATCH 011/160] gcc 9.2.1 fix --- system/devel/gcc/actions.py | 111 +- system/devel/gcc/files/c89 | 10 - system/devel/gcc/files/c99 | 10 - system/devel/gcc/files/gSTLFilt.pl | 2062 +++++++++++++++++ .../gcc/files/gcc-4.9-isl-0.13-hack.patch | 71 + system/devel/gcc/files/gfilt | 107 + system/devel/gcc/files/pisilinux/64.patch | 21 + .../pisilinux/gcc-4.8-filename-output.patch | 17 + .../gcc_47_based-record_gcc_options.patch | 69 + system/devel/gcc/pspec.xml | 21 +- 10 files changed, 2439 insertions(+), 60 deletions(-) delete mode 100644 system/devel/gcc/files/c89 delete mode 100644 system/devel/gcc/files/c99 create mode 100755 system/devel/gcc/files/gSTLFilt.pl create mode 100755 system/devel/gcc/files/gcc-4.9-isl-0.13-hack.patch create mode 100755 system/devel/gcc/files/gfilt create mode 100755 system/devel/gcc/files/pisilinux/64.patch create mode 100755 system/devel/gcc/files/pisilinux/gcc-4.8-filename-output.patch create mode 100755 system/devel/gcc/files/pisilinux/gcc_47_based-record_gcc_options.patch diff --git a/system/devel/gcc/actions.py b/system/devel/gcc/actions.py index e7f28ffa..f55518f2 100755 --- a/system/devel/gcc/actions.py +++ b/system/devel/gcc/actions.py @@ -9,26 +9,64 @@ from pisi.actionsapi import pisitools from pisi.actionsapi import shelltools from pisi.actionsapi import get +import os -shelltools.export('CFLAGS', get.CFLAGS().replace('-pipe', '').replace(' -g ', ' -g3 ') + ' -Wall') -shelltools.export('CXXFLAGS', get.CXXFLAGS().replace('-pipe', '').replace(' -g ', ' -g3 ') + ' -Wall') +snapshot = False +if snapshot: + verMajor, verMinor = get.srcVERSION().replace("pre", "").split("_", 1) + WorkDir = "gcc-4.7-%s" % verMinor +else: + verMajor = get.srcVERSION() + +arch = get.ARCH().replace("x86_64", "x86-64") + +#opt_unwind = "--with-system-libunwind" if get.ARCH() == "x86_64" else "--without-system-libunwind" +opt_arch = "--with-arch_32=i686" if get.ARCH() == "x86_64" else "--with-arch=i686" +opt_multilib = "--enable-multilib" if get.ARCH() == "x86_64" else "" + +# WARNING: even -fomit-frame-pointer may break the build, stack protector, fortify source etc. are off limits +cflags = "-O2 -g" + + +def removePisiLinuxSection(_dir): + for root, dirs, files in os.walk(_dir): + for name in files: + # FIXME: should we do this only on nonshared or all ? + # if ("crt" in name and name.endswith(".o")) or name.endswith("nonshared.a"): + if ("crt" in name and name.endswith(".o")) or name.endswith(".a"): + i = os.path.join(root, name) + shelltools.system('objcopy -R ".comment.PISILINUX.OPTs" -R ".note.gnu.build-id" %s' % i) + +def exportFlags(): + # we set real flags with new configure settings, these are just safe optimizations + shelltools.export("CFLAGS", cflags) + shelltools.export("CXXFLAGS", cflags) + # shelltools.export("LDFLAGS", "") + + # FIXME: this may not be necessary for biarch + shelltools.export("CC", "gcc") + shelltools.export("CXX", "g++") + shelltools.export("LC_ALL", "en_US.UTF-8") def setup(): + exportFlags() + # Maintainer mode off, do not force recreation of generated files + #shelltools.system("contrib/gcc_update --touch") pisitools.dosed("gcc/Makefile.in", "\.\/fixinc\.sh", "-c true") - pisitools.dosed("gcc/config/i386/t-linux64", "m64=../lib64", "m64=../lib") pisitools.dosed("gcc/configure", "^(ac_cpp='\$CPP\s\$CPPFLAGS)", r"\1 -O2") pisitools.dosed("libiberty/configure", "^(ac_cpp='\$CPP\s\$CPPFLAGS)", r"\1 -O2") - + shelltools.move("isl-0.21", "isl") shelltools.move("mpfr-4.0.2", "mpfr") shelltools.move("mpc-1.1.0", "mpc") shelltools.move("gmp-6.1.2", "gmp") + + shelltools.cd("../") + shelltools.makedirs("build") + shelltools.cd("build") - shelltools.makedirs("../build") - shelltools.cd("../build") - - shelltools.system('../gcc-%s/configure \ + shelltools.system('.././gcc-%s/configure \ --prefix=/usr \ --bindir=/usr/bin \ --libdir=/usr/lib \ @@ -36,8 +74,9 @@ def setup(): --includedir=/usr/include \ --mandir=/usr/share/man \ --infodir=/usr/share/info \ - --with-bugurl=https://pisilinux.org/bugs \ + --with-bugurl=http://bugs.pisilinux.org \ --enable-languages=c,c++,fortran,lto,objc,obj-c++ \ + --disable-libgcj \ --enable-shared \ --enable-threads=posix \ --with-system-zlib \ @@ -48,47 +87,61 @@ def setup(): --disable-libssp \ --enable-gnu-unique-object \ --enable-linker-build-id \ + --enable-cloog-backend=isl \ + --disable-cloog-version-check \ --enable-lto \ --enable-plugin \ --with-linker-hash-style=gnu \ --with-pkgversion="Pisi Linux" \ - --with-isl \ --disable-werror \ --enable-checking=release \ - --enable-install-libiberty \ - --enable-gnu-indirect-function \ - --enable-multilib \ - --enable-default-pie \ - --enable-default-ssp \ - --enable-cet' % get.srcVERSION()) - + --build=%s \ + %s \ + %s ' % ( verMajor , get.HOST(), opt_arch, opt_multilib)) def build(): + exportFlags() + shelltools.cd("../build") - autotools.make() - - -def check(): - shelltools.cd("../build") - autotools.make("-k check || true") - shelltools.system("%s/gcc/contrib/test_summary" % get.srcDIR()) - + autotools.make('BOOT_CFLAGS="%s" profiledbootstrap' % cflags) def install(): shelltools.cd("../build") autotools.rawInstall("DESTDIR=%s" % get.installDIR()) + #autotools.install() + + for header in ["limits.h","syslimits.h"]: + pisitools.insinto("/usr/lib/gcc/%s/%s/include" % (get.HOST(), verMajor) , "gcc/include-fixed/%s" % header) # Not needed pisitools.removeDir("/usr/lib/gcc/*/*/include-fixed") + pisitools.removeDir("/usr/lib/gcc/*/*/install-tools") + + # This one comes with binutils + #pisitools.remove("/usr/lib*/libiberty.a") # cc symlink - pisitools.dosym("/usr/bin/gcc", "/usr/bin/cc") + pisitools.dosym("/usr/bin/gcc" , "/usr/bin/cc") # /lib/cpp symlink for legacy X11 stuff pisitools.dosym("/usr/bin/cpp", "/lib/cpp") + + pisitools.dosym("/usr/bin/x86_64-pc-linux-gnu-gcc-ar", "/usr/bin/x86_64-pc-linux-gnu-ar") - # TODO: Add liblto_plugin.so link to necessary place. + # Remove our options section from crt stuff + removePisiLinuxSection("%s/usr/lib/" % get.installDIR()) + if get.ARCH() == "x86_64": + removePisiLinuxSection("%s/usr/lib32/" % get.installDIR()) - gdbpy_files = shelltools.ls("%s/usr/lib/*gdb.py" % get.installDIR()) + + # autoload gdb pretty printers + gdbpy_dir = "/usr/share/gdb/auto-load/usr/lib/" + pisitools.dodir(gdbpy_dir) + + gdbpy_files = shelltools.ls("%s/usr/lib/libstdc++*gdb.py*" % get.installDIR()) for i in gdbpy_files: - pisitools.domove("/usr/lib/%s" % shelltools.baseName(i), "/usr/share/gdb/auto-load/usr/lib") + pisitools.domove("/usr/lib/%s" % shelltools.baseName(i), gdbpy_dir) + + if arch == "x86-64": + pisitools.remove("/usr/lib32/libstdc++*gdb.py*") + diff --git a/system/devel/gcc/files/c89 b/system/devel/gcc/files/c89 deleted file mode 100644 index 53eebdae..00000000 --- a/system/devel/gcc/files/c89 +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh -fl="-std=c89" -for opt; do - case "$opt" in - -ansi|-std=c89|-std=iso9899:1990) fl="";; - -std=*) echo "`basename $0` called with non ANSI/ISO C option $opt" >&2 - exit 1;; - esac -done -exec gcc $fl ${1+"$@"} \ No newline at end of file diff --git a/system/devel/gcc/files/c99 b/system/devel/gcc/files/c99 deleted file mode 100644 index 1ca2079c..00000000 --- a/system/devel/gcc/files/c99 +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh -fl="-std=c99" -for opt; do - case "$opt" in - -std=c99|-std=iso9899:1999) fl="";; - -std=*) echo "`basename $0` called with non ISO C99 option $opt" >&2 - exit 1;; - esac -done -exec gcc $fl ${1+"$@"} \ No newline at end of file diff --git a/system/devel/gcc/files/gSTLFilt.pl b/system/devel/gcc/files/gSTLFilt.pl new file mode 100755 index 00000000..5cc6a6c8 --- /dev/null +++ b/system/devel/gcc/files/gSTLFilt.pl @@ -0,0 +1,2062 @@ +################################################################################################################ +# gSTLFilt.pl: BD Software STL Error Message Decryptor (a Perl script) +# This version supports the gcc 2/3/4 C++ compiler/library +# It was tested under: +# DJGPP 2.95.2 +# MinGW gcc 2.95.2, 3.2.3, 3.4.5, 4.1.1 +# TDM gcc 4.2.2 +# + +$STLFilt_ID = "BD Software STL Message Decryptor v3.10 for gcc 2/3/4"; + +# +# (c) Copyright Leor Zolman 2002-2008. Permission to copy, use, modify, sell and +# distribute this software is granted provided this copyright notice appears +# in all copies. This software is provided "as is" without express or implied +# warranty, and with no claim as to its suitability for any purpose. +# +################################################################################################################# +# Visit www.bdsoft.com for information about BD Software's on-site training seminars # +# in C, C++, STL, Perl, Unix Fundamentals and Korn Shell Programming # +################################################################################################################# +# +# For quick installation instructions for the STL Error Decryptor, see QUICKSTART.txt. +# For manifest and other general information, see README.txt +# +# (Note: hard tab setting for this source file is: 4) +# +# Purpose: Transform STL template-based typenames from gcc error messages +# into a minimal, *readable* format. We might lose some details... +# but retain our sanity! +# +# This script may be used in several different ways: +# 1) With the "Proxy C++" program, C++.EXE (from the command-line or from within Dev-CPP) +# 2) With a batch/shell script driver for command-line use... +# For Windows: The companion batch file GFILT.BAT is provided as a sample driver for this script +# For Unix/Linux/OS X: The companion shell script "gfilt" is provided as a sample driver for +# this script, allowing arbitrary intermixing of compiler and Decryptor options +# on the command line. +# +# Acknowledgements: +# Scott Meyers taught his "Effective STL" seminar, where the project began. +# Thomas Becker wrote and helps me maintain the Win32 piping code used throughout both C++.CPP and +# the Perl scripts, keeping everyone talking despite all the curves thrown him (so far) by +# ActiveState and Microsoft. THANK YOU, Thomas! +# David Abrahams designed the long-typename-wrapping algorithm and continues to contribute actively +# to its evolution. +# David Smallberg came up with the "Proxy compiler" idea (but blame me for the name). +# +# For the complete list of folks whose feedback and de-bugging help contributed to this +# package, and also for the list of programming courses BD Software offers, see README.txt. +# +# +################################################################################################################# +# +# Script Options +# -------------- +# +# Command line options are case insensitive, and may be preceded by either '-' or '/'. +# The Proxy C++, if being used, supplies many of these options as per settings in the +# Proxy-gcc.INI configuration file. +# +# Note that some of the Decryptor's behavior is controlled via command-line options, +# while other behavior may only be configured via hard-wired variable settings. Please +# examine the entire "User-Configurable Settings" section below to become familiar with +# all the customizable features. +# +# General options: +# +# -iter:x Set iterator policy to x, where x is s[short], m[edium] or l[ong] +# (See the assignments of $def_iter_policy and $newiter below for details) +# +# -cand:x Set "candidates" policy to x, where x is L[ong], M[edium] or S[hort] +# (See the assignment of $def_cand_policy below for details) +# +# -hdr:x Set STL header policy to x or nn, where x is L[ong], M[edium], or S[hort], +# -hdr:nn or nn is the # of errors to show in a cluster +# -hdr:LD Dave Abrahams re-ordering mode 1 (see below) +# -hdr:LD1 save as above +# -hdr:LD2 Dave Abrahams re-ordering mode 2 +# (See the assignment of $def_hdr_policy below for details) +# +# -with:x Set "with clause" substitution policy to x, where x is L[ong] or S[hort] +# (See the assignment of $def_with_policy below for details) +# +# -path:x Set "show long pathnames" policy to x, where x is l[ong] or s[hort] +# (See the assignment of $def_path_policy below for details) +# +# -showback:x Set backtrace policy: Y (default) or N (suppress all backtrace lines) +# +# -width:nn Set output line width (break message lines at this column, or 0 for NO wrapping) +# +# -lognative Log all native messages to NativeLog.txt (for de-bugging) +# +# -banner:x Show Decryptor banner line: Y (default) or N +# +# -nullarg:xxx Add xxx to the list of "null argument" typenames that get stripped from the +# trailing portion of template argument lists. (See also the initializations of +# variable @nullargs). xxx must be fully qualified (including namespace). +# +# if xxx is 'clear', the null argument list is emptied; subsequent -nullarg +# specification appearing on the command line will work, but not the defaults +# as per the initialization of @nullargs below (unless they're re-specified +# using the -nullarg option later on the commmad line.) +# +# Options supporting long typename wrapping: +# +# (Note: If output width is set to 0, line wrapping is disabled and the +# following options have NO EFFECT) +# +# -break:x Break algorithm: D[ave Abrahams] (default) or P[lain] +# The "Dave" option wraps long complex typenames in a way that +# makes it easier to see parameter lists at various nesting depths. +# +# -cbreak:x Comma break: B = break before commas (default), A = break after +# [applies only in -break:D mode] +# +# -closewrap:x Wrap before unmatched closing delimiters: Y (default) or N +# [applies only in -break:D mode] +# +# -meta:x Configure for metaprogramming [Y] or vanilla wrapping [N] as follows: +# +# -meta:y (or just -meta) forces -break:D, and forces -cbreak and +# -closewrap options according to values specified in the $meta_y_cbreak +# and $meta_y_closewrap variable initializations, respectively. +# +# -meta:n forces -break:P (-cbreak and -closewrap don't apply) +# +# In either case, if the output width hasn't yet been set to a non-zero +# value, it is set to 80 (choosing a wrapping flavor makes no sense +# with wrapping disabled); this may be overridden by a subsequent -width +# option. +# +# Note: If no -meta option is present, the default values for -break, +# -cbreak and -closewrap are determined by the user-configurable +# settings of $break_algorithm, $comma_wrap and $close_wrap below. +# +# Note also that -meta is not configurable from the INI files, because +# it is intended as a command-line "override" mechanism. The individual +# settings of -break, -cbreak and -closewrap, however, *are* (and apply +# only when the /meta option is not used.) +# +################################################################################################################# +# User-configurable settings (use UPPER CASE ONLY for all alphabetics here (except $newiter): +# + #################################################################################### + # The following twelve settings may be overridden by options on + # the command line (either explicitly, or when conveyed by the + # Proxy C++ from settings in Proxy-gcc.INI): + + # default iterator policy (/iter:x option): +$def_iter_policy = 'L'; # 'L' (Long): NEVER remove iterator type name qualification + # 'M' (Medium): USUALLY remove iterator type name qualification + # leave intact when iter type may be significant + # to the diagnostic + # 'S' (Short): ALWAYS remove iterator type name qualification + +$def_cand_policy = 'L'; # default candidate policy (/cand:x option): + # 'L' (long): Retain candidate list (same as: 'Y') + # 'M' (medium): Suppress candidates, but tell how many were suppressed + # 'S' (short): completely ignore candidate list (same as: 'N') + +$def_hdr_policy = 'LD2'; # default standard header messages policy (/hdr:x option): + # 'L' (long): Retain all messages referring to standard header files (same as 'Y') + # 'M' (medium): Retain only the first $headers_to_show messages in each cluster + # 'S' (short): Discard all messages referring to standard header files (same as 'N') + # 'LD[1]' (long, Dave Abrahams re-ordering mode 1): + # actual error msg moves to front of instantiation backtrace + # 'LD2' (long, Dave Abrahams re-ordering mode 2): + # as above, with trigger line duplicated before the backtrace + +$def_with_policy = 'S'; # default "with clause" substitution policy (/with:x option): + # 'L' (long): Do NOT substitute in template parameters in "with" clauses + # 'S' (short): Do substitute template parameters in "with" clauses + +$def_path_policy = 'S'; # default long path policy (/path:x option): + # 'L' (long): Retain entire pathname in all cases (same as 'Y') + # 'S' (short): Discard all except base name from pathnames (same as 'N') + # [NOTE: Use L if you rely upon your IDE to locate errors in source files] + +$def_hdrs_to_show = 1; # Default number of header messages to show for 'M' header policy + +$banner = 'N'; # Show banner with Decryptor ID by default (/banner option) + +$break_algorithm = 'D'; # P[lain] or D[ave Abrahams] line-breaking algorithm (/break:x option) + # (Note: line-breaking of any kind happens only if $output_width is non-zero) + +$comma_wrap = 'B'; # wrap lines B[efore] or A[fter] commas. (/cbreak:x option) + # (Applies in Dave mode only.) + +$close_wrap = 'Y'; # Force a break before close delimiters + # whose open is not on the same line (/closewrap:x option) + # (Applies in Dave mode only.) + +$output_width = 80; # wrap at 80 columns by default (/width:nn option) + +$show_backtraces = 'Y'; # show (Y) or suppress (N) backtrace messages (/showback:x option) + + + ##################################################################################### + # The remaining settings are controlled strictly by their assigned + # value below (no corresponding command-line options offered): + +$newiter = 'iter'; # ('iter' or 'IT' or...) shorten the word "iterator" to this + # Note: /iter:L forces $newiter to be 'iterator' (no filtering) + +$tabsize = 4; # number of chars to incrementally indent lines + +$advise_re_policy_opts = 1; # remind folks they can use /hdr:L and /cand:L to see more message details + +$nix_only_once = 1; # suppress "undefined identifiers shown only once..." messages + +$reformat_linenumbers = 0; # 1 to reformat lines numbers to LZ's preferred style (may conflict with + # cursor-placement mechanisms in some editors/IDE's) + +$smush_amps_and_stars = 0; # 1 leaves asterisks/ampersands adjacent to preceding identifiers; + # 0 inserts a space between + +$space_after_commas = 0; # 1 to force spaces after commas, 0 not to + +$meta_y_cbreak = 'B'; # /meta:y forces this value for cbreak +$meta_y_closewrap = 'Y'; # /meta:y forces this values for closewrap + +$wrap_own_msgs = 0; # wrap STL Decryptor messages to same output width + # as errors (1) or don't (0) + +$keep_stdns = 0; # 0 to remove "std::" and related prefixes, 1 to retain them. + # NOTE: if set to 1, STL-related filtering will *not* work (for now). This option + # is designed for use in conjunction with /break:D to retain maximum detail in + # metaprogramming-style messages, rather than for use with STL library messages. + +$show_internal_err = 1; # If set to 0, suppresses delimiter mismatch errors. Please leave at 1, + # and contact me as per the emitted instructions in the case of an + # internal error. + + # default list of names of trailing type names to be stripped from the end of + # argument lists (the -nullarg:xxx command line option allows additional names to + # be added to the list, or for the these default ones to be cleared out): + +@nullargs = qw(boost::tuples::null_type mpl_::void_ mpl_::na boost::detail::variant::void\d+); + # (Designed primarly for use with boost libraries tuple, mpl, etc...) + +#@nullargs = qw(); # to totally disable the null args stripping feature by default, uncomment this + # line and comment out the initialization of @nullargs above. + + +# +# END of user-configurable settings (change anything below here AT YOUR OWN RISK.) +################################################################################################################# + + +$| = 1; # force output buffer flush after every line + +$iter_policy = $def_iter_policy; # default iterator policy + +$dave_move = 0; # true for /hdr:LD1 +$dave_rep = 0; # true for /hdr:LD2 +$in_backtrace = 0; # not processing a backtrace right now + +if ("\u$def_hdr_policy" =~ 'LD[12]?') +{ + $dave_move = 1; + $dave_rep = 0; + $dave_rep = 1 if "\u$def_hdr_policy" eq 'LD2'; + $def_hdr_policy = 'L'; +} + +$header_policy = $def_hdr_policy; # default std. header message policy +$with_policy = $def_with_policy; # default "with clause" substitution policy +$headers_to_show = $def_hdrs_to_show; # number of headers to show for 'M' header policy +$candidate_policy = $def_cand_policy; # default candidate policy (gcc only) +$pathname_policy = $def_path_policy; # default pathname policy (gcc only) + +$lognative = 0; # by default, not logging native messages +$suppressed_headers = 0; # true when we've suppressed at least one stdlib header +$suppressed_candidates = 0; # true when we've suppressed at least one template candidate + +$pdbg = 0; # true to show print trace +$wrapdbg = 0; # de-bug wrap loop +$movedbg = 0; # de-bug Dave mode reordering +$delimdbg = 0; # de-bug /wrap:D mode delimiter parsing +$optdbg = 0; # show value of all command-line modfiable options +$choked = 0; # haven't choked yet with an internal error + + +sub scanback; +sub println; +sub print2; +sub break_and_print; +sub break_and_print_plain; +sub break_and_println_plain; +sub break_and_print_fragment; +sub lognative_header; +sub showkey; + + +# Little hack to avoid "Exiting subroutine via next" warnings on internal error: +sub NoWarn +{ + $msg = shift (@_); + print "$msg" if $msg !~ /Exiting subroutine via next/; +} + +$SIG{__WARN__} = "NoWarn"; + +@save_args = @ARGV; # lognative_header uses this + +while (@ARGV) # process command-line options +{ + if ($ARGV[0] =~ /^[\/-]iter:([SML])[A-Z]*$/i) # allow command-line iterator policy + { # specification of form: /iter:x + print "$ARGV[0] " if $optdbg; + $iter_policy = "\u$1"; + $newiter = 'iterator' if $iter_policy eq 'L'; + shift; + next; + } + + if ($ARGV[0] =~ /^[\/-]cand:([YNSML])[A-Z]*$/i) # allow candidate policy + { # specification of form: /cand:x + print "$ARGV[0] " if $optdbg; + $candidate_policy = "\u$1"; + $candidate_policy =~ tr/NY/SL/; + shift; + next; + } + + if ($ARGV[0] =~ /^[\/-]with:([YNSL])[A-Z]*$/i) # allow with clause policy + { # specification of form: /with:x + print "$ARGV[0] " if $optdbg; + $with_policy = "\u$1"; + $with_policy =~ tr/NY/LS/; + shift; + next; + } + + if ($ARGV[0] =~ /^[\/-]hdr:L(D[12]?)$/i) # detect special "Dave Abrahams" header policy + { # specifications of form: /hdr:LD /hdr:LD1 /hdr:LD2 + print "$ARGV[0] " if $optdbg; + $header_policy = "L"; + $dave_move = 1; # moving error line to before the trace + $dave_rep = 0; + $dave_rep = 1 if "\u$1" eq "D2"; # replicating trigger line + shift; + next; + } + + if ($ARGV[0] =~ /^[\/-]hdr:([YNSML])[a-ce-z]*$/i) # allow standard header policy + { # specification of form: /hdr:x + print "$ARGV[0] " if $optdbg; + $header_policy = "\u$1"; + $header_policy =~ tr/NY/SL/; + $headers_to_show = 0 if $header_policy eq 'S'; + $dave_move = 0; + $dave_rep = 0; + shift; + next; + } + + if ($ARGV[0] =~ /^[\/-]hdr:(\d+)/i) # allow standard header policy + { # specification of form: /hdr:nn + print "$ARGV[0] " if $optdbg; + $header_policy = 'M'; + $headers_to_show = $1; + shift; + next; + } + + if ($ARGV[0] =~ /^[\/-]path:([SL])[A-Z]*$/i) # allow pathname policy + { # specification of form: /path:x + print "$ARGV[0] " if $optdbg; + $pathname_policy = "\u$1"; + $pathname_policy =~ tr/NY/SL/; + shift; + next; + } + + if ($ARGV[0] =~ /^[\/-]banner:?([YN]?)[A-Z]*$/i) # banner:Y or N + { # (just "/banner" means Y) + print "$ARGV[0] " if $optdbg; + $banner = "\u$1"; + $banner = 'Y' if $banner eq ""; + shift; + next; + } + + if ($ARGV[0] =~ /^[\/-]showback:?([YN]?)[A-Z]*$/i) # showback:Y or N + { # (just "/showback" means Y) + print "$ARGV[0] " if $optdbg; + $show_backtraces = "\u$1"; + $show_backtraces = 'Y' if $show_backtraces eq ""; + shift; + next; + } + + if ($ARGV[0] =~ /^[\/-]width:(\d+)/i) # allow line output width spec + { # of form: /width:n + print "$ARGV[0] " if $optdbg; + $output_width = $1; + shift; + next; + } + + if ($ARGV[0] =~ /^[\/-]break:([DP])[A-Z]*$/i) # break: D or P + { + print "$ARGV[0] " if $optdbg; + $break_algorithm = "\u$1"; + shift; + next; + } + + if ($ARGV[0] =~ /^[\/-]cbreak:([AB])[A-Z]*$/i) # comma break: B or A + { + print "$ARGV[0] " if $optdbg; + $comma_wrap = "\u$1"; + shift; + next; + } + + if ($ARGV[0] =~ /^[\/-]closewrap:?([YN]?)[A-Z]*$/i) # closewrap:Y or N + { # (just "/closewrap" means Y) + print "$ARGV[0] " if $optdbg; + $close_wrap = "\u$1"; + $close_wrap = 'Y' if $close_wrap eq ""; + shift; + next; + } + + if ($ARGV[0] =~ /^[\/-]nullarg:(.*)/i) # add to list of "null arg" identifiers + { + print "$ARGV[0] " if $optdbg; + if ($1 =~ /^clear$/i) + { + @nullargs = (); # "clear" means clear out null arg list + } + else + { + push @nullargs, $1; # any other name is appened to list + } + shift; + next; + } + + + if ($ARGV[0] =~ /^[\/-]meta:?([YN]?)[A-Z]*$/i) # meta:Y or N + { # (just "/meta" means Y) + if ("\u$1" =~ /^N/) + { + $break_algorithm = 'P'; + } + else + { + $break_algorithm = 'D'; + $comma_wrap = $meta_y_cbreak; + $close_wrap = $meta_y_closewrap; + } + $output_width = 80 if $output_width == 0; + shift; + next; + } + + if ($ARGV[0] =~ /^[\/-]lognative/i) # allow log native msgs option + { # of form: /lognative + print "$ARGV[0] " if $optdbg; + $lognative = 1; + shift; + next; + } + + println "Warning: unrecognized gSTLFilt2.pl command line option: $ARGV[0]\n"; + shift; +} + +# List of "standard" header files names: + +@keywords = qw(algo algorithm algobase bitset cassert cctype cerrno cfloat ciso646 + climits clocale cmath complex csetjmp csignal cstdarg stdarg cstddef stddef + cstdio stdio cstdlib stdlib cstring ctime time cwchar cwtype cxxabi deque editbuf exception exception_defines + fstream fstream.h functional hashtable hash_map hash_set heap iomanip + ios iosfwd iostream iostream istream iterator limits list locale + map memory new new numeric ostream queue rope set slist + pair sstream stack stdexcept streambuf streambuf_iterator string + strstream strstream stream_iterator typeinfo utility valarray vector + basic_ios basic_string boost_concept_check char_traits codecvt concept_check + cpp_type_traits fpos functexcept generic_shadow gslice gslice_array indirect_array + ios_base localefwd stringfwd locale_facets mask_array pthread_allocimpl slice slice_array + type_traits valarray_array valarray_meta bastring complext fcomplex ldcomplex + std_valarray straits strfile tempbuf alloc floatio math + array random regex type_traits tuple unordered_map unordered_set + cfenv cinttypes cstdbool cstdint ctgmath + ); + + +# Put 'em in a hash for rapid searching: + +for (@keywords) +{ + $keywords{$_}++; +} + + +print "\n" if $optdbg; +$tab = " " x $tabsize; + +print "\n\n" . ("=" x $output_width) . "\n\n" if $pdbg or $wrapdbg or $movedbg or $delimdbg; + +# +# This sections builds the $t ("type") regex from the ground up. +# After it is built, the component variables (except for $id) are not used again. +# + +$sid = '\b[a-zA-Z_]\w*'; # pattern for a simple identifier or keyword +$id = "(?:$sid\:\:)*$sid"; # simple id preceded by an optional namespace qualifier +$p = '(?: ?\*)*'; # suffix for "ptr", "ptr to ptr", "ptr to ptr to ptr", ad nauseum. +$idp = "(?:$id )*$id ?$p ?"; # one or more identifiers/keywords with perhaps some *'s after + + # simple id or basic template spec +$cid = "(?:$idp(?: ?const ?\\*? ?)?|$id<$idp(?: ?const ?\\*? ?)?(?:, ?$idp(?: ?const ?\\*? ?)?)*>$p) ?"; + + # a cid or template type with 1+ cid's as parameters +$t = "(?:$cid|$id<$cid(?:, ?$cid)*>$p|$id<$id<$cid>$p(?:, ?$id<$cid>$p)* ?>$p)"; + +println "$STLFilt_ID" if ($banner eq 'Y'); + +showkey $output_width if $pdbg; + +lognative_header if $lognative; + +$doing_candidates = 0; +$doing_stl_headers = 0; +$save_filename = ''; +$this_is_gcc3 = 0; +$saw_instantiated = 0; + +# +# Data structures supporting the Dave Abrahams mode line break algorithm: +# + +@open_delims = ('(', '{', '<'); +@close_delims= (')', '}', '>'); + +for (@open_delims) # list of "open" delimiters +{ + $open_delims{$_}++; +} + +for (@close_delims) # list of "close" delimiters +{ + $close_delims{$_}++; +} + +# create "opposites" table, mapping each delimiter to its complement: +for ($i = 0; $i < @open_delims; $i++) +{ + $opps{$open_delims[$i]} = $close_delims[$i]; + $opps{$close_delims[$i]} = $open_delims[$i]; +} + + +# The following state varaibles are used for Dave-mode line re-ordering: + +$pushed_back_line = ""; +$displaying_error_msg = 0; # true if displaying actual error message of backtrace in re-order mode +$last_within_context = ""; # save "within this context" lines to detect duplicates and strip them + +# +# NOTE: We cannot use a main loop of the form +# +# while( <> ) +# +# because of ActivePerl's way of handling input from Win32 pipes +# connected to STDIN. (EOF is treated like an ordinary character. +# In particular, it doesn't get read unless FOLLOWED by a newline. +# Yeah, great, EOF followed by a newline.) +# + +MAIN_LOOP: +while ( 1 ) +{ + if ($pushed_back_line ne "") + { + $_ = $pushed_back_line; + $pushed_back_line = ""; + } + else + { + # Read the first char of the next line to see if it equals EOF. + # If we're the ones who write the code that writes to STDIN, + # we can guarantee that EOF is always preceded by a newline. + # + # We must do this in a loop, because if the next line is empty, + # then we have not read the first char of the next line, but + # the entire next line. + # + $newlines = ""; + + CHECK_FOR_EOF_LOOP: + while( 1 ) + { + # Read one char. + $nextchar = ""; + $numRead = read STDIN, $nextchar, 1; + + # Normally, perl will return an undefined value from read if the next + # character was EOF. ActivePerl will simply read the EOF like any other + # character. Since we know that one of the newlines was ours, we print one + # less newline than we have seen. NOTE: It is possible that we have seen no + # newline at all. This happens if the CL output has no newline at the end. + # In that case, we have appended a newline, and that's good. + + if (1 != $numRead or $nextchar eq "\032") + { + if ($newlines ne "") + { + chop $newlines; + print $newlines; + } + last MAIN_LOOP; + } + else # Else, if we have read a newline, we store it for later output and continue reading. + { + if ($nextchar eq "\n") + { + $newlines = $newlines . "\n"; + } + + # Else, if we have read something that's neither a newline nor EOF, we print + # the accumulated newlines and proceed to read and process the next line. + + else + { + print $newlines; + last CHECK_FOR_EOF_LOOP; + } + } + } + + # Read the next line, prepend the first char, which has already been read. + $_ = ; + + # If the read failed, the pipe must have broken. + if (!defined $_) + { + print "\nSTL Decryptor: Input stream terminated abnormally (broken pipe?)\n"; + last MAIN_LOOP; + } + + $_ = $nextchar . $_; + } + + +# +# Done with special EOF-processing-enabled input handling. +# Now process the line (in $_): +# + + $save_line_for_dbg = $_; # in case of a panic error + + print LOGNATIVE $_ if $lognative; # log native message if requested + + print "DBG: Next line to be processed:\n$_\n" if $movedbg; + + s/{anonymous}/anonymous/g; # massage anonymous namespace specs to qualify as identifiers + s//unnamed/g; + + $obj = 0; # by default, not object file message + $obj = 1 if /\.o(bj)?\b/i or /\.a\b/i; # set $obj if an object or lib file + + if ($obj) + { + print "************** PRINT DBG 1 **************\n" if $pdbg; + if (/(.*\):\s*)([\S].*)/) # look for possibly-mangled name followed by additional text... + { + $before = $1; + $after = "$2\n"; + break_and_print_plain "$before"; # print the part containing possible mangled-name-from-hell + $_ = $after; # and process the rest normally. + } + else + { + break_and_print_plain "$_"; # print entire line containing possible mangled-name-from-hell + next; + } + } + + next if $show_backtraces eq 'N' and (/\binstantiated from\b/ or /^\s*from /); + +# get rid of useless messages from gcc + + if ($nix_only_once) + { + next if /\(Each undeclared identifier is reported only once/; + next if /for each function it appears in\.\)/; + } + + $has_lineno = 0; + $has_lineno = 1 if /^(.*\.(cpp|cxx|cc|h|hpp|tcc)\:(\d+\:) ?)/; + + # strip prefix of form: + if (/^(.*\.(cpp|cxx|cc|h|hpp|tcc)\:(\d+\:)? ?)/ or # "pathname.h:n: " or + (/^((?:[a-zA-Z]\:)?[^:]*\b(\w+)(\.\w+)?\:(\d+\:)? ?)/ and exists $keywords{$2})) # std header + { + $prefix = "$1"; # and restore it later + s/^\Q$prefix//; # remove during filtering + } + else + { + $prefix = ""; # null prefix if none detected + } + + +# test if we're looking at a message referring to a standard header +# (note that the candidate policy trumps the header policy): + + $needs_stripping = ($prefix =~ /stl_[a-zA-Z]\w*\.h:/i or + ($prefix =~ m#([/\\])include\1(?:.*\1)*(\w+)# and exists $keywords{$2})); + + $this_is_an_stl_header = ($needs_stripping and + !$doing_candidates and ($_ !~ /candidates are\:/)); + +# strip message referring to standard headers if header_policy is S: + + if ($this_is_an_stl_header) + { + ++$doing_stl_headers; + next if $header_policy eq 'S'; # skip all headers if using 'S' header policy + # skip all but first $headers_to_show if policy is 'M' + next if $doing_stl_headers > $headers_to_show and $header_policy eq 'M'; + } + + # if 'M' or 'S' header policy, tell how many skipped: + if (!$this_is_an_stl_header and ($doing_stl_headers > ($headers_to_show)) and $header_policy ne 'L') + { + println " [STL Decryptor: Suppressed " . + ($doing_stl_headers - $headers_to_show) . + ($header_policy eq 'M' ? " more " : " ") . + "STL standard header message" . + (($doing_stl_headers - $headers_to_show) != 1 ? "s" : "") . "]"; + $suppressed_headers = 1; + } + + $doing_stl_headers = 0 if !$this_is_an_stl_header; + + +# gcc: strip pathname from deadly-long stdlib file paths as per $pathname_policy: + + if ($pathname_policy eq 'S' and $needs_stripping) + { + $preprefix = ""; # special case: preserve leading " from " phrase + if ($prefix =~ /^(.* from )/) + { + $preprefix = $1; + $prefix =~ s/^.* from //; + } + + if ($prefix =~ /$sid\.(h|hpp|tcc|cpp|cxx|cc)\:/) + { # case where there's an extension + $prefix =~ s/.*($sid\.(h|hpp|tcc|cpp|cxx|cc))\:/$preprefix$1:/; + } + else + { # case where there's (perhaps) no extension + $prefix =~ s/^(?:[a-zA-Z]\:)?[^:]*\b(\w+(\.\w+)?\:(\d+\:)? ?)/$preprefix$1/; + } + } + +# save filename, if any + + if ($prefix =~ /^($sid\.(h|hpp|tcc))\:/) + { + $filename = $1; # save file basename + } + else + { + $filename = 'No filename'; + } + + if ($candidate_policy ne 'L' and /candidates are:/) + { + $doing_candidates++; + $save_filename = $filename; + $suppressed_candidates = 1; + next; + } + + $this_is_gcc3 = 1 if $doing_candidates and / /; + + # skip all messages referring to "candidates" (if req'd): + if ($candidate_policy ne 'L' and $doing_candidates and + ($this_is_gcc3 and / /) or (!$this_is_gcc3 and $filename eq $save_filename)) + { + $doing_candidates++; + next; + } + + if (((!$this_is_gcc3 and $filename ne $save_filename) or $this_is_gcc3) and $doing_candidates) + { + println " [STL Decryptor: Suppressed $doing_candidates 'candidate' line" . + ($doing_candidates != 1 ? "s" : "") . "]" + if $candidate_policy eq 'M'; + $doing_candidates = 0; + } + + s/no matching function for call to/No match for/; + + ################################################################################################### + # Do 'with' clause processing, transforming into plain-Jane type specifications: + + if ($with_policy eq 'S') + { + # temporary eliminate [##] sequences: + @dims = (); + $dim_counter = 1; + + while (/(\[(\d*)])/) + { + $old = $1; + $sub = $2; + s/\Q$old/zzz-$dim_counter-$sub-zzz/; + push @dims, $sub; + $dim_counter++; + } + + while (/(.*)( \[with ([^]]*)])/) + { + $text = $1; # the original message text with placeholder names + $keyclause = $2; # the "with [...]" clause + $keylist = $3; # just the list of key/value mappings + + chop $keylist if substr($keylist, -1, 1) eq ']'; + + %map = (); # clear the hash of key/value pairs + + while($keylist =~ /(\w+) ?=/) + { + $key = $1; + $pos = $start = index($keylist, $key) + length($key) + 1; + if (substr($keylist, $pos, 1) eq '=') + { $pos++; $start++; } + if (substr($keylist, $pos, 1) eq ' ') + { $pos++; $start++; } + + + $depth = 0; # count <'s and >'s + $previous = ' '; + while ($pos <= length($keylist)) + { + $next = substr ($keylist, $pos++, 1); + last if $depth == 0 and ($next eq ',' or ($next eq ']' and $previous ne '[')); # ignore "[]" + $previous = $next; + $depth++ if $next =~ /[<\[\(]/; + $depth-- if $next =~ /[>\]\)]/; + } + + $value = substr($keylist, $start, $pos - $start - 1); + $map{$key} = $value; + + last if $pos > length($keylist); + $keylist = substr($keylist, $pos); + } + + # Apply substitutions to the original text fragment: + + $newtext = $text; + while(($key, $value) = each(%map)) + { + $newtext =~ s/\b$key\b/$value/g; + } + + # Replace the original message text with the expanded version: + + s/\Q$text/$newtext/; + + # Delete the key/value list from the message: + + s/\Q$keyclause//; + } + + # restore [###] clauses: + $dim_counter = 1; + foreach $dim (@dims) + { + s/zzz-$dim_counter-$dim-zzz/[$dim]/g; + $dim_counter++; + } + } + + # End 'with' clause processing + ############################################################################################# + +# eliminate standard namespace qualifiers (for now, required for STL filtering): + + s/\bstd(ext)?\:\://g unless $keep_stdns; + s/\b__gnu_cxx\:\://g unless $keep_stdns; + + s/note: //; # WTF? It's just noise. + s/typename //g; # ditto + +# The following section strips out the "class" keyword when it is part +# of a type name, but not when it is part of the 'prose' of a message. +# To do this, we only strip the word "class" when it follows an +# odd-numbered single quote (1st, 3rd, 5th, + + $out = ""; # accumulate result into $out + $old = $_; + + while (1) + { + if (($pos = index ($old, "`")) == -1) # index of next opening quote + { # if none, + $out .= $old; # we're done + last; + } + $out .= substr($old, 0, $pos + 1, ""); # splice up to & including the "'" to $out + $pos = index($old, "'"); # index of next closing quote in $out + $txt = substr($old, 0, $pos + 1, ""); # splice from $old into $txt + $txt =~ s/\bclass //g if !/\btypedef\b/; # filter out "class" from $txt + $out .= $txt; # concatenate result to cumulative result + } # loop for next fragment + $_ = $out; # done; update entire current line + + +# s/\bclass //g if !/typedef/; # strip "class" except in typedef errors + + + s/\bstruct ([^'])/$1/g if !/typedef/; # don't strip "struct" for *anonymous* structs or typedefs + + s/\b_STLD?\:\://g unless $keep_stdns; # for STLPort + +# simplify the ubiquitous "vanilla" string and i/ostreams (w/optional default allocator): + + s/\b(_?basic_(string|if?stream|of?stream|([io]?stringstream)))<(char|wchar_t), ?(string_)?char_traits<\4>(, ?__default_alloc_template<(true|false), ?0>)? ?>\:\:\1/$2::$2/g; + s/\b_?basic_(string|if?stream|of?stream|([io]?stringstream))<(char|wchar_t), ?(string_)?char_traits<\3>(, ?__default_alloc_template<(true|false), ?0>)? ?>/$1/g; + s/\b(_?basic_(string|if?stream|of?stream|([io]?stringstream)))<(char|wchar_t), ?(string_)?char_traits<\4>(, allocator<\4>)? ?>\:\:\1/$2::$2/g; + s/\b_?basic_(string|if?stream|of?stream|([io]?stringstream))<(char|wchar_t), ?(string_)?char_traits<\3>(, allocator<\3>)? ?>/$1/g; + s/\b([io])stream_iterator<($t), ?($t), ?char_traits<\3>, ?($t)>/$1stream_iterator<$2>/g; + + s/\b__normal_iterator\:\:__normal_iterator\(/string::const_iterator(/g; + s/\b__normal_iterator<$t, ?($t)>\:\:__normal_iterator\(/string::iterator(/g; + + +# The following loop repeats until no transformations occur in the last complete iteration: + + for ($pass = 1; ;$pass++) # pass count (for de-bugging purposes only) + { + my $before = $_; # save the current line; keep looping while changes happen + +# +# Handle allocator clauses: +# + +# delete allocators from template typenames completely: + + $has_double_gt = 0; + $has_double_gt++ if />>/; + + s/allocator<($t)>::rebind<\1>::other::($id)/allocator<$1>::$2/g; + s/\b,? ?allocator<$t ?>(,(0|1|true|false)) ?>/$2>/g; + s/, ?allocator<$id<($t), ?allocator<\1> ?> ?>//g; + s/, ?allocator<$t> ?>/>/g; + + +# remove allocator clauses + +# gcc 4.x allocator types + + s/, ?allocator<($t) ?>\:\:rebind<\1 ?>\:\:other>/>/g; + +# remove allocator clauses if the message doesn't refer to an allocator explicitly: + + unless (/' to '.*allocator\:\:/) + { + s/, ?allocator<$t ?> ?//g; # the leading comma allows the full spec. + s/, ?const allocator<$t ?> ?&//g; # to appear in the error message details + s/,? ?(const )?$t\:\:allocator_type ?&//g; + } + + + if (!$has_double_gt) + { + while (/>>/) + { + s/>>/> >/g; + } + } + + +# gcc deque, deque iterators: + + s/\bdeque<($t),0>/deque<$1>/g; + s/\b_Deque_iterator<($t), ?\1 ?&, ?\1 ?[*&](, ?0)?>\:\:_Deque_iterator ?\(/deque<$1>::iterator(/g; + s/\b_Deque_iterator<($t), ?\1 ?&, ?\1 ?[*&](, ?0)?>/deque<$1>::iterator/g; + + s/\b_Deque_iterator<($t), ?const \1 ?&, ?const \1 ?[*&](,0)?>\:\:_Deque_iterator ?\(/deque<$1>::const_iterator(/g; + s/\b_Deque_iterator<($t), ?const \1 ?&, ?const \1 ?[*&](,0)?>/deque<$1>::const_iterator/g; + +# gcc list iterators: + + s/\b_List_iterator<($t), ?(const )?\1 ?&, ?(const )?\1 ?\*>\:\:_List_iterator ?\(/list<$1>::iterator(/g; + s/\b_List_iterator<($t), ?(const )?\1 ?&, ?(const )?\1 ?\*>/list<$1>::iterator/g; + + s/\b_List_iterator<($t)>\:\:_List_iterator\(/list<$1>::iterator(/g; + s/\b_List_iterator<($t)>/list<$1>\:\:iterator/g; + + s/\b_List_const_iterator<($t)>\:\:_List_const_iterator ?\(/list<$1>::const_iterator(/g; + s/\b_List_const_iterator<($t)>/list<$1>::const_iterator/g; + + s/_List_node<($t)> ?\*/list<$1>::iterator/g; + s/_List_node_base ?\*/iterator/g; + s/_List_const_iterator/const_iterator/g; + s/_List_iterator/iterator/g; + +# gcc slist iterators: + + s/\b_Slist_iterator<($t), ?\1 ?&, ?\1 ?\*>\:\:_Slist_iterator ?\(/slist<$1>::iterator(/g; + s/\b_Slist_iterator<($t), ?const \1 ?&, ?const \1 ?\*>\:\:_Slist_iterator ?\(/slist<$1>::const_iterator(/g; + s/\b_Slist_iterator<($t), ?\1 ?&, ?\1 ?\*>/slist<$1>::iterator/g; + s/\b_Slist_iterator<($t), ?const \1 ?&, ?const \1 ?\*>/slist<$1>::const_iterator/g; + s/\b_Slist_node<($t)> ?\*/slist<$1>::iterator/g; + + +# gcc vector iterator: + + s/\b__normal_iterator<($t) ?\*, vector<\1 ?> ?>\:\:__normal_iterator ?\(/vector<$1>::iterator(/g; + s/\b__normal_iterator<($t) ?\*, vector<\1 ?> ?>/vector<$1>::iterator/g; + s/\b__normal_iterator<($t) const ?\*, vector<\1 ?> ?>\:\:__normal_iterator ?\(/vector<$1>::const_iterator(/g; + s/\b__normal_iterator ?>\:\:__normal_iterator ?\(/vector<$1>::const_iterator(/g; + s/\b__normal_iterator<($t) const ?\*, vector<\1 ?> ?>/vector<$1>::const_iterator/g; + s/\b__normal_iterator ?>/vector<$1>::const_iterator/g; + + +# gcc map: + + s/\b_Rb_tree<($t), ?pair, ?_Select1st ?> ?>/map<$1,$2>/g; + s/\b_Rb_tree<($t), ?pair, ?_Select1st ?>, ($t) ?>/map<$1,$2,$3>/g; + +# s/\b_Rb_tree<($t), ?pair, ?_Select1st > ?>/map<$1,$2>/g; + s/\b_Rb_tree<($t), ?pair, ?_Select1st ?>, ($t)::rebind >::other>/map<$1,$2,$3>/g; + + +# gcc map/multimap iterators: + + s/\b_Rb_tree<($t), ?pair, ?_Select1st ?>::rebind >::other>/multimap<$1,$2>/g; + + + s/\b_Rb_tree_iterator ?>\:\:_Rb_tree_iterator\(const _Rb_tree_iterator ?>&\)/gen_map<$1,$2>::iterator(const gen_map<$1,$2>::iterator &)/g; + s/\b_Rb_tree_const_iterator ?>\:\:_Rb_tree_const_iterator\(const _Rb_tree_const_iterator ?>&\)/gen_map<$1,$2>::const_iterator(const gen_map<$1,$2>::const_iterator &)/g; + s/\b_Rb_tree_const_iterator ?>\:\:_Rb_tree_const_iterator\(const _Rb_tree_iterator ?>&\)/gen_map<$1,$2>::const_iterator(const gen_map<$1,$2>::iterator &)/g; + + s/\b_Rb_tree_iterator ?>\:\:_Rb_tree_iterator\(_Rb_tree_node ?>\*\)/gen_map<$1,$2>::iterator/g; + s/\b_Rb_tree_const_iterator ?>\:\:_Rb_tree_const_iterator\(const _Rb_tree_node ?>\*\)/gen_map<$1,$2>::iterator/g; + + s/\b_Rb_tree_iterator ?>/gen_map<$1,$2>::iterator/g; + s/\b_Rb_tree_const_iterator ?>/gen_map<$1,$2>::const_iterator/g; + + s/\b_Rb_tree_node ?> ?\*/gen_map<$1,$2>::iterator/g; + + s/\b_Rb_tree_iterator, ?pair ?&, ?pair ?\*>\:\:_Rb_tree_iterator ?\(/gen_map<$1,$2>::iterator(/g; + s/\b_Rb_tree_iterator, ?pair ?&, ?pair ?\*>/gen_map<$1,$2>::iterator/g; + + s/\b_Rb_tree_iterator, ?const pair ?&,const pair ?\*>\:\:_Rb_tree_iterator ?\(/gen_map<$1,$2>::const_iterator(/g; + s/\b_Rb_tree_iterator, ?pair<\1 ?const, ?\2> ?&, ?pair<\1 ?const, ?\2> ?\*>\:\:_Rb_tree_iterator ?\(/gen_map<$1,$2>::const_iterator(/g; + + s/\b_Rb_tree_iterator, ?const pair ?&,const pair ?\*>/gen_map<$1,$2>::const_iterator/g; + s/\b_Rb_tree_iterator, ?pair<\1 ?const, ?\2> ?&, ?pair<\1 ?const, ?\2> ?\*>/gen_map<$1,$2>::const_iterator/g; + + s/\b_Rb_tree_iterator ?>/gen_map<$1,$2>::iterator/g; + s/\b_Rb_tree_const_iterator ?>/gen_map<$1,$2>::const_iterator/g; + + +# gcc set/multiset/map/multimap iterator (who knows, lol?) + + s/\b_Rb_tree_iterator\(($t)\)/gen_set_or_map::iterator($1)/g; + s/\b_Rb_tree_const_iterator<($t)>\:\:_Rb_tree_const_iterator\(/gen_set_or_map<$1>::const_iterator(/g; + s/\b_Rb_tree_const_iterator<($t)>/gen_set_or_map<$1>::const_iterator/g; + s/\b_Rb_tree_const_iterator\(($t)\)/gen_set_or_map::const_iterator($1)/g; + + +# Since the same iterator type is used for both set and multiset, we just +# say "gen_set::iterator" to mean the "GENERIC" set/multiset iterator type: + +# gcc set/multiset: + + s/\b_Rb_tree<($t), ?\1, ?_Identity<$t>, ?($t)>/gen_set<$1,$2>/g; + s/\b_Rb_tree<($t), ?\1, ?_Identity<$t>>/gen_set<$1>/g; + + +# gcc set/multiset iterator: + + s/\b_Rb_tree_iterator<($t), ?const \1 ?&, ?const \1 ?\*>::_Rb_tree_iterator ?\(/gen_set<$1>::iterator(/g; + + s/\b_Rb_tree_iterator<($t), ?const \1 ?&, ?const \1 ?\*>/gen_set<$1>::iterator/g; + + s/\b_Rb_tree_iterator<($t) \*, ?\1 ?\*const &, ?\1 ?\*const \*>::_Rb_tree_iterator ?\(/gen_set<$1>::iterator(/g; + s/\b_Rb_tree_iterator<($t) \*, ?\1 ?\*const &, ?\1 ?\*const \*>/gen_set<$1>::iterator/g; + + s/[`']\b_Rb_tree_const_iterator ?<($t)>\:\:_Rb_tree_const_iterator\(const _Rb_tree_node<($t)> ?\*\)'/gen_set<$1>::const_iterator/g; + + s/[`']\b_Rb_tree_iterator ?\(($t)\)'/gen_set<$1>::iterator/g; + s/[`']\b_Rb_tree_const_iterator ?\(($t)\)'/gen_set<$1>::const_iterator/g; + s/\b_Rb_tree_iterator ?\(($t)\)/gen_set<$1>::iterator/g; + s/\b_Rb_tree_const_iterator ?\((const $t)\)/gen_set<$1>::const_iterator/g; + s/\b_Rb_tree_iterator ?<($t)>/gen_set<$1>::iterator/g; + s/\b_Rb_tree_const_iterator ?<($t)>/gen_set<$1>::const_iterator/g; + + s/\bconst _Rb_tree_node<($t) ?> ?\*/gen_set<$1>::const_iterator/g; + s/\b_Rb_tree_node<($t)> ?\*/gen_set<$1>::iterator/g; + + +# STLPort /gcc hash_set/_multiset: + + s/\b(hash_(?:multi)?)set<($t)(, ?hash<\2 ?>)? ?(, ?equal_to<\2 ?>)? ?>/$1set<$2>/g; + s/\bhashtable<($t), ?\1, ?hash<\1 ?>, ?_Identity<\1 ?>, ?$t>/gen_hash_set<$1>/g; + + +# gcc hash_map/multimap: + + s/\b(hash_(?:multi)?)map<($t), ?($t), ?hash<\2 ?>, ?($t)>/$1map<$2,$3>/g; + + +# gcc hash_set/hash_multiset iterator: + + s/\b_Hashtable_const_iterator<($t), ?\1, ?hash<\1 ?>, ?_Identity<\1 ?>, ?$t>\:\:_Hashtable_const_iterator ?\(/gen_hash_set($1):const_iterator(/g; + s/\b_Hashtable_const_iterator<($t), ?\1, ?hash<\1 ?>, ?_Identity<\1 ?>, ?$t>/gen_hash_set($1):const_iterator/g; + s/\b_Hashtable_iterator<($t), ?\1, ?hash<\1 ?>, ?_Identity<\1 ?>, ?$t>\:\:_Hashtable_iterator ?\(/gen_hash_set($1):iterator(/g; + s/\b_Hashtable_iterator<($t), ?\1, ?hash<\1>, ?_Identity<\1>, ?$t>/gen_hash_set($1):iterator/g; + +# gcc hash_map/hash_multimap: + + s/\bhashtable<(pair), ?\2, ?hash<\2 ?>, ?_Select1st<\1 ?>, ?$t ?>/gen_hash_map<$2,$3>/g; + +# gcc hash_set/hash_multiset value_type: + + s/\bhashtable<($t), ?\1, ?hash<\1>, ?_Identity<\1>, ?$t>::value_type/$1/g; + +# STLPort/gcc hash_map/_multimap iterators under VC7 (same "GENERIC" iterator approach as above): + + s/\b_Hashtable_iterator, ?\1, ?hash<\1 ?>, ?_Select1st ?>, ?equal_to<\1 ?> ?>\:\:_Hashtable_iterator\(/gen_hash_map<$1,$2>::iterator(/g; + s/\b_Hashtable_const_iterator, ?\1, ?hash<\1 ?>, ?_Select1st ?>, ?equal_to<\1 ?> ?>\:\:_Hashtable_const_iterator\(/gen_hash_map<$1,$2>::const_iterator(/g; + s/\b_Hashtable_iterator, ?\1, ?hash<\1 ?>, ?_Select1st ?>, ?equal_to<\1 ?> ?>/gen_hash_map<$1,$2>::iterator/g; + s/\b_Hashtable_const_iterator, ?\1, ?hash<\1 ?>, ?_Select1st ?>, ?equal_to<\1 ?> ?>/gen_hash_map<$1,$2>::const_iterator/g; + +# simplify default comparison function objects, leave others intact: + + s/, ?_?less<$t ?>//g; + s/, ?Comp<$t ?>//g; # STLPort's default comparison function + + last if $before eq $_; # keep looping if substitutions were actually made + } + +# reverse iterators: + + s/\breverse_iterator<($t)::iterator ?>/$1::reverse_iterator/g; + s/\breverse_iterator<($t)::const_iterator ?>/$1::const_reverse_iterator/g; + s/\bconst_reverse_iterator\:\:reverse_iterator/const_reverase_iterator/g; + +# reduce iterators according to $iter_policy: + + $olditer = '(reverse_)?(bidirectional_)?((back_)?insert_)?iterator'; + if ($iter_policy eq 'M') # policy 'M': USUALLY remove: + { + unless (/( of type|' to '|from ')$t\:\:(const_)?$olditer/ # Shorten to $newiter and + or /iterator' does/) # *remove* the base type completely... + { # as long as the error message doesn't + s/$t\:\:((const_)?$olditer)\b/$1/g; # mention iterators! + } + } + elsif ($iter_policy eq 'S') # policy 'S': ALWAYS remove: + { + s/$t\:\:((const_)?$olditer)\b/$1/g; # remove the base type completely + } + # All policies (including 'L'): + s/\biterator\b/$newiter/g; + s/\b(const_|reverse_|const_reverse_)iterator\b/$1$newiter/g; + +# remove trailing "null args" from template parameter lists: + + foreach $name (@nullargs) + { + s/(, ?$name ?)* ?>/>/g; + } + +# reduce "double" constructor names 'T::T' to just 'T': + + s/[`']string\:\:string([\('])/'string$1/g; + s/[`'](.*)\:\:\1([\('])/'$1$2/g; + +# deal with some other non-critical (and often not even very aesthetic) spaces (or lack thereof): + + s/>>>>>([\(:',*&])/> > > > >$1/g; # put spaces between the close brackets + s/>>>>([\(:',*&])/> > > >$1/g; + s/>>>([\(:',*&])/> > >$1/g; + + if (/(.)>>(.)/) # careful, ">>" could be operator... + { + $before = $1; + $after = $2; + s/(.)>>([ \(:',*&])/$1> >$2/g unless (/operator ?>>/ or ($before eq ' ' and $after eq ' ')); + } + + + s/([^> ]) >([^>=])/$1>$2/g; # remove space before '>' (unless between another '>' or '>=') + + s/([\w>])([&*])/$1 $2/g if !$smush_amps_and_stars; # conditionally force space between identifier and '*' or '&' + + s/,([^ ])/, $1/g if $space_after_commas; # add space *after* a comma, however, if desired. + + + s/ initializing argument / init. arg /; + +# and FINALLY, print out the result of all transformations, preceded by saved prefix: + + $_ = $prefix . $_; + s/\: /:/ if $break_algorithm eq 'D'; # lose "candidate" alignment in "Dave" wrap mode + + # reformat line number indicator + s/\:(\d+)/($1)/g if $reformat_linenumbers; + + if ($dave_move) + { + print "DBG: A\n" if $movedbg; + $has_from = /^\s*from /; + if (!$in_backtrace) + { + print "DBG: B\n" if $movedbg; + if (/:\s+In\b/i or /^\s*In file included from/) + { + $in_backtrace = 1; # template instantiation backtrace? + print "DBG: C (in_backtrace set to 1)\n" if $movedbg; + @backtrace = (); + } + } + elsif (/instantiated\s+from\s+here/) + { + print "DBG: D\n" if $movedbg; + $saved_trigger = $_; + } + elsif (/instantiated\s+from\s+[`']/) #` Fix syntax hilighting for emacs + { + $saw_instantiated = 1; + print "DBG: E (saw_instantiated set to 1)\n" if $movedbg; + } + elsif (/^\s*from .*[,:]$/) + { + $in_backtrace = 2; # header backtrace + print "DBG: F (in_backtrace set to 2)\n" if $movedbg; + } + else # we've come to the end. + { + print "DBG: G\n" if $movedbg; + + # if we've already begun displaying the final error message: + + if ($displaying_error_msg) + { + if (substr($_, 0, 1) =~ /\s/ or /within this context/) # if we see a line beginning with whitespace, it is a continuation of the actual error message: + { + if (/within this context/) + { + next if $last_within_context eq $_; # strip consecutive identical "within this context" lines (gcc bug?) + $last_within_context = $_; + } + break_and_print $_; + next; + } + else # if we see a line not starting with whitespace, finalize the re-order mode processing: + { + $last_within_context = ""; # reset "within this context" duplicate detection mechanism + break_and_print (shift @backtrace); # print 1st line of backtrace + + # if replicating trigger, do it: + break_and_print $saved_trigger if $dave_rep and $saw_instantiated; + + $backtrace[$#backtrace] =~ s/:$// # if header file backtrace, strip trailing + if $in_backtrace == 2 and @backtrace; # colon from last line + + foreach $line (@backtrace) # now emit the accumulated backtrace + { + break_and_print $line; + } + print "\n"; + $in_backtrace = 0; + print "DBG: I\n" if $movedbg; + + $displaying_error_msg = 0; + $last_within_context = ""; + $pushed_back_line = $_; + next; + } + } + + if ($saw_instantiated or ($in_backtrace == 2 and $has_lineno and !$has_from)) + { + print "DBG: H\n" if $movedbg; + print "************** PRINT DBG 2 **************\n" if $pdbg; + print "\n"; # let's set the "deep" error sequence apart + break_and_print $_; # print the first line of the actual error first + $displaying_error_msg = 1; # and go into displaying error message mode until we see a line beginning with non-ws + next; + } + elsif ($in_backtrace == 1) # template backtrace "false alarm"? + { + print "DBG: J\n" if $movedbg; + break_and_print (shift @backtrace); # yes. + $in_backtrace = 0; # reset for another round + } + } + + print "DBG: K\n" if $movedbg; + if ($in_backtrace) + { + print "DBG: L\n" if $movedbg; + push @backtrace, $_; + next; + } + } + + print "************** PRINT DBG 3 **************\n" if $pdbg; + break_and_print "$_"; +} + + +if ($displaying_error_msg) +{ + break_and_print (shift @backtrace); # print 1st line of backtrace + + # if replicating trigger, do it: + break_and_print $saved_trigger if $dave_rep and $saw_instantiated; + + $backtrace[$#backtrace] =~ s/:$// # if header file backtrace, strip trailing + if $in_backtrace == 2 and @backtrace; # colon from last line + + foreach $line (@backtrace) # now emit the accumulated backtrace + { + break_and_print $line; + } + print "\n"; + + print "DBG: I2\n" if $movedbg; +} + +close LOGNATIVE if $lognative; # close native messages logfile if active + +if ($doing_candidates and $candidate_policy eq 'M') +{ + println " [STL Decryptor: Suppressed $doing_candidates 'candidate' line" . + ($doing_candidates != 1 ? "s" : "") . "]"; +} +else +{ + # if 'M' or 'S' header policy, tell how many skipped: + if (($doing_stl_headers > $headers_to_show) and $header_policy ne 'L') + { + println " [STL Decryptor: Suppressed " . + ($doing_stl_headers - $headers_to_show) . + ($header_policy eq 'M' ? " more " : " ") . + "STL standard header message" . + (($doing_stl_headers - $headers_to_show) != 1 ? "s" : "") . "]"; + $suppressed_headers = 1; + } +} + +if ($advise_re_policy_opts and ($suppressed_headers or $suppressed_candidates)) +{ + print "\nSTL Decryptor reminder"; + print "s" if $suppressed_headers and $suppressed_candidates; + println ":"; + println " Use the /hdr:L option to see all suppressed standard lib headers" if $suppressed_headers; + println " Use the /cand:L option to see all suppressed template candidates" if $suppressed_candidates; +} + +if ($choked) +{ + print "\n***************************************************************************\n"; + print "A non-fatal, internal STL Decryptor error has occurred.\n"; + if ($show_internal_err) + { + print "It should have said as much somewhere above, and then emitted the \n"; + print "partially-filtered line.\n"; + } + print "Please look for a file just created named NativeLog.txt,\n"; + print "and email this file to leor\@bdsoft.com. This will greatly assist me\n"; + print "to understand and try to correct the problem. Thank you!\n"; + print "***************************************************************************\n"; +} + +exit 0; + + +sub break_and_print { + my $line = shift(@_); + + if ($output_width == 0 or ($break_algorithm eq 'P' and length($line) < $output_width)) + { + $line =~ s/\s+\n/\n/g; # delete trailing space on a line + print "************** PRINT DBG 4 **************\n" if $pdbg; + print "$line"; + return; + } + + if ($break_algorithm eq 'P') + { + print "************** PRINT DBG 5 **************\n" if $pdbg; + break_and_print_plain "$line"; + return; + } + + $nesting_level = 0; # track combined nesting level for () [] <> {} + $in_quotes = 0; # not in quotes + +WRAPLOOP: + for ($frag_count = 0; ;$frag_count++) + { + print "\nDBG: Top of WRAPLOOP, line to process is: '$line'\n" if $wrapdbg; + print "DBG: top of WRAPLOOP a: frag_count = $frag_count, nesting_level = $nesting_level\n" if $wrapdbg; + print "DBG: tabsize = $tabsize, in_quotes = $in_quotes\n" if $wrapdbg; + + $indentation = $nesting_level; # save indentation at start of every line + $width = $output_width - ($nesting_level * $tabsize); + + print "DBG: top of WRAPLOOP: indentation = $indentation\n" if $wrapdbg; + print "DBG: width now $width \n" if $wrapdbg; + + $line =~ s/^\s*//; # delete leading spaces + $line =~ s/,([^ \t])/, $1/g; # make sure commas are followed by a space for gcc2 + + + if ($frag_count > 0) # make sure only 1st line of message hugs left margin + { + $indentation++; + $width -= $tabsize; + } + + $at_left = 0; # recognize when there's no nested parens + $at_left = 1 if ($close_wrap eq 'N' and + ($frag_count == 0 or ($frag_count > 0 and $nesting_level == 1))); + + # Preprocess line, creating table mapping close- to open-parens: + + print "\n\nDBG: line to process (width = $width, nesting_level = $nesting_level, in_quotes = $in_quotes):\n$line" if $pdbg or $delimdbg; + showkey $width if $pdbg or $delimdbg; + + + $first_unmatched_close = $width; # position of first unmatched close paren + $unmatched_close_nesting = $nesting_level; # the nesting level below which we'll consider a close paren to be unmatched + $initial_close = 0; # assume first character is not a close paren + + @delims = (); # list of unmatched open delims + @delim_index = (); # for each open, record its position + @nesting_key = (); # record nesting level at each char position + @quoting_key = (); # record whether in quotations at each char position + + # for each closer, we'll record the position of the corresponding opener in @delim_opener + + # begin by resetting each position: + for ($i = 0; $i < length($line); $i++) + { + $delim_opener[$i] = -1; + } + + for ($pos = 0; $pos < $width and $pos < length($line); $pos++) + { + $c = substr($line, $pos, 1); + + print "DBG: delimiter de-bugging, column pos = $pos (char there = '$c')\n" if $delimdbg; + + if (exists $open_delims{$c}) + { + $before = ' '; + $before = substr($line, $pos-1, 1) if $pos > 0; + + $beforetext = ""; + $beforetext = substr($line, $pos - 8, 8) if ($pos >= 8); # looking for "operator" + + $after = ' '; + if ($pos < (length($line) - 1)) + { + $after = substr($line, $pos+1, 1); + $aftertext = substr($line, $pos+1); + } + # Exclude some special cases: + if (!($before eq '`' and $after eq '\'') and # `paren' + !($before eq ' ' and $after eq ' ' and $c eq '<') and # < (relop) + !( ($before eq $c or $after eq $c) and ($c eq '<')) and # two <'s in a row + !($c eq '<' and $after eq '=') and # <= + !($c eq '<' and ($after eq '"' or $before eq '"')) and # "< or <" + !($c eq '(' and $after eq ')') and # () + !(($c eq '<' or $c eq '(') and $beforetext =~ /\boperator ? 0; + + $beforetext = ""; + $beforetext = substr($line, $pos - 10, 10) if ($pos >= 10); # looking for "operator" + + $after = ' '; + if ($pos < (length($line) - 1)) + { + $after = substr($line, $pos+1, 1); + $aftertext = substr($line, $pos+1); + } + # Exclude some special cases: + if (!($before eq '`' and $after eq '\'') and # `paren' + !($beforetext =~ /\s$/ and $c eq '>' and $after eq '>') and # whitespace >> + !($beforetext =~ /\s>$/ and $c eq '>' and $aftertext =~ /^\s/) and # whitespace >> whitespace + !($c eq '>' and $after eq '=') and # >= + !($c eq '>' and ($after eq '"' or $before eq '"')) and # "> or >" + !($c eq '>' and $beforetext =~ /\boperator ?>?$/) and # operator> or operator>> + !($c eq ')' and $before eq '(') and # () + !($aftertext =~ /^first use/) and + !($before eq '-' and $c eq '>')) # special case: -> operator (!!) + { + print "DBG: matched closing delim '$c', aftertext = '$aftertext'\n" if $delimdbg; + $nesting_level--; + # If the nesting_level ever falls below its level at + # the beginning of the line, we have an unmatched + # close paren and we must force a break there. + if ($pos == 0) + { + # initial close delimiters don't count, we'll break after the nesting falls again + $initial_close = 1; + $unmatched_close_nesting--; + } + elsif ($close_wrap eq 'Y' and $in_quotes + and $first_unmatched_close > $pos + and $nesting_level < $unmatched_close_nesting) + { + $first_unmatched_close = $pos; + } + + if (@delims > 0) + { + if ($c ne $opps{$delims[$#delims]}) + { + if ($show_internal_err) + { + if (!$lognative) + { + lognative_header; + print LOGNATIVE "Raw unprocessed input line:\n$save_line_for_dbg\n\n"; # write out the unprocessed offending line } + $lognative = 1; + } + + print LOGNATIVE "\nThe line at the point of the error was:\n$line\n"; + print LOGNATIVE " " x $pos . "^\n"; + print LOGNATIVE "\nNesting key: " . "@nesting_key\n"; + + print LOGNATIVE "\nSTL Decryptor ERROR: the char '$c' (position $pos) DOESN'T MATCH DELIMITER '$delims[$#delims]'!\n"; + + $choked = 1; + print "\n"; + print " [An Internal STL Decryptor error has occurred while processing\n"; + print " the line that follows. Note that the line has not been successfully\n"; + print " wrapped, but substitutions should still be intact:]\n\n"; + } + print "$line\n"; # write out the unwrapped line + next MAIN_LOOP; + } + else + { + pop @delims; + $delim_opener[$pos] = pop @delim_index; # map close index to open index + } + } + } + } + elsif ($c =~ /[`']/) + { + $in_quotes = !$in_quotes; + } + $nesting_key[$pos] = $nesting_level; # track nesting level at each column + $quoting_key[$pos] = $in_quotes; # track nesting level at each column + } + + # STEP 0: If there's an unmatched back-quote before the end of the line, + # and we're not in col. 1, and it isn't just `id', wrap before the back-quote: + + if (length($line) > $width and substr($line, 0, $width-1) =~ /(`$id[^'`]*$)/) #` Fix syntax highlighting for emacs + { + $name_pos = $-[0]; + + if ($name_pos != 0) + { + print "*********** PRINT DBG 6 width=$width indent=$indentation *********\n" if $pdbg; + print2 ($indentation, (substr($line, 0, $name_pos) . "\n")); + $line = substr($line, $name_pos); + $nesting_level = $nesting_key[$name_pos - 1]; + $in_quotes = $quoting_key[$name_pos - 1]; + next WRAPLOOP; + } + } + + # STEP 1: If there's an incomplete paren pair on the current line: + + if (@delims) + { + # + # STEP 1A: Find the first open paren on the line whose matching close paren doesn't fit: + # + $open_pos = $delim_index[0]; + + while (1) + { + $beforeit = substr($line, 0, $open_pos); + + # STEP 1Ai: If it's immediately preceded by >::ident[::ident...] + # or foo.template bar + # or foo.bar(...).template baz + + if (($beforeit =~ /[>)](\s*(::|\.|->)?\s*$id)+$/) and $-[0] != 0) + { + # STEP 1A1a: If the opening angle bracket matching the 1st char of the r.e. above is on + # this line, move back to that position and go to 1Ai + $open_pos = $-[0]; + if ($delim_opener[$open_pos] != -1) + { + $open_pos = $delim_opener[$open_pos]; + next; + } + # STEP 1A1b: Else move to the first char of the r.e. above and go on to 1B (this is + # already where $open_pos indicates) + } + last; + } + + if ($first_unmatched_close < $open_pos) + { + print "******** PRINT DBG 6A width=$width indent=$indentation ******\n" if $pdbg; + print2 ($indentation, (substr($line, 0, $first_unmatched_close) . "\n")); + $line = substr($line, $first_unmatched_close); + $nesting_level = $nesting_key[$first_unmatched_close - 1]; + $in_quotes = $quoting_key[$first_unmatched_close - 1]; + next WRAPLOOP; + } + + # + # STEP 1B: If we're on an open paren, and there's a comma earlier on the line at the same level, + # and the last such comma is not the first non-ws char on the line, wrap just before it + # and don't indent: + # + $c = substr($line, $open_pos, 1); + if (exists $open_delims{$c}) # if it's an open paren... + { + if ($in_quotes and scanback "$line") + { + # We've found the comma + if ($comma_wrap eq 'B' and $nesting_level > 0) + { + # Wrap just before $comma_pos: + print "******** PRINT DBG 7 width=$width indent=$indentation ******\n" if $pdbg; + print2 ($indentation, (substr($line, 0, $comma_pos) . "\n")); + $line = substr($line, $comma_pos); + $nesting_level = $nesting_key[$comma_pos - 1]; + $in_quotes = $quoting_key[$comma_pos - 1]; + } + else + { + # Wrap just after $comma_pos: + print "******** PRINT DBG 8 width=$width indent=$indentation ******\n" if $pdbg; + print2 ($indentation, (substr($line, 0, $comma_pos +1) . "\n")); + while (substr($line, $comma_pos + 1, 1) eq ' ') + { + $comma_pos++; + } + $line = substr($line, $comma_pos + 1); + $nesting_level = $nesting_key[$comma_pos]; + $in_quotes = $quoting_key[$comma_pos]; + } + next WRAPLOOP; + } + } + + # STEP 1C: Else if it's an open paren: + # if $nesting_level is 0, wrap before the pattern + # if line begins at col. 1, wrap just after the open and indent the next line + + $c = substr($line, $open_pos, 1); + if (exists $open_delims{$c}) # if it's an open paren... + { + print "*********** PRINT DBG 9 width=$width indent=$indentation *********\n" if $pdbg; + print2 ($indentation, (substr($line, 0, $open_pos + 1) . "\n")); + $width -= $tabsize; + $line = " " . substr($line, $open_pos + 1); # special case xtra leading indent + $nesting_level = $nesting_key[$open_pos]; + $in_quotes = $quoting_key[$open_pos]; + next WRAPLOOP; + } + else # It must be a close paren. Wrap just before it and unindent the next line: + { + print "*********** PRINT DBG 10 width=$width indent=$indentation *********\n" if $pdbg; + print2 ($indentation, (substr($line, 0, $open_pos) . "\n")); + $width += $tabsize; + $line = substr($line, $open_pos); + $nesting_level = $nesting_key[$open_pos - 1]; + $in_quotes = $quoting_key[$open_pos - 1]; + next WRAPLOOP; + } + } + elsif ($first_unmatched_close < $pos) + { + print "*********** PRINT DBG 10A width=$width indent=$indentation *********\n" if $pdbg; + print2 ($indentation, (substr($line, 0, $first_unmatched_close) . "\n")); + $line = substr($line, $first_unmatched_close); + $nesting_level = $nesting_key[$first_unmatched_close - 1]; + $in_quotes = $quoting_key[$first_unmatched_close - 1]; + next WRAPLOOP; + } + else + { + # STEP 2: If there is a comma at the current level of paren nesting AND + # we're not at a nesting level of 0: + $open_pos = $pos; + + if (!$at_left and $in_quotes and scanback "$line") + { + if ($comma_wrap eq 'B' and $nesting_level > 0) + { + print "*********** PRINT DBG 11: width=$width indent=$indentation *********\n" if $pdbg; + print2 ($indentation, (substr($line, 0, $comma_pos) . "\n")); + $line = substr($line, $comma_pos); + $nesting_level = $nesting_key[$comma_pos - 1]; + $in_quotes = $quoting_key[$comma_pos - 1]; + } + else + { + print "*********** PRINT DBG 12: width=$width indent=$indentation *********\n" if $pdbg; + print2 ($indentation, (substr($line, 0, $comma_pos + 1) . "\n")); + while ($comma_pos < ($width - 1) and substr($line, $comma_pos + 1, 1) eq ' ') + { + $comma_pos++; + } + $line = substr($line, $comma_pos + 1); + $nesting_level = $nesting_key[$comma_pos]; + $in_quotes = $quoting_key[$comma_pos]; + } + } + else + { + # extra by LZ: if last part of line is "`identifier" we have an unbalanced + # nesting level, then break before the "`" + + if (length($line) > $width ) + { + $beforeit = substr($line, 0, $open_pos); + if ($line =~ /`$id/ or $line =~/`[+-=!*<>%^&|\/~]+/) + { + $name_pos = $-[0]; + if ($name_pos != 0 and $name_pos < $width and + !(($beforeit =~ /`$id'/ or $beforeit =~ /`[+-=!*<>%^&|\/~]+'/) + and $+[0] < $width)) #'))) fix syntax highlighting for emacs + { + if (exists $close_delims{substr($line, 0, 1)}) # special case for leading close + { + print "*********** PRINT DBG 13: width=$width indent=$indentation *********\n" if $pdbg; + break_and_print_plain2 (($tab x ($indentation - 1)) . + substr($line, 0, $name_pos) . "\n"); + } + else + { + print "*********** PRINT DBG 14: width=$width indent=$indentation *********\n" if $pdbg; + break_and_print_plain2 (($tab x $indentation) . + substr($line, 0, $name_pos) . "\n"); + } + $line = substr($line, $name_pos); + $nesting_level = $nesting_key[$name_pos - 1]; + $in_quotes = $quoting_key[$name_pos - 1]; + next WRAPLOOP; + } + } + } + + # STEP 3: Just break according to standard alrogithm + print "*********** PRINT DBG 15: width=$width indent=$indentation *********\n" if $pdbg; + $line = break_and_print_fragment ( $indentation, $width, $line); + + return if $line eq ""; + + $nesting_level = $nesting_key[$broke_at]; + $in_quotes = $quoting_key[$broke_at]; + } + } + } # WRAPLOOP +} + + +# +# break entire line using "plain" rules: +# usage: break_and_print_plain line +# + +sub break_and_print_plain { + my $line = shift(@_); + if ($output_width != 0) + { + return if ($line = break_and_print_fragment (0, $output_width, "$line")) eq ""; + while (($line = break_and_print_fragment (1, $output_width - $tabsize, "$line")) ne "") + {} + } + else + { + $line =~ s/\s+\n/\n/g; # delete trailing space on a line + print "$line"; + } +} + + +# +# Process line using "Plain" break algorithm up to first line break, +# return remainder of line for subsequent processing: +# usage: break_and_print_fragment indent line +# +# No matter what, don't break in the middle of a pathname...so as not +# to mess up tools that locate errors in files. If the line length has +# to exceed the /width setting, so be it in that case... +# + +sub break_and_print_fragment { + my $indent = shift(@_); + my $width = shift(@_) - 1; + my $line = shift(@_); + + $nl_pos = index($line, "\n"); + if ($nl_pos == -1 or $nl_pos > $width) + { + if ($obj) + { + substr($line, $width - 1, 0) = "\n" if (length($line) > $width); + } + else + { + if (length($line) > $width) + { + if ($prefix ne "" and $line =~ /:\d+:\s/g and pos($line) > $width) # never break within pathname + { + substr($line, pos($line), 0) = "\n"; + } + else + { + $pos = $width; + $theChar = substr($line, $pos, 1); + $theCharBefore = ($pos > 0) ? substr($line, $pos - 1, 1) : ' '; + $theCharAfter = substr($line, $pos + 1, 1); + + while ( ($theChar !~ /[\n '`,:]/ and $pos > 0 and !($theChar =~ /\w/ and $theCharBefore !~ /\w/)) + or ($theChar !~ /\s/ and $theCharBefore =~ /[:\/\\.]/) + or ($theChar eq ':' and $theCharAfter =~ /[\/\\.]/) + or ($theChar eq "'" and $theCharBefore !~ /\s/) + or ($theChar =~ /[A-Za-z]/ and $theCharBefore =~ /['"`]/) + ) + { + $pos--; + $theCharAfter = $theChar; + $theChar = substr($line, $pos, 1); + $theCharBefore = ($pos > 0) ? substr($line, $pos - 1, 1) : ' '; + } + + $pos-- if $pos > 0 and $theChar eq ':' and substr($line, $pos-1, 1) eq ':'; + + if ($pos == 0) + { + $pos += $width; + substr($line, $pos, 0) = "\n"; + } + else + { + substr($line, $pos, $theChar eq ' ' ? 1 : 0) = "\n"; + $pos += ($theChar eq ' ' ? 1 : 2); + } + } + } + } + } + + $line =~ s/ +\n/\n/g; # delete trailing space on a line + + $nl_pos = index($line, "\n"); + if ($nl_pos == -1) + { + print2 ($indent, $line); + return ""; + } + + print2 ($indent, substr($line, 0, $nl_pos + 1)); + $whats_left = substr($line, $nl_pos + 1); + $broke_at = $nl_pos - 1; + return "$whats_left"; +} + + +sub println +{ + if ($wrap_own_msgs) + { + break_and_println_plain shift(@_); + } + else + { + print shift(@_) . "\n"; + } +} + + +# +# call break_and_print_plain/fragment, adjust leading comma +# + +sub break_and_print_plain2 { + my $line = shift(@_); + $line =~ s/^(\s*) ,/$1,/; # Adjust leading comma + break_and_print_plain "$line"; +} + + + +# +# break_and_println_plain: Break with Plain rules, add a newline: +# + +sub break_and_println_plain { + break_and_print_plain shift(@_); + print "\n"; +} + + +# +# print2: prints a line +# If using the 'Dave" break algorithm: +# Rule 1: Omits two spaces of indentation if there's a leading comma +# Rule 2: Reduces indentation by one tab if there's a leading close "paren" +# (unless already at far left) +# +# usage: print2 (indentation,line) +# + +sub print2 +{ + my $indent = shift(@_); + my $line = shift(@_); + my $prefix = ""; + + if ($break_algorithm eq 'D') + { + if ($indent > 0) # special case for leading close - unindent just this line + { + $prefix = "$tab" x + ((exists $close_delims{substr($line, 0, 1)} and $indent > 1) ? ($indent - 1) : $indent); + } + + if (substr($line, 0, 1) eq "," and length($line) > 4) # if leading comma, omit two spaces + { # of indentation + substr($prefix, length($prefix) - 4, 4) = " "; + } + + # back up one space for open quotes to make alignment pretty in /break:D mode + if (substr($line, 0, 1) eq "`" and length($prefix) > 0) # ?? (was '`') + { + substr($prefix, 0, 1) = ""; + } + } + else + { + $prefix = "$tab" x $indent; + } + + print "$prefix" . $line; +} + + +# +# Scan backwards from position $open_pos for a comma at the same paren nesting level that is +# not the first non-whitespace on the line. +# return true if found, with $comma_pos indicating the position of the detected comma. +# + +sub scanback +{ + my $line = shift(@_); + my $c = substr($line, $open_pos, 1); + + $nest_level = 0; + for ($comma_pos = $open_pos - 1; $comma_pos > 0; $comma_pos--) # scan back for comma at same level + { + $c = substr($line, $comma_pos, 1); + if (exists $open_delims{$c}) + { # bail if we come to an open before (working + last if $nest_level == 0; # to the left) its matching close + $nest_level--; + next; + } + elsif (exists $close_delims{$c}) + { + $nest_level++; + next; + } + elsif ($c eq ',' and $nest_level == 0) # comma at same level? + { + for ($pos = $comma_pos - 1; $pos > 0; $pos--) # scan to start of line + { + if (substr($line, $pos, 1) !~ /\s/) # comma preceded by non-space? + { + return 1; # yes, so it is a valid comma + } + } + + # It IS the first non-ws on the line. + last; + } + } + + return 0; +} + + +sub lognative_header +{ + open(LOGNATIVE, ">NativeLog.txt") or + die "STL Decryptor: Can't create NativeLog.txt. Bailing out."; + + print LOGNATIVE "---------------------------------------------------------------------\n"; + print LOGNATIVE "$STLFilt_ID\n"; + print LOGNATIVE "---------------------------------------------------------------------\n"; + + print LOGNATIVE "Command line: '@save_args'\n"; + + print LOGNATIVE "banner = $banner\n"; + print LOGNATIVE "break_algorithm = $break_algorithm\n"; + print LOGNATIVE "comma_wrap = $comma_wrap\n"; + print LOGNATIVE "close_wrap = $close_wrap\n"; + print LOGNATIVE "output_width = $output_width\n"; + print LOGNATIVE "tabsize = $tabsize\n"; + print LOGNATIVE "advise_re_policy_opts = $advise_re_policy_opts\n"; + print LOGNATIVE "reformat_linenumbers = $reformat_linenumbers\n"; + print LOGNATIVE "wrap_own_msgs = $wrap_own_msgs\n"; + print LOGNATIVE "header_policy = $header_policy\n"; + print LOGNATIVE "with_policy = $with_policy\n"; + print LOGNATIVE "headers_to_show = $headers_to_show\n"; + print LOGNATIVE "candidate_policy = $candidate_policy\n"; + print LOGNATIVE "pathname_policy = $pathname_policy\n"; + print LOGNATIVE "show_backtraces = $show_backtraces\n"; + print LOGNATIVE "---------------------------------------------------------------------\n"; + print LOGNATIVE "Native input follows:\n"; + print LOGNATIVE "---------------------------------------------------------------------\n\n"; +} + + + +sub showkey +{ + my $width = shift (@_); + + print ((" " x ($width - 1)) . "v\n"); + print " 1 2 3 4 5 6 7 8 9\n"; + print "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345\n"; +} diff --git a/system/devel/gcc/files/gcc-4.9-isl-0.13-hack.patch b/system/devel/gcc/files/gcc-4.9-isl-0.13-hack.patch new file mode 100755 index 00000000..c2b95d95 --- /dev/null +++ b/system/devel/gcc/files/gcc-4.9-isl-0.13-hack.patch @@ -0,0 +1,71 @@ +diff -Naur gcc-4.9-20140604-old/gcc/graphite-clast-to-gimple.c gcc-4.9-20140604/gcc/graphite-clast-to-gimple.c +--- gcc-4.9-20140604-old/gcc/graphite-clast-to-gimple.c 2014-03-03 21:39:22.000000000 +1000 ++++ gcc-4.9-20140604/gcc/graphite-clast-to-gimple.c 2014-06-25 15:07:57.958697105 +1000 +@@ -28,6 +28,8 @@ + #include + #include + #include ++#include ++#include + #include + #include + #endif +diff -Naur gcc-4.9-20140604-old/gcc/graphite-interchange.c gcc-4.9-20140604/gcc/graphite-interchange.c +--- gcc-4.9-20140604-old/gcc/graphite-interchange.c 2014-01-03 08:23:26.000000000 +1000 ++++ gcc-4.9-20140604/gcc/graphite-interchange.c 2014-06-25 15:10:06.882899243 +1000 +@@ -29,6 +29,9 @@ + #include + #include + #include ++#include ++#include ++#include + #include + #include + #endif +diff -Naur gcc-4.9-20140604-old/gcc/graphite-optimize-isl.c gcc-4.9-20140604/gcc/graphite-optimize-isl.c +--- gcc-4.9-20140604-old/gcc/graphite-optimize-isl.c 2014-01-03 08:23:26.000000000 +1000 ++++ gcc-4.9-20140604/gcc/graphite-optimize-isl.c 2014-06-25 15:16:57.038386166 +1000 +@@ -28,6 +28,8 @@ + #include + #include + #include ++#include ++#include + #endif + + #include "system.h" +@@ -373,7 +375,7 @@ + { + for (i = ScheduleDimensions - 1 ; i >= 0 ; i--) + { +- if (isl_band_member_is_zero_distance (Band, i)) ++ if (isl_band_member_is_coincident (Band, i)) + { + isl_map *TileMap; + isl_union_map *TileUMap; +diff -Naur gcc-4.9-20140604-old/gcc/graphite-poly.c gcc-4.9-20140604/gcc/graphite-poly.c +--- gcc-4.9-20140604-old/gcc/graphite-poly.c 2014-01-03 08:23:26.000000000 +1000 ++++ gcc-4.9-20140604/gcc/graphite-poly.c 2014-06-25 15:18:01.207157796 +1000 +@@ -28,6 +28,8 @@ + #include + #include + #include ++#include ++#include + #include + #include + #endif +diff -Naur gcc-4.9-20140604-old/gcc/graphite-sese-to-poly.c gcc-4.9-20140604/gcc/graphite-sese-to-poly.c +--- gcc-4.9-20140604-old/gcc/graphite-sese-to-poly.c 2014-04-08 20:59:40.000000000 +1000 ++++ gcc-4.9-20140604/gcc/graphite-sese-to-poly.c 2014-06-25 15:19:46.575140398 +1000 +@@ -26,6 +26,9 @@ + #include + #include + #include ++#include ++#include ++#include + #include + #include + #include diff --git a/system/devel/gcc/files/gfilt b/system/devel/gcc/files/gfilt new file mode 100755 index 00000000..2d6b5d31 --- /dev/null +++ b/system/devel/gcc/files/gfilt @@ -0,0 +1,107 @@ +#!/bin/sh +# gfilt: Unix shell script driver for gcc / STL Error Decryptor +# +# Leor Zolman leor@bdsoft.com +# BD Software www.bdsoft.com +# Updated: 1/30/2008 +# +# Installation: Place this file and gSTLFilt.pl somewhere in your PATH +# (Make sure Perl is also in your PATH) +# +# Usage: gfilt [mixture of compiler and Decryptor options] file(s) +# +# Purpose: Serve as a substitute for the g++ compiler driver, in- +# corporating STLFilt functionality transparently. +# Distinguishes compiler options/args from Decryptor options, +# makes sure all recognized Decryptor options are passed on +# the Decryptor script command line while other options/ +# args are passed on the compiler command line. +# Filter all compiler output, and send results to stdout. +# +# (Note: stdout and stderr output streams from the compiler +# are combined by this process, so the two can no longer be +# individually redirected afterwards. If this is an issue +# for anyone, please let me know.) +# +# Exit status: The status code returned by the compiler +# +# Contents of the environment variable GFILTOPTS are passed as +# options to the STLFILT script (see the setting of DOPTS below.) +# +# 01/30/08 - Gets gSTLFilt.pl from same dir as this script +# Expanded the usage message a bit +# 06/29/05 - added more explanatory comments, fixed COPTS handling +# 02/16/05 - fixed multi-line case statement to work for freeBSD +# 12/17/04 - Added recognition of several script options that +# were missing from the case: with, meta, nullarg +# Added more comments. +# 02/21/03 - Exit status is now status of compilation +# +# Note: If packaged in a ZIP file, this file uses CR-LF line termination. +# If packaged in a .tar file, it'll have Unix-style termination. +######################################################################### +# Configuration section: + +COMPILER=c++ # Your g++ compiler command +STLFILT="`dirname $0`/gSTLFilt.pl" # Assumes gSTLFilt.pl is in same dir as gfilt + + # default options to Decryptor script: +DOPTS="/hdr:m /cand:s /iter:L ${GFILTOPTS:-}" +PAGER=less # pager of choice, or leave blank for no paging +COPTS= # compiler options + +# End of configuration section +######################################################################### + + +if $COMPILER --version | grep " 3\." >/dev/null # if gcc 3.x... +then + COPTS="-fmessage-length=0 $COPTS" # ...this option is needed. +fi + +if [ $# -eq 0 ]; then + echo "gfilt: wrapper for gcc/c++ compiler with STL Error Decryptor" + echo "usage: $0 [all-options] [compiler-arguments]" + echo " [NOTE: compiler and decryptor options may be mixed]" + exit 0 +fi + + + +GCC_ARGS= +DECRYPTOR_ARGS= + +for arg +do + case $arg in + [-/]iter:* | [-/]cand:* | [/-]hdr:* | \ + [-/]with:* | [-/]path:* | [/-]showback:* | \ + [/-]width:* | [-/]lognative | [-/]banner:* | [-/]nullarg:* | \ + [-/]break:* | [-/]cbreak:* | [-/]closewrap:* | [-/]meta | [-/]meta:*) + DECRYPTOR_ARGS="$DECRYPTOR_ARGS $arg";; + *) + GCC_ARGS="$GCC_ARGS $arg";; + esac +done + + +# +# Note that there are several options the Perl script accepts. +# see the comments at the top of gSTLFilt.pl for details. +# + +TMPFILE=/tmp/gfilt$$.tmp +touch $TMPFILE +trap "rm $TMPFILE; exit 1" 1 2 3 15 + +$COMPILER $COPTS $GCC_ARGS >$TMPFILE 2>&1 +STATUS=$? + +if [ "$PAGER" != "" ]; then + perl $STLFILT $DOPTS $DECRYPTOR_ARGS < $TMPFILE | $PAGER +else + perl $STLFILT $DOPTS $DECRYPTOR_ARGS < $TMPFILE +fi + +rm $TMPFILE +exit $STATUS diff --git a/system/devel/gcc/files/pisilinux/64.patch b/system/devel/gcc/files/pisilinux/64.patch new file mode 100755 index 00000000..46f1ce18 --- /dev/null +++ b/system/devel/gcc/files/pisilinux/64.patch @@ -0,0 +1,21 @@ +diff -Nuar gcc-4.9.0.orig/gcc/config/i386/linux64.h gcc-4.9.0/gcc/config/i386/linux64.h +--- gcc-4.9.0.orig/gcc/config/i386/linux64.h 2014-01-03 00:23:26.000000000 +0200 ++++ gcc-4.9.0/gcc/config/i386/linux64.h 2014-05-15 13:21:11.968021447 +0300 +@@ -28,5 +28,5 @@ + #define GNU_USER_LINK_EMULATIONX32 "elf32_x86_64" + + #define GLIBC_DYNAMIC_LINKER32 "/lib/ld-linux.so.2" +-#define GLIBC_DYNAMIC_LINKER64 "/lib64/ld-linux-x86-64.so.2" ++#define GLIBC_DYNAMIC_LINKER64 "/lib/ld-linux-x86-64.so.2" + #define GLIBC_DYNAMIC_LINKERX32 "/libx32/ld-linux-x32.so.2" +diff -Nuar gcc-4.9.0.orig/gcc/config/i386/t-linux64 gcc-4.9.0/gcc/config/i386/t-linux64 +--- gcc-4.9.0.orig/gcc/config/i386/t-linux64 2014-01-03 00:23:26.000000000 +0200 ++++ gcc-4.9.0/gcc/config/i386/t-linux64 2014-05-15 13:11:48.198012307 +0300 +@@ -33,6 +33,6 @@ + comma=, + MULTILIB_OPTIONS = $(subst $(comma),/,$(TM_MULTILIB_CONFIG)) + MULTILIB_DIRNAMES = $(patsubst m%, %, $(subst /, ,$(MULTILIB_OPTIONS))) +-MULTILIB_OSDIRNAMES = m64=../lib64$(call if_multiarch,:x86_64-linux-gnu) ++MULTILIB_OSDIRNAMES = m64=../lib$(call if_multiarch,:x86_64-linux-gnu) + MULTILIB_OSDIRNAMES+= m32=$(if $(wildcard $(shell echo $(SYSTEM_HEADER_DIR))/../../usr/lib32),../lib32,../lib)$(call if_multiarch,:i386-linux-gnu) + MULTILIB_OSDIRNAMES+= mx32=../libx32$(call if_multiarch,:x86_64-linux-gnux32) diff --git a/system/devel/gcc/files/pisilinux/gcc-4.8-filename-output.patch b/system/devel/gcc/files/pisilinux/gcc-4.8-filename-output.patch new file mode 100755 index 00000000..6951eb23 --- /dev/null +++ b/system/devel/gcc/files/pisilinux/gcc-4.8-filename-output.patch @@ -0,0 +1,17 @@ +--- gcc/c-family/c-opts.c (revision 200330) ++++ gcc/c-family/c-opts.c (working copy) +@@ -1338,10 +1338,14 @@ c_finish_options (void) + + /* Give CPP the next file given by -include, if any. */ + static void + push_command_line_include (void) + { ++ // This can happen if disabled by -imacros for example. ++ if (include_cursor > deferred_count) ++ return; ++ + if (!done_preinclude) + { + done_preinclude = true; + if (flag_hosted && std_inc && !cpp_opts->preprocessed) + { diff --git a/system/devel/gcc/files/pisilinux/gcc_47_based-record_gcc_options.patch b/system/devel/gcc/files/pisilinux/gcc_47_based-record_gcc_options.patch new file mode 100755 index 00000000..04a62883 --- /dev/null +++ b/system/devel/gcc/files/pisilinux/gcc_47_based-record_gcc_options.patch @@ -0,0 +1,69 @@ +diff -Nuar gcc-4.7.1.old/gcc/output.h gcc-4.7.1/gcc/output.h +--- gcc-4.7.1.old/gcc/output.h 2012-03-22 12:40:31.000000000 +0200 ++++ gcc-4.7.1/gcc/output.h 2012-07-22 08:03:30.669774211 +0300 +@@ -661,6 +661,7 @@ + extern void default_file_start (void); + extern void file_end_indicate_exec_stack (void); + extern void file_end_indicate_split_stack (void); ++extern void pisilinux_file_end_indicate_optflags (void); + + extern void default_elf_asm_output_external (FILE *file, tree, + const char *); +diff -Nuar gcc-4.7.1.old/gcc/toplev.c gcc-4.7.1/gcc/toplev.c +--- gcc-4.7.1.old/gcc/toplev.c 2012-01-05 17:08:42.000000000 +0200 ++++ gcc-4.7.1/gcc/toplev.c 2012-07-22 08:05:04.729598301 +0300 +@@ -674,6 +674,8 @@ + + /* Invoke registered plugin callbacks. */ + invoke_plugin_callbacks (PLUGIN_FINISH_UNIT, NULL); ++ ++ pisilinux_file_end_indicate_optflags (); + + /* This must be at the end. Some target ports emit end of file directives + into the assembly file here, and hence we can not output anything to the +diff -Nuar gcc-4.7.1.old/gcc/varasm.c gcc-4.7.1/gcc/varasm.c +--- gcc-4.7.1.old/gcc/varasm.c 2012-04-24 09:10:53.000000000 +0300 ++++ gcc-4.7.1/gcc/varasm.c 2012-07-22 08:01:31.878259309 +0300 +@@ -7165,14 +7165,34 @@ + switch_to_section (get_section (".note.GNU-stack", flags, NULL)); + } + +-/* Emit a special section directive to indicate that this object file +- was compiled with -fsplit-stack. This is used to let the linker +- detect calls between split-stack code and non-split-stack code, so +- that it can modify the split-stack code to allocate a sufficiently +- large stack. We emit another special section if there are any +- functions in this file which have the no_split_stack attribute, to +- prevent the linker from warning about being unable to convert the +- functions if they call non-split-stack code. */ ++/* This is a generic routine emitting a PisiLinux specific section for ++ QA check marks. */ ++ ++void ++pisilinux_file_end_indicate_optflags (void) ++{ ++ unsigned int flags = SECTION_DEBUG | SECTION_STRINGS | SECTION_MERGE | (SECTION_ENTSIZE & 1); ++ ++ /* ++ o/O: optimize was off/on ++ s/S: size optimisation was off/on ++ p/P: stack-protector was off/on ++ w/W: warnings were off/on ++ g/G: debug was off/on ++ */ ++ ++ char opts_buffer[6]; ++ ++ opts_buffer[0] = (optimize >= 2) ? 'O' : 'o'; ++ opts_buffer[1] = (optimize >= 1 && optimize_size) ? 'S' : 's'; ++ opts_buffer[2] = (flag_stack_protect >= 1) ? 'P' : 'p'; ++ opts_buffer[3] = (warn_uninitialized >= 1 && warn_sequence_point >= 1) ? 'W' : 'w'; ++ opts_buffer[4] = (debug_info_level > DINFO_LEVEL_NONE) ? 'G' : 'g'; ++ opts_buffer[5] = '\0'; ++ ++ switch_to_section (get_section (".comment.PISILINUX.OPTs", flags, NULL)); ++ ASM_OUTPUT_ASCII (asm_out_file, opts_buffer, strlen (opts_buffer) + 1); ++} + + void + file_end_indicate_split_stack (void) diff --git a/system/devel/gcc/pspec.xml b/system/devel/gcc/pspec.xml index 7e0f370c..c16388b6 100755 --- a/system/devel/gcc/pspec.xml +++ b/system/devel/gcc/pspec.xml @@ -34,6 +34,12 @@ zlib-devel elfutils + + + + pisilinux/64.patch + pisilinux/gcc_47_based-record_gcc_options.patch + @@ -131,23 +137,16 @@ /usr/share/info - c89 - c99 + gfilt + gSTLFilt.pl - + 2019-12-25 9.2.1 - Version bump with new toolchain. - Idris Kalp - idriskalp@gmail.com - - - 2019-12-13 - 9.2.0 - Version bump with new toolchain. + Version bump. Idris Kalp idriskalp@gmail.com From c69519ef8aaa5ca1e3a13772edbe757e5ee3de8a Mon Sep 17 00:00:00 2001 From: idriskalp Date: Wed, 25 Dec 2019 18:38:48 +0300 Subject: [PATCH 012/160] libcap 2.27 --- system/base/libcap/pspec.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/system/base/libcap/pspec.xml b/system/base/libcap/pspec.xml index 1f10f169..7fb21f29 100644 --- a/system/base/libcap/pspec.xml +++ b/system/base/libcap/pspec.xml @@ -13,7 +13,7 @@ library POSIX 1003.1e capabilities library libcap is a library for getting and setting POSIX.1e (formerly POSIX 6) draft 15 capabilities. - https://www.kernel.org/pub/linux/libs/security/linux-privs/libcap2/libcap-2.25.tar.xz + https://www.kernel.org/pub/linux/libs/security/linux-privs/libcap2/libcap-2.27.tar.xz attr-devel pam-devel @@ -67,6 +67,13 @@ + + 2019-2-25 + 2.27 + Version bump + Idris Kalp + idriskalp@gmail.com + 2018-07-15 2.25 From a947f0b2910335447cab5f14178cc2fd0f862633 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Wed, 25 Dec 2019 18:41:21 +0300 Subject: [PATCH 013/160] psmisc 23.2 --- system/base/psmisc/pspec.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/system/base/psmisc/pspec.xml b/system/base/psmisc/pspec.xml index 07dadb1f..f8dfe0c8 100644 --- a/system/base/psmisc/pspec.xml +++ b/system/base/psmisc/pspec.xml @@ -12,7 +12,7 @@ app:console A set of tools that use the proc filesystem PSmisc is a collection of small utilities using /proc file system, and providing the system administrator with some help in common tasks. - mirrors://sourceforge/psmisc/psmisc-23.1.tar.xz + mirrors://sourceforge/psmisc/psmisc-23.2.tar.xz ncurses-devel gettext @@ -37,6 +37,13 @@ + + 2019-12-25 + 23.2 + Version bump + Idris Kalp + idriskalp@gmail.com + 2018-07-15 23.1 From 152f46867d566b880f5fcadd6b688018718b8268 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Wed, 25 Dec 2019 18:43:00 +0300 Subject: [PATCH 014/160] grep 3.3 --- system/base/grep/pspec.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/system/base/grep/pspec.xml b/system/base/grep/pspec.xml index 87d052d9..23df6fd6 100644 --- a/system/base/grep/pspec.xml +++ b/system/base/grep/pspec.xml @@ -12,7 +12,7 @@ app:console GNU regular expression matcher The grep command searches one or more input files for lines containing a match to a specified pattern. By default, grep prints the matching lines. - http://ftp.gnu.org/gnu/grep/grep-3.1.tar.xz + http://ftp.gnu.org/gnu/grep/grep-3.3.tar.xz gettext libpcre-devel @@ -34,6 +34,13 @@ + + 2019-12-25 + 3.3 + Version bump + Idris Kalp + idriskalp@gmail.com + 2018-07-15 3.1 From af7fb27ad044ea66025e4b42b66a8a1d72914eb5 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Wed, 25 Dec 2019 18:43:58 +0300 Subject: [PATCH 015/160] libtool rebuild --- system/devel/libtool/pspec.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/system/devel/libtool/pspec.xml b/system/devel/libtool/pspec.xml index af2b4b37..39d3aca8 100644 --- a/system/devel/libtool/pspec.xml +++ b/system/devel/libtool/pspec.xml @@ -61,6 +61,13 @@ + + 2019-12-25 + 2.4.6 + Rebuild. + Idris Kalp + idriskalp@gmail.com + 2018-07-15 2.4.6 From aff769dbd8ec0cc7528f8197b8ce3beb36cb674d Mon Sep 17 00:00:00 2001 From: idriskalp Date: Wed, 25 Dec 2019 18:48:40 +0300 Subject: [PATCH 016/160] gperf rebuild --- system/base/gperf/pspec.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/system/base/gperf/pspec.xml b/system/base/gperf/pspec.xml index ebffa724..635eba89 100644 --- a/system/base/gperf/pspec.xml +++ b/system/base/gperf/pspec.xml @@ -29,6 +29,13 @@ + + 2019-12-25 + 3.1 + Rebuild + Idris Kalp + idriskalp@gmail.com + 2018-07-15 3.1 From ebe892c06ab6b05acd97383158172a7d4e230e61 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Wed, 25 Dec 2019 18:51:04 +0300 Subject: [PATCH 017/160] intltool rebuild --- system/devel/intltool/pspec.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/system/devel/intltool/pspec.xml b/system/devel/intltool/pspec.xml index e7ae5574..046e0108 100644 --- a/system/devel/intltool/pspec.xml +++ b/system/devel/intltool/pspec.xml @@ -39,6 +39,13 @@ + + 2019-12-25 + 0.51.0 + Rebuild + Idris Kalp + idriskalp@gmail.com + 2018-07-20 0.51.0 From e4384b847e6f15a69177e546d696dac25838d7ea Mon Sep 17 00:00:00 2001 From: idriskalp Date: Wed, 25 Dec 2019 18:52:35 +0300 Subject: [PATCH 018/160] kmod 26 --- system/base/kmod/pspec.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/system/base/kmod/pspec.xml b/system/base/kmod/pspec.xml index 3a3e9c80..3efe0e8b 100644 --- a/system/base/kmod/pspec.xml +++ b/system/base/kmod/pspec.xml @@ -12,7 +12,7 @@ app:console Linux kernel module management utilities Linux kernel module management utilities - https://www.kernel.org/pub/linux/utils/kernel/kmod/kmod-25.tar.xz + https://www.kernel.org/pub/linux/utils/kernel/kmod/kmod-26.tar.xz chrpath @@ -106,6 +106,13 @@ + + 2019-12-25 + 26 + Version bump + Idris Kalp + idriskalpta@gmail.com + 2019-08-03 25 From 9b84d7d649cef3462b6dccaf2c52dfedec6b4291 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Wed, 25 Dec 2019 19:11:40 +0300 Subject: [PATCH 019/160] re2c move to core --- system/devel/re2c/actions.py | 18 ++++++++++++ system/devel/re2c/pspec.xml | 54 ++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 system/devel/re2c/actions.py create mode 100644 system/devel/re2c/pspec.xml diff --git a/system/devel/re2c/actions.py b/system/devel/re2c/actions.py new file mode 100644 index 00000000..bd802f57 --- /dev/null +++ b/system/devel/re2c/actions.py @@ -0,0 +1,18 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# +# Licensed under the GNU General Public License, version 3. +# See the file http://www.gnu.org/licenses/gpl.txt + +from pisi.actionsapi import pisitools +from pisi.actionsapi import autotools + +def setup(): + autotools.rawConfigure() + +def build(): + autotools.make() + +def install(): + autotools.install() + diff --git a/system/devel/re2c/pspec.xml b/system/devel/re2c/pspec.xml new file mode 100644 index 00000000..950b493a --- /dev/null +++ b/system/devel/re2c/pspec.xml @@ -0,0 +1,54 @@ + + + + + re2c + https://github.com/skvadrik/re2c + + Ergün Salman + Poyraz76@pisilinux.org + + GPL + re2c + Libry + A tool for generating C-based recognizers from regular expressions + ACM Letters on Programming Languages and Systems (LOPLAS) + https://github.com/skvadrik/re2c/releases/download/1.0.3/re2c-1.0.3.tar.gz + + gcc + + + + re2c + + /usr/bin/ + /usr/lib/ + /usr/include/re2c/* + /usr/lib/pkgconfig/ + /usr/share/man/* + + + + + 2018-08-05 + 1.0.3 + Rebuild with new toolchain + Pisi Linux Community + admin@pisilinux.org + + + 2017-04-23 + 0.16 + Rebuild with new toolchain + Pisi Linux Community + admin@pisilinux.org + + + 2016-07-09 + 0.16 + First release + Ergün Salman + Poyraz76@pisilinux.org + + + From 0ec82731f8fe8ad79d2c7b6ae9e22b61b0869e9b Mon Sep 17 00:00:00 2001 From: idriskalp Date: Wed, 25 Dec 2019 19:12:13 +0300 Subject: [PATCH 020/160] asciidoc move to core --- office/docbook/asciidoc/actions.py | 32 +++++++++++ office/docbook/asciidoc/pspec.xml | 68 ++++++++++++++++++++++++ office/docbook/asciidoc/translations.xml | 8 +++ 3 files changed, 108 insertions(+) create mode 100644 office/docbook/asciidoc/actions.py create mode 100644 office/docbook/asciidoc/pspec.xml create mode 100644 office/docbook/asciidoc/translations.xml diff --git a/office/docbook/asciidoc/actions.py b/office/docbook/asciidoc/actions.py new file mode 100644 index 00000000..0738b261 --- /dev/null +++ b/office/docbook/asciidoc/actions.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +# +# Licensed under the GNU General Public License, version 3. +# See the file http://www.gnu.org/licenses/gpl.txt + +from pisi.actionsapi import autotools +from pisi.actionsapi import pisitools +from pisi.actionsapi import get + +def setup(): + autotools.configure("--prefix=/usr \ + --sysconfdir=/etc") + +def build(): + autotools.make() + +def install(): + autotools.rawInstall("DESTDIR=%s install-sh" % get.installDIR()) + + # Move data files and create symlinks for asciidoc to work + for d in ("dblatex", "docbook-xsl", "images", "javascripts", "stylesheets"): + pisitools.domove("/etc/asciidoc/%s" % d, "/usr/share/asciidoc") + pisitools.dosym("/usr/share/asciidoc/%s" % d, "/etc/asciidoc/%s" % d) + + # Python module + pisitools.insinto("/usr/lib/%s/site-packages" % get.curPYTHON(), "asciidocapi.py") + + # Vim syntax and filetype plugins + pisitools.insinto("/usr/share/vim/vimfiles/syntax/" , "vim/syntax/asciidoc.vim") + + pisitools.dodoc("BUGS", "CHANGELOG", "COPYING", "README") + pisitools.dodoc("docbook-xsl/asciidoc-docbook-xsl.txt", "filters/code/code-filter-readme.txt") diff --git a/office/docbook/asciidoc/pspec.xml b/office/docbook/asciidoc/pspec.xml new file mode 100644 index 00000000..0082d1a1 --- /dev/null +++ b/office/docbook/asciidoc/pspec.xml @@ -0,0 +1,68 @@ + + + + + asciidoc + http://www.methods.co.nz/asciidoc/ + + PisiLinux Community + admins@pisilinux.org + + GPLv2 + app:console + Text document format for writing documents + AsciiDoc is a text document format for writing short documents, articles, books and UNIX man pages. AsciiDoc files can be translated to HTML and DocBook markups using the asciidoc command. + mirrors://sourceforge/asciidoc/asciidoc-8.6.9.tar.gz + + + + + + + asciidoc + + docbook-xml + docbook-xsl + + + /etc + /usr/bin + /usr/lib/python* + /usr/share/asciidoc + /usr/share/vim + /usr/share/doc/asciidoc + /usr/share/man + + + + + + 2018-07-25 + 8.6.9 + Rebuild + Pisi Linux Community + admin@pisilinux.org + + + 2017-02-05 + 8.6.9 + Rebuild + Pisi Linux Community + admin@pisilinux.org + + + 2016-06-09 + 8.6.9 + Release Bump + Pisi Linux Community + admin@pisilinux.org + + + 2014-05-18 + 8.6.9 + First release + Alihan Öztürk + alihan@pisilinux.org + + + diff --git a/office/docbook/asciidoc/translations.xml b/office/docbook/asciidoc/translations.xml new file mode 100644 index 00000000..07ae986b --- /dev/null +++ b/office/docbook/asciidoc/translations.xml @@ -0,0 +1,8 @@ + + + + asciidoc + Belge hazırlamak için metin biçimlendirme sistemi + AsciiDoc, kısa belgeler, makaleler, kitaplar ve kılavuz sayfaları yazmak ve bunları HTML/Docbook'a dönüştürmek için kullanılır. + + From 20098dbcf3779f351147b80bf26d7b9c1e8cca51 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Wed, 25 Dec 2019 19:16:23 +0300 Subject: [PATCH 021/160] re2c ver bump --- system/devel/re2c/pspec.xml | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/system/devel/re2c/pspec.xml b/system/devel/re2c/pspec.xml index 950b493a..1483057d 100644 --- a/system/devel/re2c/pspec.xml +++ b/system/devel/re2c/pspec.xml @@ -13,22 +13,33 @@ Libry A tool for generating C-based recognizers from regular expressions ACM Letters on Programming Languages and Systems (LOPLAS) - https://github.com/skvadrik/re2c/releases/download/1.0.3/re2c-1.0.3.tar.gz + https://github.com/skvadrik/re2c/releases/download/1.3/re2c-1.3.tar.xz gcc re2c + + libgcc + /usr/bin/ /usr/lib/ /usr/include/re2c/* + /usr/share/re2c/* /usr/lib/pkgconfig/ /usr/share/man/* + + 2019-12-25 + 1.3 + Version bump + Pisi Linux Community + admin@pisilinux.org + 2018-08-05 1.0.3 From 848945acacb5a287980d176bda00427295477e58 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Wed, 25 Dec 2019 19:19:14 +0300 Subject: [PATCH 022/160] ninja move to core and rebuild --- system/devel/ninja/actions.py | 42 +++++++++++ system/devel/ninja/files/LFS.patch | 13 ++++ system/devel/ninja/pspec.xml | 104 ++++++++++++++++++++++++++++ system/devel/ninja/translations.xml | 8 +++ 4 files changed, 167 insertions(+) create mode 100644 system/devel/ninja/actions.py create mode 100755 system/devel/ninja/files/LFS.patch create mode 100644 system/devel/ninja/pspec.xml create mode 100644 system/devel/ninja/translations.xml diff --git a/system/devel/ninja/actions.py b/system/devel/ninja/actions.py new file mode 100644 index 00000000..1935321e --- /dev/null +++ b/system/devel/ninja/actions.py @@ -0,0 +1,42 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# +# Licensed under the GNU General Public License, version 3. +# See the file http://www.gnu.org/licenses/gpl.txt + +from pisi.actionsapi import pythonmodules +from pisi.actionsapi import pisitools +from pisi.actionsapi import shelltools +from pisi.actionsapi import get + + +def build(): + shelltools.system("""sed -i '/int Guess/a \ + int j = 0;\ + char* jobs = getenv( "NINJAJOBS" );\ + if ( jobs != NULL ) j = atoi( jobs );\ + if ( j > 0 ) return j;\ + ' src/ninja.cc""") + + shelltools.system("python configure.py --bootstrap") + shelltools.system("asciidoc doc/manual.asciidoc") + #shelltools.system("emacs -Q --batch -f batch-byte-compile misc/ninja-mode.el") + +def check(): + #needs new package gtest -> ignore it for now + shelltools.system("python ./configure.py") + shelltools.system("./ninja ninja_test") + shelltools.system("./ninja_test --gtest_filter=-SubprocessTest.SetWithLots") + +def install(): + pisitools.dobin("ninja", "/usr/bin") + + pisitools.insinto("/usr/share/bash-completion/completions", "misc/bash-completion", "ninja") + pisitools.insinto("/usr/share/emacs/site-lisp", "misc/ninja-mode.el") + #pisitools.insinto("/usr/share/emacs/site-lisp", "misc/ninja-mode.elc") + pisitools.insinto("/usr/share/vim/vimfiles/syntax", "misc/ninja.vim") + pisitools.insinto("/usr/share/zsh/site-functions", "misc/zsh-completion", "_ninja") + + pisitools.dodoc("HACKING.md", "COPYING", "RELEASING", "README", "doc/manual.asciidoc") + + pisitools.dohtml("doc/manual.html") diff --git a/system/devel/ninja/files/LFS.patch b/system/devel/ninja/files/LFS.patch new file mode 100755 index 00000000..c8a5025b --- /dev/null +++ b/system/devel/ninja/files/LFS.patch @@ -0,0 +1,13 @@ +Largefile patch +https://github.com/martine/ninja/issues/829 + +--- ninja-1.5.1/configure.py~ 2014-10-26 22:45:18.000000000 +0200 ++++ ninja-1.5.1/configure.py 2014-10-26 22:45:26.284641172 +0200 +@@ -142,6 +142,7 @@ + '-fno-exceptions', + '-fvisibility=hidden', '-pipe', + '-Wno-missing-field-initializers', ++ '-D_LARGEFILE_SOURCE', '-D_FILE_OFFSET_BITS=64', + '-DNINJA_PYTHON="%s"' % options.with_python] + if options.debug: + cflags += ['-D_GLIBCXX_DEBUG', '-D_GLIBCXX_DEBUG_PEDANTIC'] diff --git a/system/devel/ninja/pspec.xml b/system/devel/ninja/pspec.xml new file mode 100644 index 00000000..f9a2a444 --- /dev/null +++ b/system/devel/ninja/pspec.xml @@ -0,0 +1,104 @@ + + + + + ninja + https://ninja-build.org/ + + Stefan Gronewold(groni) + groni@pisilinux.org + + LGPLv2 + app:console + Ninja is a small build system with a focus on speed. + Ninja is a small build system with a focus on speed. + https://github.com/ninja-build/ninja/archive/v1.9.0.tar.gz + + re2c + asciidoc + + + + + + + + + + ninja + + libgcc + + + /usr/bin + /usr/share + /usr/share/doc + + + + + + 2019-12-25 + 1.9.0 + Rebuild + Idris Kalp + idriskalp@gmail.com + + + 2019-05-31 + 1.9.0 + Version bump. + Mustafa Cinasal + muscnsl@gmail.com + + + 2019-02-01 + 1.8.2 + Rebuild. + Mustafa Cinasal + muscnsl@gmail.com + + + 2018-08-05 + 1.8.2 + Rebuild. + Mustafa Cinasal + muscnsl@gmail.com + + + 2017-10-08 + 1.8.2 + Version Bump. + Mustafa Cinasal + muscnsl@gmail.com + + + 2017-02-22 + 1.7.2 + Release Bump. + Stefan Gronewold + groni@pisilinux.org + + + 2016-07-09 + 1.7.1 + Version Bump + Ergün Salman + poyraz76@pisilinux.org + + + 2016-06-09 + 1.6.0 + Release Bump + Pisi Linux Community + admin@pisilinux.org + + + 2015-08-25 + 1.6.0 + First release + Vedat Demir + vedat@pisilinux.org + + + diff --git a/system/devel/ninja/translations.xml b/system/devel/ninja/translations.xml new file mode 100644 index 00000000..22df4837 --- /dev/null +++ b/system/devel/ninja/translations.xml @@ -0,0 +1,8 @@ + + + + ninja + Ninja, hız odaklı bir inşa sistemidir. + Ninja is a small build system with a focus on speed. + + From 0daf7a45e1b5b78346b4e43c258e254215056231 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Wed, 25 Dec 2019 19:21:08 +0300 Subject: [PATCH 023/160] check rebuild --- system/devel/check/pspec.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/system/devel/check/pspec.xml b/system/devel/check/pspec.xml index 841047a0..092dcf94 100644 --- a/system/devel/check/pspec.xml +++ b/system/devel/check/pspec.xml @@ -51,6 +51,13 @@ + + 2019-12-25 + 0.12 + Rebuild + Idris Kalp + idriskalp@gmail.com + 2018-07-15 0.12 From ec409af5d6ca3beab4d9b4a69f2a2578c2ba35e3 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Wed, 25 Dec 2019 19:22:53 +0300 Subject: [PATCH 024/160] groff 1.22.4 --- system/base/groff/pspec.xml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/system/base/groff/pspec.xml b/system/base/groff/pspec.xml index b1e69031..19096116 100644 --- a/system/base/groff/pspec.xml +++ b/system/base/groff/pspec.xml @@ -14,13 +14,13 @@ app:console A document formatting system groff is a document formatting system. Groff takes standard text and formatting commands as input and produces formatted output. - http://ftp.gnu.org/gnu/groff/groff-1.22.3.tar.gz + http://ftp.gnu.org/gnu/groff/groff-1.22.4.tar.gz texinfo groff-1.19.2-man-unicode-dashes.patch - groff-1.22.3-parallel-mom.patch + @@ -52,6 +52,13 @@ + + 2019-12-25 + 1.22.4 + Version bump + Idris Kalp + idriskalp@gmail.com + 2018-07-15 1.22.3 From fdaa488d4a2dd0c28253baba6e5545bffa86acb4 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Wed, 25 Dec 2019 19:25:13 +0300 Subject: [PATCH 025/160] less 551 --- system/base/less/pspec.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/system/base/less/pspec.xml b/system/base/less/pspec.xml index 015674d2..568981f6 100644 --- a/system/base/less/pspec.xml +++ b/system/base/less/pspec.xml @@ -12,7 +12,7 @@ app:console Excellent text file viewer The less utility is a text file browser that resembles more, but has more capabilities. Less allows you to move backwards in the file as well as forwards. Since less doesn't have to read the entire input file before it starts, less starts up more quickly than text editors (for example, vi). - http://www.greenwoodsoftware.com/less/less-530.tar.gz + http://www.greenwoodsoftware.com/less/less-551.tar.gz ncurses-devel @@ -38,6 +38,13 @@ + + 2019-12-25 + 551 + Version bump + Idris Kalp + idriskalp@gmail.com + 2018-07-15 530 From 51a8c075aec5987e3474fde1f8d5c9025bad342a Mon Sep 17 00:00:00 2001 From: idriskalp Date: Wed, 25 Dec 2019 19:26:31 +0300 Subject: [PATCH 026/160] gzip 1.10 --- system/base/gzip/pspec.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/system/base/gzip/pspec.xml b/system/base/gzip/pspec.xml index 5d5f8bc5..3bb94e60 100644 --- a/system/base/gzip/pspec.xml +++ b/system/base/gzip/pspec.xml @@ -13,7 +13,7 @@ app:console Standard GNU compressor gzip (GNU zip) is a popular data compression program written for the GNU project. - http://ftp.gnu.org/gnu/gzip/gzip-1.9.tar.xz + http://ftp.gnu.org/gnu/gzip/gzip-1.10.tar.xz @@ -27,6 +27,13 @@ + + 2019-12-25 + 1.10 + Version bump + Idris Kalp + idriskalp@gmail.com + 2018-07-15 1.9 From fea1557c8067b9a81c016a1c7e48395d83fb043f Mon Sep 17 00:00:00 2001 From: idriskalp Date: Wed, 25 Dec 2019 19:27:44 +0300 Subject: [PATCH 027/160] kbd 2.2.0 --- .../archlinux/kbd-fix-loadkmap-compat.patch | 14 + .../files/blfs/kbd-2.2.0-backspace-1.patch | 250 ++++++++++++++++++ system/base/kbd/pspec.xml | 25 +- 3 files changed, 282 insertions(+), 7 deletions(-) create mode 100644 system/base/kbd/files/archlinux/kbd-fix-loadkmap-compat.patch create mode 100644 system/base/kbd/files/blfs/kbd-2.2.0-backspace-1.patch diff --git a/system/base/kbd/files/archlinux/kbd-fix-loadkmap-compat.patch b/system/base/kbd/files/archlinux/kbd-fix-loadkmap-compat.patch new file mode 100644 index 00000000..317cb5f4 --- /dev/null +++ b/system/base/kbd/files/archlinux/kbd-fix-loadkmap-compat.patch @@ -0,0 +1,14 @@ +diff --git a/src/libkeymap/dump.c b/src/libkeymap/dump.c +index 83ac351..a7ba1e5 100644 +--- a/src/libkeymap/dump.c ++++ b/src/libkeymap/dump.c +@@ -72,7 +72,7 @@ int lk_dump_bkeymap(struct lk_ctx *ctx, FILE *fd) + continue; + + for (j = 0; j < NR_KEYS / 2; j++) { +- int v = lk_get_key(ctx, i, j); ++ short v = (short)lk_get_key(ctx, i, j); + + if (fwrite(&v, sizeof(v), 1, fd) != 1) + goto fail; + diff --git a/system/base/kbd/files/blfs/kbd-2.2.0-backspace-1.patch b/system/base/kbd/files/blfs/kbd-2.2.0-backspace-1.patch new file mode 100644 index 00000000..8fec1718 --- /dev/null +++ b/system/base/kbd/files/blfs/kbd-2.2.0-backspace-1.patch @@ -0,0 +1,250 @@ +Submitted By: Matt Burgess +Date: 2008-12-06 +Initial Package Version: 1.15 +Upstream Status: Not submitted, possibly incomplete +Description: Makes Backspace and Delete keys consistent in all i386 keymaps. +Makes the Backspace key send character code 127, and Delete send a well known +escape sequence. Obsoletes the /etc/kbd/bs-sends-del file for i386. + +Original patch for 1.12 by Alexander Patrakov. +Updated for 1.13 (drop ru.map, the change is upstream, and add ru_win.map, +ru-cp1251.map) by Ken Moffat . +Re-diffed against 1.15 by Matt Burgess . + +diff -Naur kbd-1.15.orig/data/keymaps/i386/dvorak/dvorak-l.map kbd-1.15/data/keymaps/i386/dvorak/dvorak-l.map +--- kbd-1.15.orig/data/keymaps/i386/dvorak/dvorak-l.map 2008-06-20 12:36:01.000000000 +0100 ++++ kbd-1.15/data/keymaps/i386/dvorak/dvorak-l.map 2008-12-03 22:27:55.000000000 +0000 +@@ -43,7 +43,7 @@ + keycode 11 = three numbersign + keycode 12 = two at + keycode 13 = one exclam +- keycode 14 = BackSpace Delete ++ keycode 14 = Delete Delete + ! -------------------------------------------------------------------------- + ! Row 3 + ! -------------------------------------------------------------------------- +diff -Naur kbd-1.15.orig/data/keymaps/i386/dvorak/dvorak-r.map kbd-1.15/data/keymaps/i386/dvorak/dvorak-r.map +--- kbd-1.15.orig/data/keymaps/i386/dvorak/dvorak-r.map 2008-06-20 12:36:01.000000000 +0100 ++++ kbd-1.15/data/keymaps/i386/dvorak/dvorak-r.map 2008-12-03 22:28:13.000000000 +0000 +@@ -43,7 +43,7 @@ + keycode 11 = slash question + keycode 12 = bracketleft braceleft + keycode 13 = bracketright braceright +- keycode 14 = BackSpace Delete ++ keycode 14 = Delete Delete + ! -------------------------------------------------------------------------- + ! Row 3 + ! -------------------------------------------------------------------------- +diff -Naur kbd-1.15.orig/data/keymaps/i386/fgGIod/tr_f-latin5.map kbd-1.15/data/keymaps/i386/fgGIod/tr_f-latin5.map +--- kbd-1.15.orig/data/keymaps/i386/fgGIod/tr_f-latin5.map 2008-10-23 20:03:58.000000000 +0100 ++++ kbd-1.15/data/keymaps/i386/fgGIod/tr_f-latin5.map 2008-12-03 22:40:32.000000000 +0000 +@@ -51,7 +51,7 @@ + alt keycode 12 = Meta_minus + keycode 13 = minus underscore + alt keycode 13 = Meta_equal +-keycode 14 = BackSpace Delete ++keycode 14 = Delete Delete + alt keycode 14 = Meta_Delete + keycode 15 = Tab Meta_Tab + alt keycode 15 = Meta_Tab +diff -Naur kbd-1.15.orig/data/keymaps/i386/qwerty/lt.l4.map kbd-1.15/data/keymaps/i386/qwerty/lt.l4.map +--- kbd-1.15.orig/data/keymaps/i386/qwerty/lt.l4.map 2008-10-23 20:03:59.000000000 +0100 ++++ kbd-1.15/data/keymaps/i386/qwerty/lt.l4.map 2008-12-03 22:42:14.000000000 +0000 +@@ -205,7 +205,7 @@ + # edit this if you want the key above to delete symbols above + # cursor, not before. + keycode 14 = \ +- BackSpace BackSpace BackSpace BackSpace \ ++ Delete Delete Delete Delete \ + Delete Delete Delete Delete \ + Meta_BackSpace Meta_BackSpace Meta_BackSpace Meta_BackSpace \ + Meta_Delete Meta_Delete Meta_Delete Meta_Delete +@@ -506,7 +506,7 @@ + + # Edit this if you want strict VT100 emulation. + string F111 = "\033[3$" +-keycode 111 = Delete F111 Delete F111 \ ++keycode 111 = Remove F111 Remove F111 \ + Remove Remove Remove Remove \ + Meta_Delete Meta_Delete Meta_Delete Meta_Delete \ + Boot Boot Boot Boot +diff -Naur kbd-1.15.orig/data/keymaps/i386/qwerty/lt.map kbd-1.15/data/keymaps/i386/qwerty/lt.map +--- kbd-1.15.orig/data/keymaps/i386/qwerty/lt.map 2008-10-23 20:03:59.000000000 +0100 ++++ kbd-1.15/data/keymaps/i386/qwerty/lt.map 2008-12-03 22:42:58.000000000 +0000 +@@ -204,7 +204,7 @@ + # edit this if you want the key above to delete symbols above + # cursor, not before. + keycode 14 = \ +- BackSpace BackSpace BackSpace BackSpace \ ++ Delete Delete Delete Delete \ + Delete Delete Delete Delete \ + Meta_BackSpace Meta_BackSpace Meta_BackSpace Meta_BackSpace \ + Meta_Delete Meta_Delete Meta_Delete Meta_Delete +@@ -505,7 +505,7 @@ + + # Edit this if you want strict VT100 emulation. + string F111 = "\033[3$" +-keycode 111 = Delete F111 Delete F111 \ ++keycode 111 = Remove F111 Remove F111 \ + Remove Remove Remove Remove \ + Meta_Delete Meta_Delete Meta_Delete Meta_Delete \ + Boot Boot Boot Boot +diff -Naur kbd-1.15.orig/data/keymaps/i386/qwerty/no-latin1.map kbd-1.15/data/keymaps/i386/qwerty/no-latin1.map +--- kbd-1.15.orig/data/keymaps/i386/qwerty/no-latin1.map 2008-06-20 12:36:00.000000000 +0100 ++++ kbd-1.15/data/keymaps/i386/qwerty/no-latin1.map 2008-12-03 22:44:25.000000000 +0000 +@@ -3,7 +3,7 @@ + # Send comments to Kjetil T. Homme + include "linux-with-alt-and-altgr" + plain keycode 83 = KP_Comma +- plain keycode 111 = Delete # "Remove" originally, weird... ++ plain keycode 111 = Remove + strings as usual + + keycode 1 = Escape +diff -Naur kbd-1.15.orig/data/keymaps/i386/qwerty/ru1.map kbd-1.15/data/keymaps/i386/qwerty/ru1.map +--- kbd-1.15.orig/data/keymaps/i386/qwerty/ru1.map 2008-10-23 20:03:59.000000000 +0100 ++++ kbd-1.15/data/keymaps/i386/qwerty/ru1.map 2008-12-03 22:45:32.000000000 +0000 +@@ -143,8 +143,8 @@ + + # The keycode "0xFF" is too dangerous for many programs (including emacs). + # So let it be bracket instead of Hard Sign. +-# altgr keycode 27 = +0xDF +-# altgr shift keycode 27 = +0xFF ++altgr keycode 27 = +0xDF ++altgr shift keycode 27 = +0xFF + control keycode 27 = Control_bracketright + altgr control keycode 27 = Control_bracketright + alt keycode 27 = Meta_bracketright +diff -Naur kbd-1.15.orig/data/keymaps/i386/qwerty/ru2.map kbd-1.15/data/keymaps/i386/qwerty/ru2.map +--- kbd-1.15.orig/data/keymaps/i386/qwerty/ru2.map 2008-10-23 20:03:59.000000000 +0100 ++++ kbd-1.15/data/keymaps/i386/qwerty/ru2.map 2008-12-03 22:46:15.000000000 +0000 +@@ -46,7 +46,7 @@ + alt keycode 12 = Meta_minus + keycode 13 = equal plus equal plus + alt keycode 13 = Meta_equal +- keycode 14 = BackSpace BackSpace BackSpace BackSpace ++ keycode 14 = Delete Delete Delete Delete + alt keycode 14 = Meta_Delete + keycode 15 = Tab Tab Tab Tab + alt keycode 15 = Meta_Tab +diff -Naur kbd-1.15.orig/data/keymaps/i386/qwerty/ru-cp1251.map kbd-1.15/data/keymaps/i386/qwerty/ru-cp1251.map +--- kbd-1.15.orig/data/keymaps/i386/qwerty/ru-cp1251.map 2008-10-23 20:03:59.000000000 +0100 ++++ kbd-1.15/data/keymaps/i386/qwerty/ru-cp1251.map 2008-12-03 22:47:12.000000000 +0000 +@@ -39,7 +39,7 @@ + alt keycode 12 = Meta_minus + keycode 13 = equal plus equal plus + alt keycode 13 = Meta_equal +- keycode 14 = BackSpace ++ keycode 14 = Delete + alt keycode 14 = Meta_Delete + keycode 15 = Tab + alt keycode 15 = Meta_Tab +diff -Naur kbd-1.15.orig/data/keymaps/i386/qwerty/ru-ms.map kbd-1.15/data/keymaps/i386/qwerty/ru-ms.map +--- kbd-1.15.orig/data/keymaps/i386/qwerty/ru-ms.map 2008-10-23 20:03:59.000000000 +0100 ++++ kbd-1.15/data/keymaps/i386/qwerty/ru-ms.map 2008-12-03 22:48:10.000000000 +0000 +@@ -89,8 +89,8 @@ + altgr alt keycode 13 = Meta_equal + shift alt keycode 13 = Meta_plus + altgr shift alt keycode 13 = Meta_plus +- keycode 14 = BackSpace BackSpace BackSpace BackSpace +-# keycode 14 = Delete Delete Delete Delete ++# keycode 14 = BackSpace BackSpace BackSpace BackSpace ++ keycode 14 = Delete Delete Delete Delete + alt keycode 14 = Meta_Delete + altgr alt keycode 14 = Meta_Delete + keycode 15 = Tab Tab Tab Tab +diff -Naur kbd-1.15.orig/data/keymaps/i386/qwerty/ru_win.map kbd-1.15/data/keymaps/i386/qwerty/ru_win.map +--- kbd-1.15.orig/data/keymaps/i386/qwerty/ru_win.map 2008-10-23 20:03:59.000000000 +0100 ++++ kbd-1.15/data/keymaps/i386/qwerty/ru_win.map 2008-12-03 22:49:17.000000000 +0000 +@@ -42,7 +42,7 @@ + alt keycode 12 = Meta_minus + keycode 13 = equal plus equal plus + alt keycode 13 = Meta_equal +- keycode 14 = BackSpace BackSpace BackSpace BackSpace ++ keycode 14 = Delete Delete Delete Delete + alt keycode 14 = Meta_Delete + keycode 15 = Tab Tab Tab Tab + alt keycode 15 = Meta_Tab +diff -Naur kbd-1.15.orig/data/keymaps/i386/qwerty/se-ir209.map kbd-1.15/data/keymaps/i386/qwerty/se-ir209.map +--- kbd-1.15.orig/data/keymaps/i386/qwerty/se-ir209.map 2008-10-23 20:03:59.000000000 +0100 ++++ kbd-1.15/data/keymaps/i386/qwerty/se-ir209.map 2008-12-03 22:50:18.000000000 +0000 +@@ -345,7 +345,7 @@ + keycode 109 = Next Scroll_Forward + keycode 110 = Insert + +- keycode 111 = Delete # "Remove" originally, weird... ++ keycode 111 = Remove + control alt keycode 111 = Boot + control altgr keycode 111 = Boot + +diff -Naur kbd-1.15.orig/data/keymaps/i386/qwerty/se-lat6.map kbd-1.15/data/keymaps/i386/qwerty/se-lat6.map +--- kbd-1.15.orig/data/keymaps/i386/qwerty/se-lat6.map 2008-10-23 20:03:59.000000000 +0100 ++++ kbd-1.15/data/keymaps/i386/qwerty/se-lat6.map 2008-12-03 22:50:44.000000000 +0000 +@@ -374,6 +374,6 @@ + keycode 109 = Next Scroll_Forward + keycode 110 = Insert + +- keycode 111 = Delete # "Remove" originally, weird... ++ keycode 111 = Remove + control alt keycode 111 = Boot + control altgr keycode 111 = Boot +diff -Naur kbd-1.15.orig/data/keymaps/i386/qwerty/tr_q-latin5.map kbd-1.15/data/keymaps/i386/qwerty/tr_q-latin5.map +--- kbd-1.15.orig/data/keymaps/i386/qwerty/tr_q-latin5.map 2008-10-23 20:03:59.000000000 +0100 ++++ kbd-1.15/data/keymaps/i386/qwerty/tr_q-latin5.map 2008-12-03 22:52:09.000000000 +0000 +@@ -49,7 +49,7 @@ + alt keycode 12 = Meta_minus + keycode 13 = minus underscore + alt keycode 13 = Meta_equal +-keycode 14 = BackSpace Delete ++keycode 14 = Delete Delete + alt keycode 14 = Meta_Delete + keycode 15 = Tab Meta_Tab + alt keycode 15 = Meta_Tab +diff -Naur kbd-1.15.orig/data/keymaps/i386/qwerty/ua.map kbd-1.15/data/keymaps/i386/qwerty/ua.map +--- kbd-1.15.orig/data/keymaps/i386/qwerty/ua.map 2008-10-23 20:03:59.000000000 +0100 ++++ kbd-1.15/data/keymaps/i386/qwerty/ua.map 2008-12-03 22:52:52.000000000 +0000 +@@ -249,7 +249,7 @@ + shift ctrll ctrlr keycode 13 = plus + alt ctrll ctrlr keycode 13 = Meta_equal + shift alt ctrll ctrlr keycode 13 = Meta_plus +-keycode 14 = BackSpace Delete ++keycode 14 = Delete Delete + control keycode 14 = BackSpace + alt keycode 14 = Meta_Delete + ctrlr keycode 14 = BackSpace +diff -Naur kbd-1.15.orig/data/keymaps/i386/qwerty/ua-utf.map kbd-1.15/data/keymaps/i386/qwerty/ua-utf.map +--- kbd-1.15.orig/data/keymaps/i386/qwerty/ua-utf.map 2008-10-23 20:03:59.000000000 +0100 ++++ kbd-1.15/data/keymaps/i386/qwerty/ua-utf.map 2008-12-03 22:53:36.000000000 +0000 +@@ -250,7 +250,7 @@ + shift ctrll ctrlr keycode 13 = plus + alt ctrll ctrlr keycode 13 = Meta_equal + shift alt ctrll ctrlr keycode 13 = Meta_plus +-keycode 14 = BackSpace Delete ++keycode 14 = Delete Delete + control keycode 14 = BackSpace + alt keycode 14 = Meta_Delete + ctrlr keycode 14 = BackSpace +diff -Naur kbd-1.15.orig/data/keymaps/i386/qwerty/ua-utf-ws.map kbd-1.15/data/keymaps/i386/qwerty/ua-utf-ws.map +--- kbd-1.15.orig/data/keymaps/i386/qwerty/ua-utf-ws.map 2008-10-23 20:03:59.000000000 +0100 ++++ kbd-1.15/data/keymaps/i386/qwerty/ua-utf-ws.map 2008-12-03 22:54:06.000000000 +0000 +@@ -260,7 +260,7 @@ + shift ctrll ctrlr keycode 13 = plus + alt ctrll ctrlr keycode 13 = Meta_equal + shift alt ctrll ctrlr keycode 13 = Meta_plus +-keycode 14 = BackSpace Delete ++keycode 14 = Delete Delete + control keycode 14 = BackSpace + alt keycode 14 = Meta_Delete + ctrlr keycode 14 = BackSpace +diff -Naur kbd-1.15.orig/data/keymaps/i386/qwerty/ua-ws.map kbd-1.15/data/keymaps/i386/qwerty/ua-ws.map +--- kbd-1.15.orig/data/keymaps/i386/qwerty/ua-ws.map 2008-10-23 20:03:59.000000000 +0100 ++++ kbd-1.15/data/keymaps/i386/qwerty/ua-ws.map 2008-12-03 22:54:23.000000000 +0000 +@@ -260,7 +260,7 @@ + shift ctrll ctrlr keycode 13 = plus + alt ctrll ctrlr keycode 13 = Meta_equal + shift alt ctrll ctrlr keycode 13 = Meta_plus +-keycode 14 = BackSpace Delete ++keycode 14 = Delete Delete + control keycode 14 = BackSpace + alt keycode 14 = Meta_Delete + ctrlr keycode 14 = BackSpace diff --git a/system/base/kbd/pspec.xml b/system/base/kbd/pspec.xml index e9854a87..3afb078c 100644 --- a/system/base/kbd/pspec.xml +++ b/system/base/kbd/pspec.xml @@ -12,18 +12,21 @@ app:console Keyboard and console utilities The kbd package contains keytable files and keyboard utilities compatible with kernel version 1.1.54 and later. - https://www.kernel.org/pub/linux/utils/kbd/kbd-2.0.4.tar.xz - http://source.pisilinux.org/1.0/kbd-latarcyrheb-16-fixed.tar.bz2 - http://source.pisilinux.org/1.0/kbd-latsun-fonts.tar.bz2 - http://source.pisilinux.org/1.0/ro_maps.tar.bz2 + https://www.kernel.org/pub/linux/utils/kbd/kbd-2.2.0.tar.xz + https://sourceforge.net/projects/pisilinux/files/source/kbd-latarcyrheb-16-fixed.tar.bz2 + https://sourceforge.net/projects/pisilinux/files/source/kbd-latsun-fonts.tar.bz2 + https://sourceforge.net/projects/pisilinux/files/source/ro_maps.tar.bz2 gettext gzip pam-devel - check-devel + check-devel - + + blfs/kbd-2.2.0-backspace-1.patch + + mandriva/kbd-1.15-mandriva.patch mandriva/kbd-1.15-tilde_twosuperior_french_kbd.patch mandriva/kbd-1.12-data_thai.patch @@ -32,6 +35,7 @@ archlinux/fix-euro2.patch + archlinux/kbd-fix-loadkmap-compat.patch pisilinux/unicode_start-default-font.patch @@ -40,7 +44,7 @@ pisilinux/trq-capslock-fix.patch pisilinux/currency.patch pisilinux/trf-keymap-fixes.patch - pisilinux/trf-capslock-fix.patch + pisilinux/trf-capslock-fix.patch @@ -72,6 +76,13 @@ + + 2019-12-25 + 2.2.0 + Version bump + Idris Kalp + idriskalp@gmail.com + 2018-07-15 2.0.4 From f2acfa320452fc4ded3939913dcb230c4d958b90 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Wed, 25 Dec 2019 19:30:42 +0300 Subject: [PATCH 028/160] libpipeline 1.5.1 --- system/base/libpipeline/pspec.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/system/base/libpipeline/pspec.xml b/system/base/libpipeline/pspec.xml index f939b74a..a192cf3e 100644 --- a/system/base/libpipeline/pspec.xml +++ b/system/base/libpipeline/pspec.xml @@ -12,7 +12,7 @@ library pipeline manipulation library libpipeline is a C library for manipulating pipelines of subprocesses in a flexible and convenient way. - http://download.savannah.gnu.org/releases/libpipeline/libpipeline-1.5.0.tar.gz + http://mirror.lihnidos.org/GNU/savannah/libpipeline/libpipeline-1.5.1.tar.gz @@ -38,6 +38,13 @@ + + 2019-12-25 + 1.5.1 + Version bump + Idris Kalp + idriskalp@gmail.com + 2018-07-15 1.5.0 From 3231f5496be64a046bee42f190577d784522554c Mon Sep 17 00:00:00 2001 From: idriskalp Date: Wed, 25 Dec 2019 19:36:13 +0300 Subject: [PATCH 029/160] gc 8.0.4 --- system/devel/gc/pspec.xml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/system/devel/gc/pspec.xml b/system/devel/gc/pspec.xml index 3afaa659..55aaa063 100644 --- a/system/devel/gc/pspec.xml +++ b/system/devel/gc/pspec.xml @@ -13,7 +13,7 @@ library A garbage collector for C and C++ The Boehm-Demers-Weiser conservative garbage collector can be used as a garbage collecting replacement for C malloc or C++ new. - http://hboehm.info/gc/gc_source/gc-7.6.4.tar.gz + https://hboehm.info/gc/gc_source/gc-8.0.4.tar.gz libatomic_ops-devel @@ -30,6 +30,7 @@ /usr/lib /usr/share/doc + /usr/share/man @@ -46,6 +47,13 @@ + + 2019-12-25 + 8.0.4 + Version bump. + Idris Kalp + idriskalp@gmail.com + 2018-07-20 7.6.4 From f4856f6ce95bdd6bae209b81c162118dd97f0c46 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Wed, 25 Dec 2019 19:36:30 +0300 Subject: [PATCH 030/160] libatomic_ops 7.6.10 --- system/devel/libatomic_ops/pspec.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/system/devel/libatomic_ops/pspec.xml b/system/devel/libatomic_ops/pspec.xml index bcd008c8..81ae6c50 100644 --- a/system/devel/libatomic_ops/pspec.xml +++ b/system/devel/libatomic_ops/pspec.xml @@ -13,7 +13,7 @@ library Atomic memory update operations library libatomic_ops provides implementations for atomic memory update operations on a number of architectures. This allows direct use of these in reasonably portable code. - http://www.ivmaisoft.com/_bin/atomic_ops/libatomic_ops-7.6.4.tar.gz + http://www.ivmaisoft.com/_bin/atomic_ops/libatomic_ops-7.6.10.tar.gz @@ -38,6 +38,13 @@ + + 2019-12-25 + 7.6.10 + Version bump. + Idris Kalp + idriskalp@gmail.com + 2018-07-15 7.6.4 From 2a478109e6af302f0a7e25023c43df48dc0c215e Mon Sep 17 00:00:00 2001 From: idriskalp Date: Wed, 25 Dec 2019 19:37:18 +0300 Subject: [PATCH 031/160] make rebuild --- system/devel/make/pspec.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/system/devel/make/pspec.xml b/system/devel/make/pspec.xml index cd8c1def..e8ead999 100644 --- a/system/devel/make/pspec.xml +++ b/system/devel/make/pspec.xml @@ -43,6 +43,13 @@ + + 2019-12-25 + 4.2.1 + Rebuild. + Idris Kalp + idriskalp@gmail.com + 2018-07-20 4.2.1 From 3b84ccd8668d93571a8a80870534308f933ecca0 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Wed, 25 Dec 2019 19:38:19 +0300 Subject: [PATCH 032/160] gc build fix --- system/devel/gc/actions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/devel/gc/actions.py b/system/devel/gc/actions.py index 94d9b837..214fd0eb 100644 --- a/system/devel/gc/actions.py +++ b/system/devel/gc/actions.py @@ -29,6 +29,6 @@ def check(): def install(): autotools.rawInstall("DESTDIR=%s" % get.installDIR()) - pisitools.dodoc("ChangeLog", "doc/README.linux", "doc/*.html") + pisitools.dodoc("ChangeLog", "doc/README.linux") #pisitools.removeDir("/usr/share/gc") From 04036d8b4ad27919d75b6c26a595b16acfdb12db Mon Sep 17 00:00:00 2001 From: idriskalp Date: Wed, 25 Dec 2019 19:44:35 +0300 Subject: [PATCH 033/160] man-db 2.8.6.1 --- system/base/man-db/actions.py | 1 + system/base/man-db/pspec.xml | 13 ++++++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/system/base/man-db/actions.py b/system/base/man-db/actions.py index 3a6993b2..ee140f2a 100644 --- a/system/base/man-db/actions.py +++ b/system/base/man-db/actions.py @@ -25,6 +25,7 @@ def install(): autotools.rawInstall("DESTDIR=%s" % get.installDIR()) pisitools.dodir("/var/cache/man") + pisitools.removeDir("/lib") # These are shipped with groff #pisitools.remove("/usr/bin/zsoelim") diff --git a/system/base/man-db/pspec.xml b/system/base/man-db/pspec.xml index a8d1676c..e91d02b2 100644 --- a/system/base/man-db/pspec.xml +++ b/system/base/man-db/pspec.xml @@ -14,7 +14,7 @@ data:doc Application to read Linux man pages Man package consists of programs which is used to read most of the documentation available in linux system. For example, you can write "man nameoftheprogram" into the konsole or "man:nameoftheprogram" into the konqueror to get a detailed usage information for many programs. - http://download.savannah.gnu.org/releases/man-db/man-db-2.8.4.tar.xz + http://download.savannah.gnu.org/releases/man-db/man-db-2.8.6.1.tar.xz less gzip @@ -22,7 +22,7 @@ gdbm-devel zlib-devel gettext-devel - libpipeline-devel + libpipeline-devel @@ -33,7 +33,7 @@ gdbm zlib - libpipeline + libpipeline /etc @@ -53,6 +53,13 @@ + + 2019-12-25 + 2.8.6.1 + Version bump. + Idris Kalp + idriskalp@gmail.com + 2018-11-29 2.8.4 From e1f8761f6c03ace3e7b6b93879d3db69e21af5ed Mon Sep 17 00:00:00 2001 From: idriskalp Date: Wed, 25 Dec 2019 19:45:05 +0300 Subject: [PATCH 034/160] procps rebuild --- system/base/procps/pspec.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/system/base/procps/pspec.xml b/system/base/procps/pspec.xml index 813052b6..0edf1f35 100644 --- a/system/base/procps/pspec.xml +++ b/system/base/procps/pspec.xml @@ -38,6 +38,13 @@ + + 2019-12-25 + 3.3.15 + Rebuild + Idris Kalp + idriskalp@gmail.com + 2018-11-28 3.3.15 From ef2a5c48ea06883a76baad38c9bd2e72530c0855 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Wed, 25 Dec 2019 19:56:15 +0300 Subject: [PATCH 035/160] eudev 3.2.8 --- system/base/eudev/pspec.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/system/base/eudev/pspec.xml b/system/base/eudev/pspec.xml index 1c2398a0..d9e20cbe 100644 --- a/system/base/eudev/pspec.xml +++ b/system/base/eudev/pspec.xml @@ -12,7 +12,7 @@ console eudev is a fork of system-udev eudev is a fork of system-udev with the goal of obtaining better compatibility with existing software such as OpenRC and Upstart, older kernels, various toolchains and anything else required by users and various distributions. - https://github.com/gentoo/eudev/archive/v3.2.5.tar.gz + https://github.com/gentoo/eudev/archive/v3.2.8.tar.gz config.cache @@ -92,6 +92,13 @@ + + 2019-12-25 + 3.2.8 + Version bump + Idris Kalp + idriskalp@gmail.com + 2018-11-28 3.2.5 From f7f5f493c2dc80c10adfe79e79d1ea57b19943e9 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Wed, 25 Dec 2019 19:56:54 +0300 Subject: [PATCH 036/160] util-linux 2.35_rc1 --- ...-force-to-print-PKNAME-for-partition.patch | 31 +++++++++++++++++++ system/base/util-linux/pspec.xml | 17 +++++++++- 2 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 system/base/util-linux/files/0001-lsblk-force-to-print-PKNAME-for-partition.patch diff --git a/system/base/util-linux/files/0001-lsblk-force-to-print-PKNAME-for-partition.patch b/system/base/util-linux/files/0001-lsblk-force-to-print-PKNAME-for-partition.patch new file mode 100644 index 00000000..3fc342b3 --- /dev/null +++ b/system/base/util-linux/files/0001-lsblk-force-to-print-PKNAME-for-partition.patch @@ -0,0 +1,31 @@ +From e3bb9bfb76c17b1d05814436ced62c05c4011f48 Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Thu, 27 Jun 2019 09:22:18 +0200 +Subject: [PATCH 1/1] lsblk: force to print PKNAME for partition + +PKNAME (parent kernel device name) is based on printed tree according +to parent -> child relationship. The tree is optional and not printed +if partition specified (.e.g "lsblk -o+PKNAME /dev/sda1"), but old +versions print the PKNAME also in this case. + +Addresses: https://github.com/karelzak/util-linux/issues/813 +Signed-off-by: Karel Zak +Signed-off-by: Christian Hesse +--- + misc-utils/lsblk.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/misc-utils/lsblk.c b/misc-utils/lsblk.c +index e95af7af0..3ce6da730 100644 +--- a/misc-utils/lsblk.c ++++ b/misc-utils/lsblk.c +@@ -1019,6 +1019,9 @@ static void device_to_scols( + DBG(DEV, ul_debugobj(dev, "add '%s' to scols", dev->name)); + ON_DBG(DEV, if (ul_path_isopen_dirfd(dev->sysfs)) ul_debugobj(dev, " %s ---> is open!", dev->name)); + ++ if (!parent && dev->wholedisk) ++ parent = dev->wholedisk; ++ + /* Do not print device more than one in --list mode */ + if (!(lsblk->flags & LSBLK_TREE) && dev->is_printed) + return; diff --git a/system/base/util-linux/pspec.xml b/system/base/util-linux/pspec.xml index 6e3dd9fd..8f414a86 100644 --- a/system/base/util-linux/pspec.xml +++ b/system/base/util-linux/pspec.xml @@ -13,7 +13,7 @@ library Various useful Linux utilities The util-linux package contains a large variety of low-level system utilities that are necessary for a Linux system to function. - https://www.kernel.org/pub/linux/utils/util-linux/v2.31/util-linux-2.31.1.tar.xz + https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v2.35/util-linux-2.35-rc1.tar.xz zlib-devel eudev-devel @@ -23,10 +23,12 @@ ncurses-devel libcap-ng-devel pam-devel + libpcre2-devel upstream/util-linux-ng-2.21-login-lastlog.patch + @@ -43,6 +45,7 @@ eudev libcap-ng + libpcre2 /etc @@ -127,8 +130,13 @@ emul32 ncurses-32bit + libpcre2-32bit + libutil-linux-devel + ncurses-32bit + libpcre2-32bit + libutil-linux-devel libblkid-32bit @@ -140,6 +148,13 @@ + + 2019-12-25 + 2.35_rc1 + Version bump + Idris Kalp + idriskalp@gmail.com + 2019-03-17 2.31.1 From 8fecc83d598cf7759af24dbf14210985492921ed Mon Sep 17 00:00:00 2001 From: idriskalp Date: Wed, 25 Dec 2019 20:00:53 +0300 Subject: [PATCH 037/160] libseccomp 2.4.2 --- system/devel/libseccomp/actions.py | 2 +- system/devel/libseccomp/pspec.xml | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/system/devel/libseccomp/actions.py b/system/devel/libseccomp/actions.py index 09e900dc..a49ea7da 100644 --- a/system/devel/libseccomp/actions.py +++ b/system/devel/libseccomp/actions.py @@ -10,7 +10,7 @@ from pisi.actionsapi import shelltools def setup(): - shelltools.system("sh ./autogen.sh") + #shelltools.system("sh ./autogen.sh") autotools.configure() def build(): diff --git a/system/devel/libseccomp/pspec.xml b/system/devel/libseccomp/pspec.xml index 0970465a..be424376 100644 --- a/system/devel/libseccomp/pspec.xml +++ b/system/devel/libseccomp/pspec.xml @@ -12,7 +12,7 @@ app:library Enhanced seccomp library High level interface to the Linux Kernel's seccomp filter. - https://github.com/seccomp/libseccomp/archive/v2.3.1.tar.gz + https://github.com/seccomp/libseccomp/releases/download/v2.4.2/libseccomp-2.4.2.tar.gz glibc-devel libutil-linux-devel @@ -40,6 +40,13 @@ + + 2019-12-25 + 2.4.2 + Version bump + Idris Kalp + idriskalp@gmail.com + 2018-07-15 2.3.1 From 7c4a2a255647d46523d5d8a8e4b5d9131a7aec12 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Wed, 25 Dec 2019 20:03:55 +0300 Subject: [PATCH 038/160] e2fsprogs rebuild --- system/base/e2fsprogs/pspec.xml | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/system/base/e2fsprogs/pspec.xml b/system/base/e2fsprogs/pspec.xml index 750fecb7..414f460b 100644 --- a/system/base/e2fsprogs/pspec.xml +++ b/system/base/e2fsprogs/pspec.xml @@ -12,7 +12,7 @@ app:console Standard ext2/3/4 filesystem utilities e2fsprogs provides the filesystem utilities for use with the ext2 filesystem. It also supports the ext3/4 filesystem with journaling support. - mirrors://sourceforge/e2fsprogs/e2fsprogs-1.43.9.tar.gz + mirrors://sourceforge/e2fsprogs/e2fsprogs-1.45.3.tar.gz libutil-linux-devel @@ -65,6 +65,20 @@ + + 2019-12-25 + 1.45.3 + Rebuild + Idris Kalp + idriskalp@gmail.com + + + 2018-09-18 + 1.45. + Rebuild + Ertuğrul Erata + ertugrulerata@gmail.com + 2018-09-18 1.43.9 From 4f044de81e7c5e49025605e7e148a3e4e0c9ab24 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Wed, 25 Dec 2019 21:27:17 +0300 Subject: [PATCH 039/160] fuse 2.9.9 --- system/base/fuse/pspec.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/system/base/fuse/pspec.xml b/system/base/fuse/pspec.xml index d617e765..e655b61a 100644 --- a/system/base/fuse/pspec.xml +++ b/system/base/fuse/pspec.xml @@ -12,7 +12,7 @@ library An interface for filesystems implemented in userspace fuse is a backend allowing regular users to (un)mount filesystems for their own use. - https://github.com/libfuse/libfuse/archive/fuse-2.9.7.tar.gz + https://github.com/libfuse/libfuse/archive/fuse-2.9.9.tar.gz gettext-devel @@ -50,6 +50,13 @@ + + 2019-12-25 + 2.9.9 + Version bump + Idris Kalp + idriskalp@gmail.com + 2018-09-18 2.9.7 From 96453834bb766fb326a901277eccd7b1c146cdf7 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Wed, 25 Dec 2019 21:59:38 +0300 Subject: [PATCH 040/160] e2fsprogs 1.45.3 --- system/base/e2fsprogs/pspec.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/system/base/e2fsprogs/pspec.xml b/system/base/e2fsprogs/pspec.xml index 414f460b..fca6af3b 100644 --- a/system/base/e2fsprogs/pspec.xml +++ b/system/base/e2fsprogs/pspec.xml @@ -18,6 +18,7 @@ gettext util-linux + fuse-devel ntfs-3g.patch @@ -30,6 +31,7 @@ e2fsprogs libutil-linux + fuse From 76ff91b459f8d6faacd9300164b8b6ae871cad7b Mon Sep 17 00:00:00 2001 From: idriskalp Date: Wed, 25 Dec 2019 22:01:07 +0300 Subject: [PATCH 041/160] sysvinit 2.96 --- system/base/sysvinit/actions.py | 6 +++++- system/base/sysvinit/pspec.xml | 19 +++++++++++++------ 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/system/base/sysvinit/actions.py b/system/base/sysvinit/actions.py index e743f8b0..f59168e8 100644 --- a/system/base/sysvinit/actions.py +++ b/system/base/sysvinit/actions.py @@ -9,7 +9,7 @@ from pisi.actionsapi import autotools from pisi.actionsapi import pisitools from pisi.actionsapi import get -WorkDir = "sysvinit-%sdsf" % get.srcVERSION() +WorkDir = "sysvinit-%s" % get.srcVERSION() def build(): autotools.make("-C src CC=\"%s\" CFLAGS=\"%s -D_GNU_SOURCE\" LCRYPT=\"-lcrypt\"" % (get.CC(), get.CFLAGS())) @@ -19,4 +19,8 @@ def install(): autotools.rawInstall("ROOT='%s' STRIP=/bin/true" % get.installDIR()) pisitools.remove("/bin/pidof") + # These files conflict with e2fsprogs + pisitools.remove("/sbin/logsave") + pisitools.remove("/usr/share/man/man8/logsave.8") + pisitools.dosym("killall5", "/sbin/pidof") diff --git a/system/base/sysvinit/pspec.xml b/system/base/sysvinit/pspec.xml index ecf1155c..946d2a95 100644 --- a/system/base/sysvinit/pspec.xml +++ b/system/base/sysvinit/pspec.xml @@ -12,19 +12,19 @@ app:console Programs which control basic system processes sysvinit package contains a group of utilities that control the very basic functions of your system. sysvinit contains the init program, the first program started by the Linux kernel when the system boots. - http://download.savannah.gnu.org/releases/sysvinit/sysvinit-2.88dsf.tar.bz2 + http://download.savannah.gnu.org/releases/sysvinit/sysvinit-2.96.tar.xz - sysvinit-2.86-ctrlc.patch + - sysvinit-2.78-man.patch + sysvinit-2.86-loginshell.patch sysvinit-2.86-single.patch sysvinit-2.88-quiet.patch - sysvinit-2.88-ipv6.patch - sysvinit-2.88-omit.patch - sysvinit-2.88-wall-maxlines.patch + + + @@ -63,6 +63,13 @@ + + 2019-12-25 + 2.96 + Version bump + Idris Kalp + idriskalp@gmail.com + 2018-07-15 2.88 From 9cb5f556b908fef5099c3412178c1912a11dd36b Mon Sep 17 00:00:00 2001 From: idriskalp Date: Wed, 25 Dec 2019 22:07:30 +0300 Subject: [PATCH 042/160] autoconf-archive 2019.01.06 --- system/devel/autoconf-archive/pspec.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/system/devel/autoconf-archive/pspec.xml b/system/devel/autoconf-archive/pspec.xml index 1b967afc..3c43e301 100644 --- a/system/devel/autoconf-archive/pspec.xml +++ b/system/devel/autoconf-archive/pspec.xml @@ -13,7 +13,7 @@ autoconf automake - ftp://ftp.gnu.org/pub/gnu/autoconf-archive/autoconf-archive-2016.09.16.tar.xz + ftp://ftp.gnu.org/pub/gnu/autoconf-archive/autoconf-archive-2019.01.06.tar.xz autoconf-archive @@ -28,6 +28,13 @@ + + 2019-12-25 + 2019.01.06 + Version bump + Idris Kalp + idriskalp@gmail.com + 2018-07-15 2016.09.16 From 18e8e2443ebe0012e1ee8719c2d1399687d72803 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Thu, 26 Dec 2019 15:27:07 +0300 Subject: [PATCH 043/160] xtrans 1.4.0 --- system/devel/xtrans/pspec.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/system/devel/xtrans/pspec.xml b/system/devel/xtrans/pspec.xml index 14a4f9e5..867f0a6e 100644 --- a/system/devel/xtrans/pspec.xml +++ b/system/devel/xtrans/pspec.xml @@ -12,7 +12,7 @@ library X.Org trans library xtrans includes a number of routines to make X implementations transport-independent. - mirrors://xorg/individual/lib/xtrans-1.3.5.tar.bz2 + mirrors://xorg/individual/lib/xtrans-1.4.0.tar.bz2 util-macros libxslt-devel @@ -32,6 +32,13 @@ + + 2019-12-26 + 1.4.0 + Version bump + Idris Kalp + idriskalp@gmail.com + 2019-01-07 1.3.5 From 632500a22b505e7f622df69916eb014c1427e2d4 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Thu, 26 Dec 2019 15:29:13 +0300 Subject: [PATCH 044/160] xcb-proto rebuild --- system/devel/xcb-proto/pspec.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/system/devel/xcb-proto/pspec.xml b/system/devel/xcb-proto/pspec.xml index 5be6c99d..a3f367ab 100644 --- a/system/devel/xcb-proto/pspec.xml +++ b/system/devel/xcb-proto/pspec.xml @@ -29,6 +29,13 @@ + + 2019-12-26 + 1.13 + Rebuild + PisiLinux Community + admin@pisilinux.org + 2018-11-05 1.13 From 01841831223429751006890dc840154d52864900 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Thu, 26 Dec 2019 15:36:06 +0300 Subject: [PATCH 045/160] libbsd move to core and version bump --- system/base/libbsd/actions.py | 25 ++++++++ system/base/libbsd/pspec.xml | 93 +++++++++++++++++++++++++++++ system/base/libbsd/translations.xml | 8 +++ 3 files changed, 126 insertions(+) create mode 100644 system/base/libbsd/actions.py create mode 100644 system/base/libbsd/pspec.xml create mode 100644 system/base/libbsd/translations.xml diff --git a/system/base/libbsd/actions.py b/system/base/libbsd/actions.py new file mode 100644 index 00000000..9d0211af --- /dev/null +++ b/system/base/libbsd/actions.py @@ -0,0 +1,25 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# +# Licensed under the GNU General Public License, version 3. +# See the file http://www.gnu.org/copyleft/gpl.txt + +from pisi.actionsapi import get +from pisi.actionsapi import autotools +from pisi.actionsapi import pisitools + +def setup(): + autotools.configure("--disable-static \ + --disable-silent-rules") + +def build(): + autotools.make() + +def install(): + autotools.rawInstall("DESTDIR=%s" % get.installDIR()) + +# solve conflict with elfutils and glibc-devel +# pisitools.remove("/usr/include/nlist.h") +# pisitools.remove("/usr/lib/libbsd.a") + + pisitools.dodoc("ChangeLog", "COPYING", "README", "TODO") diff --git a/system/base/libbsd/pspec.xml b/system/base/libbsd/pspec.xml new file mode 100644 index 00000000..f2917ad7 --- /dev/null +++ b/system/base/libbsd/pspec.xml @@ -0,0 +1,93 @@ + + + libbsd + http://libbsd.freedesktop.org + + Marcin Bojara + marcin@pisilinux.org + + BSD + BSD-2 + BSD-4 + ISC + library + Provides useful functions commonly found on BSD systems + This library provides useful functions commonly found on BSD systems, and lacking on others like GNU systems, thus making it easier to port projects with strong BSD origins, without needing to embed the same code over and over again on each project. + https://libbsd.freedesktop.org/releases/libbsd-0.10.0.tar.xz + + + + libbsd + + /usr/lib + /usr/share/doc + + + + + libbsd-devel + Development files for libbsd + + libbsd + + + /usr/include + /usr/lib/pkgconfig + /usr/share/man/man3 + /usr/share/man/man7 + + + + + + + 2019-12-26 + 0.10.0 + Version Bump + Pisi Linux Community + admin@pisilinux.org + + + 2019-03-29 + 0.9.1 + Version Bump + Pisi Linux Community + admin@pisilinux.org + + + 2018-07-23 + 0.8.7 + Rebuild + Pisi Linux Community + admin@pisilinux.org + + + 2018-05-07 + 0.8.7 + Version Bump + Pisi Linux Community + admin@pisilinux.org + + + 2017-01-27 + 0.8.3 + Version Bump + Pisi Linux Community + admin@pisilinux.org + + + 2016-06-09 + 0.8.2 + Release Bump + Pisi Linux Community + admin@pisilinux.org + + + 2014-03-09 + 0.8.2 + First release + Marcin Bojara + marcin@pisilinux.org + + + diff --git a/system/base/libbsd/translations.xml b/system/base/libbsd/translations.xml new file mode 100644 index 00000000..db67d1d7 --- /dev/null +++ b/system/base/libbsd/translations.xml @@ -0,0 +1,8 @@ + + + + libbsd + Taşınabilirlik için BSD uyumlu fonksiyonlar sağlayan bir kitaplık. + GNU Linux sistemlerde bulunmayan BSD sistemlere özgü fonsiyonları barındıran bir kitaplıktır ve BSD uygulamalarının GNU Linux'a taşınmasını kolaylaştırır. + + \ No newline at end of file From c488738dc009f535decddc994dab7048979afe20 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Thu, 26 Dec 2019 15:37:44 +0300 Subject: [PATCH 046/160] libXdmcp move to core and rebuild --- system/base/libXdmcp/actions.py | 22 +++++ system/base/libXdmcp/pspec.xml | 118 ++++++++++++++++++++++++++ system/base/libXdmcp/translations.xml | 20 +++++ 3 files changed, 160 insertions(+) create mode 100644 system/base/libXdmcp/actions.py create mode 100644 system/base/libXdmcp/pspec.xml create mode 100644 system/base/libXdmcp/translations.xml diff --git a/system/base/libXdmcp/actions.py b/system/base/libXdmcp/actions.py new file mode 100644 index 00000000..2fbb68da --- /dev/null +++ b/system/base/libXdmcp/actions.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# +# Licensed under the GNU General Public License, version 3. +# See the file http://www.gnu.org/licenses/gpl.txt + +from pisi.actionsapi import autotools +from pisi.actionsapi import pisitools +from pisi.actionsapi import get + +def setup(): + autotools.autoreconf("-fi") + + autotools.configure("--disable-static \ + --without-xmlto") + +def build(): + autotools.make() + +def install(): + autotools.rawInstall("DESTDIR=%s" % get.installDIR()) + + pisitools.dodoc("AUTHORS", "ChangeLog", "COPYING", "README*") diff --git a/system/base/libXdmcp/pspec.xml b/system/base/libXdmcp/pspec.xml new file mode 100644 index 00000000..b08a5d5f --- /dev/null +++ b/system/base/libXdmcp/pspec.xml @@ -0,0 +1,118 @@ + + + + + libXdmcp + http://x.org/ + + PisiLinux Community + admins@pisilinux.org + + MIT + library + X.Org Xdmcp library + LibXdmcp is the X Display Manager Control Protocol library. + http://xorg.freedesktop.org/archive/individual/lib/libXdmcp-1.1.3.tar.bz2 + + libxslt + util-macros + xorg-proto + libbsd-devel + + + + + libXdmcp + + libbsd + + + /usr/lib + /usr/share/doc + + + + + libXdmcp-devel + Development files for libXdmcp + + xorg-proto + libXdmcp + + + /usr/include/X11 + /usr/lib/pkgconfig + /usr/lib32/pkgconfig + /usr/share/doc/*/*.xml + + + + + libXdmcp-32bit + emul32 + 32-bit shared libraries for libXdmcp + emul32 + + + + + libXdmcp + + + + /usr/lib32 + + + + + + 2019-12-26 + 1.1.3 + Rebuild + Idris Kalp + idriskalp@gmail.com + + + 2019-10-20 + 1.1.3 + Version bump. + Mustafa Cinasal + muscnsl@gmail.com + + + 2019-01-07 + 1.1.2 + Rebuild. + Mustafa Cinasal + muscnsl@gmail.com + + + 2018-07-23 + 1.1.2 + Rebuild + PisiLinux Community + admin@pisilinux.org + + + 2017-01-27 + 1.1.2 + Rebuild + PisiLinux Community + admin@pisilinux.org + + + 2016-04-30 + 1.1.2 + Release bump + PisiLinux Community + admin@pisilinux.org + + + 2015-06-06 + 1.1.2 + First release + Osman Erkan + osman.erkan@yandex.com + + + diff --git a/system/base/libXdmcp/translations.xml b/system/base/libXdmcp/translations.xml new file mode 100644 index 00000000..7eb6f757 --- /dev/null +++ b/system/base/libXdmcp/translations.xml @@ -0,0 +1,20 @@ + + + + libXdmcp + X.Org Xdmcp kitaplığı. + Librairie Xdmcp de X.Org. + X.Org Xdmcp Bibliothek + LibXdmcp, X Ekran Yöneticisi Denetim Protokolü kitaplığıdır. + + + + libXdmcp-devel + libXdmcp için geliştirme dosyaları + + + + libXdmcp-32bit + libXdmcp için 32-bit paylaşımlı kitaplıklar + + From c4864d31c35c2397d21e7c7ae91194e123eea2bf Mon Sep 17 00:00:00 2001 From: idriskalp Date: Thu, 26 Dec 2019 15:43:12 +0300 Subject: [PATCH 047/160] libXau move to core and rebuild --- system/base/libXau/actions.py | 22 +++++ system/base/libXau/files/visibility.patch | 22 +++++ system/base/libXau/pspec.xml | 114 ++++++++++++++++++++++ system/base/libXau/translations.xml | 20 ++++ 4 files changed, 178 insertions(+) create mode 100644 system/base/libXau/actions.py create mode 100644 system/base/libXau/files/visibility.patch create mode 100644 system/base/libXau/pspec.xml create mode 100644 system/base/libXau/translations.xml diff --git a/system/base/libXau/actions.py b/system/base/libXau/actions.py new file mode 100644 index 00000000..eef0c2ec --- /dev/null +++ b/system/base/libXau/actions.py @@ -0,0 +1,22 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# +# Licensed under the GNU General Public License, version 3. +# See the file http://www.gnu.org/licenses/gpl.txt + +from pisi.actionsapi import get +from pisi.actionsapi import autotools +from pisi.actionsapi import shelltools + +Libdir = "/usr/lib32" if get.buildTYPE() == "emul32" else "/usr/lib" + +def setup(): + autotools.autoreconf("-vif") + autotools.configure("--disable-static") + +def build(): + autotools.make() + +def install(): + autotools.rawInstall("DESTDIR=%s" % get.installDIR()) + diff --git a/system/base/libXau/files/visibility.patch b/system/base/libXau/files/visibility.patch new file mode 100644 index 00000000..5a338a16 --- /dev/null +++ b/system/base/libXau/files/visibility.patch @@ -0,0 +1,22 @@ +--- libXau-1.0.3/AuDispose.c.orig 2007-11-23 17:51:27.000000000 -0200 ++++ libXau-1.0.3/AuDispose.c 2007-11-23 17:51:34.000000000 -0200 +@@ -33,7 +33,7 @@ in this Software without prior written a + #include + #include + +-void ++_X_EXPORT void + XauDisposeAuth (Xauth *auth) + { + if (auth) { +--- libXau-1.0.3/AuRead.c.orig 2007-11-23 17:52:14.000000000 -0200 ++++ libXau-1.0.3/AuRead.c 2007-11-23 17:52:21.000000000 -0200 +@@ -69,7 +69,7 @@ read_counted_string (unsigned short *cou + return 1; + } + +-Xauth * ++_X_EXPORT Xauth * + XauReadAuth (FILE *auth_file) + { + Xauth local; diff --git a/system/base/libXau/pspec.xml b/system/base/libXau/pspec.xml new file mode 100644 index 00000000..1bf9ae40 --- /dev/null +++ b/system/base/libXau/pspec.xml @@ -0,0 +1,114 @@ + + + + + libXau + http://www.x.org/ + + PisiLinux Community + admins@pisilinux.org + + MIT + library + X.Org Au library + libXau provides functions to manage X authorization files + http://xorg.freedesktop.org/archive/individual/lib/libXau-1.0.9.tar.gz + + visibility.patch + + + util-macros + xorg-proto + + + + + libXau + + /usr/lib + + + + + libXau-devel + Development files for libXau + + libXau + xorg-proto + + + /usr/include/X11 + /usr/lib/pkgconfig + /usr/lib32/pkgconfig + /usr/share/man + + + + + libXau-32bit + emul32 + 32-bit shared libraries for libXau + emul32 + + + + + + + + /usr/lib32 + + + + + + 2019-12-26 + 1.0.9 + Rebuild + Idris Kalp + idriskalp@gmail.com + + + 2019-10-20 + 1.0.9 + Version bump. + Mustafa Cinasal + muscnsl@gmail.com + + + 2019-01-07 + 1.0.8 + Rebuild. + Mustafa Cinasal + muscnsl@gmail.com + + + 2018-07-23 + 1.0.8 + Rebuild + PisiLinux Community + admin@pisilinux.org + + + 2017-01-27 + 1.0.8 + Rebuild + PisiLinux Community + admin@pisilinux.org + + + 2016-04-30 + 1.0.8 + Release bump + PisiLinux Community + admin@pisilinux.org + + + 2014-06-01 + 1.0.8 + First release + Marcin Bojara + marcin@pisilinux.org + + + diff --git a/system/base/libXau/translations.xml b/system/base/libXau/translations.xml new file mode 100644 index 00000000..a48e4482 --- /dev/null +++ b/system/base/libXau/translations.xml @@ -0,0 +1,20 @@ + + + + libXau + X.Org Au kitaplığı. + Librairie Au de X.Org. + X.Org Au Bibliothek + libXau, X yetkilendirme dosyalarını yönetmek için işlevler sağlar. + + + + libXau-devel + libXau için geliştirme dosyaları + + + + libXau-32bit + libXau için 32-bit paylaşımlı kitaplıklar + + From 35205c70315af7a73223cc0888f695db0ab6ed34 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Thu, 26 Dec 2019 15:46:34 +0300 Subject: [PATCH 048/160] libxcb move to core and rebuild --- system/base/libxcb/actions.py | 38 +++++ .../files/libxcb-1.1-no-pthread-stubs.patch | 11 ++ system/base/libxcb/files/pthread-stubs.pc | 8 + system/base/libxcb/pspec.xml | 145 ++++++++++++++++++ system/base/libxcb/translations.xml | 17 ++ 5 files changed, 219 insertions(+) create mode 100644 system/base/libxcb/actions.py create mode 100644 system/base/libxcb/files/libxcb-1.1-no-pthread-stubs.patch create mode 100644 system/base/libxcb/files/pthread-stubs.pc create mode 100644 system/base/libxcb/pspec.xml create mode 100644 system/base/libxcb/translations.xml diff --git a/system/base/libxcb/actions.py b/system/base/libxcb/actions.py new file mode 100644 index 00000000..7831f8cd --- /dev/null +++ b/system/base/libxcb/actions.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +# +# Licensed under the GNU General Public License, version 3. +# See the file http://www.gnu.org/licenses/gpl.txt + +from pisi.actionsapi import autotools +from pisi.actionsapi import pisitools +from pisi.actionsapi import get + +def setup(): + pisitools.flags.add("-DNDEBUG") + + autotools.autoreconf("-vfi") + options = " --disable-static \ + --enable-xevie \ + --enable-xprint \ + --enable-xinput \ + --enable-xkb \ + --without-launchd \ + --without-doxygen" + + if get.buildTYPE() == "emul32": + options += " --libdir=/usr/lib32" + + autotools.configure(options) + + pisitools.dosed("libtool", " -shared ", " -Wl,-O1,--as-needed -shared ") + +def build(): + autotools.make("-j1") + +def install(): + autotools.rawInstall("-j1 DESTDIR=%s" % get.installDIR()) + + if get.buildTYPE() == "emul32": + return + + pisitools.dodoc("COPYING", "NEWS", "README") diff --git a/system/base/libxcb/files/libxcb-1.1-no-pthread-stubs.patch b/system/base/libxcb/files/libxcb-1.1-no-pthread-stubs.patch new file mode 100644 index 00000000..7f9a9752 --- /dev/null +++ b/system/base/libxcb/files/libxcb-1.1-no-pthread-stubs.patch @@ -0,0 +1,11 @@ +--- libxcb-1.8.1/configure.ac 2012-03-09 15:38:38.000000000 +0100 ++++ libxcb-1.8.1/configure.ac.new 2012-03-09 16:50:40.107109896 +0100 +@@ -43,7 +43,7 @@ + + # Checks for pkg-config packages + PKG_CHECK_MODULES(XCBPROTO, xcb-proto >= 1.13) +-NEEDED="pthread-stubs xau >= 0.99.2" ++NEEDED="xau >= 0.99.2" + PKG_CHECK_MODULES(NEEDED, $NEEDED) + + have_xdmcp="no" diff --git a/system/base/libxcb/files/pthread-stubs.pc b/system/base/libxcb/files/pthread-stubs.pc new file mode 100644 index 00000000..ad7b91b6 --- /dev/null +++ b/system/base/libxcb/files/pthread-stubs.pc @@ -0,0 +1,8 @@ +prefix=/usr +exec_prefix=${prefix} +libdir=${exec_prefix}/lib + +Name: pthread stubs +Description: Stubs missing from libc for standard pthread functions +Version: 0.3 +Libs: diff --git a/system/base/libxcb/pspec.xml b/system/base/libxcb/pspec.xml new file mode 100644 index 00000000..ff9d49b5 --- /dev/null +++ b/system/base/libxcb/pspec.xml @@ -0,0 +1,145 @@ + + + + + libxcb + http://xcb.freedesktop.org/ + + PisiLinux Community + admins@pisilinux.org + + MIT + library + The X protocol C-language Binding (XCB) + The X protocol C-language Binding (XCB) is a replacement for Xlib featuring a small footprint, latency hiding, direct access to the protocol, improved threading support, and extensibility. + https://xcb.freedesktop.org/dist/libxcb-1.13.1.tar.bz2 + + libXau-devel + libXdmcp-devel + python-devel + libxslt + util-macros + xcb-proto + + + libxcb-1.1-no-pthread-stubs.patch + + + + + libxcb + + libXau + libXdmcp + glibc + + + /usr/lib + /usr/share/man + /usr/share/doc + + + + + libxcb-devel + Development files for libxcb + + libxcb + libXau-devel + libXdmcp-devel + + + /usr/include/xcb + /usr/lib/pkgconfig + /usr/lib32/pkgconfig + + + pthread-stubs.pc + + + + + libxcb-32bit + emul32 + 32-bit shared libraries for libxcb + emul32 + + libXau-32bit + libXdmcp-32bit + + + libxcb + libXau-32bit + libXdmcp-32bit + + + /usr/lib32 + + + + + + 2019-12-26 + 1.13.1 + Rebuild. + PisiLinux Community + admin@pisilinux.org + + + 2019-10-23 + 1.13.1 + Rebuild. + PisiLinux Community + admin@pisilinux.org + + + 2019-02-20 + 1.13.1 + Rebuild. + PisiLinux Community + admin@pisilinux.org + + + 2019-01-16 + 1.13.1 + Version Bump + PisiLinux Community + admin@pisilinux.org + + + 2018-11-05 + 1.13 + Version Bump + PisiLinux Community + admin@pisilinux.org + + + 2018-09-16 + 1.12 + Rebuild. + PisiLinux Community + admin@pisilinux.org + + + 2017-01-29 + 1.12 + Version bump + PisiLinux Community + admin@pisilinux.org + + + 2016-04-30 + 1.11.1 + Release bump + PisiLinux Community + admin@pisilinux.org + + + 2016-03-08 + 1.11.1 + First release + Alihan Öztürk + alihan@pisilinux.org + + + diff --git a/system/base/libxcb/translations.xml b/system/base/libxcb/translations.xml new file mode 100644 index 00000000..d1bf19d2 --- /dev/null +++ b/system/base/libxcb/translations.xml @@ -0,0 +1,17 @@ + + + + libxcb + X protokolü için C dili bağlayıcısı (XCB) + + + + libxcb-devel + libxcb için geliştirme dosyaları + + + + libxcb-32bit + libxcb için 32-bit paylaşımlı kitaplıklar + + From c183fb3aa6fa03415c401cdf135e10109cf29bbb Mon Sep 17 00:00:00 2001 From: idriskalp Date: Thu, 26 Dec 2019 15:52:17 +0300 Subject: [PATCH 049/160] xmlto rebuild --- office/docbook/xmlto/pspec.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/office/docbook/xmlto/pspec.xml b/office/docbook/xmlto/pspec.xml index c5744100..f7249c2a 100644 --- a/office/docbook/xmlto/pspec.xml +++ b/office/docbook/xmlto/pspec.xml @@ -40,6 +40,13 @@ + + 2019-12-26 + 0.0.28 + Rebuild + Idris Kalp + idriskalp@gmail.com + 2018-07-23 0.0.28 From 119b1790c97147db243e27df0e19886e6499839c Mon Sep 17 00:00:00 2001 From: idriskalp Date: Thu, 26 Dec 2019 15:52:35 +0300 Subject: [PATCH 050/160] libX11 rebuild and move to core --- system/base/libX11/actions.py | 26 +++ .../base/libX11/files/fix-null-pointer.patch | 12 ++ system/base/libX11/files/fix-segfault.diff | 50 ++++++ system/base/libX11/files/fix_typo.diff | 27 +++ system/base/libX11/pspec.xml | 157 ++++++++++++++++++ system/base/libX11/translations.xml | 19 +++ 6 files changed, 291 insertions(+) create mode 100644 system/base/libX11/actions.py create mode 100644 system/base/libX11/files/fix-null-pointer.patch create mode 100644 system/base/libX11/files/fix-segfault.diff create mode 100644 system/base/libX11/files/fix_typo.diff create mode 100644 system/base/libX11/pspec.xml create mode 100644 system/base/libX11/translations.xml diff --git a/system/base/libX11/actions.py b/system/base/libX11/actions.py new file mode 100644 index 00000000..ba705cde --- /dev/null +++ b/system/base/libX11/actions.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +# +# Licensed under the GNU General Public License, version 3. +# See the file http://www.gnu.org/licenses/gpl.txt + +from pisi.actionsapi import get +from pisi.actionsapi import autotools +from pisi.actionsapi import pisitools +from pisi.actionsapi import shelltools + +def setup(): + autotools.autoreconf("-vif") + autotools.configure("--disable-static") + + pisitools.dosed("libtool", "^(hardcode_libdir_flag_spec=).*", '\\1""') + pisitools.dosed("libtool", "^(runpath_var=)LD_RUN_PATH", "\\1DIE_RPATH_DIE") + pisitools.dosed("libtool", " -shared ", " -Wl,-O1,--as-needed -shared ") + +def build(): + autotools.make() + +def install(): + autotools.rawInstall("DESTDIR=%s" % get.installDIR()) + if get.buildTYPE() == "emul32": return + + pisitools.dodoc("AUTHORS", "COPYING", "NEWS", "README*") diff --git a/system/base/libX11/files/fix-null-pointer.patch b/system/base/libX11/files/fix-null-pointer.patch new file mode 100644 index 00000000..8b37f365 --- /dev/null +++ b/system/base/libX11/files/fix-null-pointer.patch @@ -0,0 +1,12 @@ +diff -Naur libX11-1.3.5//src/xlibi18n/ICWrap.c libX11-1.3.5.tpg//src/xlibi18n/ICWrap.c +--- libX11-1.3.5//src/xlibi18n/ICWrap.c 2010-08-10 04:59:44.000000000 +0000 ++++ libX11-1.3.5.tpg//src/xlibi18n/ICWrap.c 2010-09-17 17:11:21.000000000 +0000 +@@ -283,7 +283,7 @@ + XIMArg *args; + char *ret; + +- if (!ic->core.im) ++ if (!ic || !ic->core.im) + return (char *) NULL; + + /* diff --git a/system/base/libX11/files/fix-segfault.diff b/system/base/libX11/files/fix-segfault.diff new file mode 100644 index 00000000..a38c0ce2 --- /dev/null +++ b/system/base/libX11/files/fix-segfault.diff @@ -0,0 +1,50 @@ +Index: libX11-1.4.99.1/src/Xrm.c +=================================================================== +--- libX11-1.4.99.1.orig/src/Xrm.c ++++ libX11-1.4.99.1/src/Xrm.c +@@ -2540,30 +2540,40 @@ Bool XrmQGetResource( + VClosureRec closure; + + if (db && *names) { +- _XLockMutex(&db->linfo); ++ if ((_XLockMutex_fn) && db->linfo.lock ) { ++ _XLockMutex(&db->linfo); ++ } + closure.type = pType; + closure.value = pValue; + table = db->table; + if (names[1]) { + if (table && !table->leaf) { + if (GetNEntry(table, names, classes, &closure)) { +- _XUnlockMutex(&db->linfo); ++ if ((_XUnlockMutex_fn) && db->linfo.lock ) { ++ _XUnlockMutex(&db->linfo); ++ } + return True; + } + } else if (table && table->hasloose && + GetLooseVEntry((LTable)table, names, classes, &closure)) { +- _XUnlockMutex (&db->linfo); ++ if ((_XUnlockMutex_fn) && db->linfo.lock ) { ++ _XUnlockMutex (&db->linfo); ++ } + return True; + } + } else { + if (table && !table->leaf) + table = table->next; + if (table && GetVEntry((LTable)table, names, classes, &closure)) { +- _XUnlockMutex(&db->linfo); ++ if ((_XUnlockMutex_fn) && db->linfo.lock ) { ++ _XUnlockMutex(&db->linfo); ++ } + return True; + } + } +- _XUnlockMutex(&db->linfo); ++ if ((_XUnlockMutex_fn) && db->linfo.lock ) { ++ _XUnlockMutex(&db->linfo); ++ } + } + *pType = NULLQUARK; + pValue->addr = (XPointer)NULL; diff --git a/system/base/libX11/files/fix_typo.diff b/system/base/libX11/files/fix_typo.diff new file mode 100644 index 00000000..a55a9407 --- /dev/null +++ b/system/base/libX11/files/fix_typo.diff @@ -0,0 +1,27 @@ +From 5dcb40f28d59587597d2ff6e6ac64c71cfe6ff7b Mon Sep 17 00:00:00 2001 +From: James Cloos +Date: Tue, 17 Sep 2013 16:50:42 +0000 +Subject: nls/en_US.UTF-8/Compose.pre: Fix typo. + +Fix typo added in 215ce6a67863, s/actute/acute/. + +Fixes bug #69476. Reported by Jean Krohn. + +Signed-off-by: James Cloos +--- +diff --git a/nls/en_US.UTF-8/Compose.pre b/nls/en_US.UTF-8/Compose.pre +index a741332..7314d7f 100644 +--- a/nls/en_US.UTF-8/Compose.pre ++++ b/nls/en_US.UTF-8/Compose.pre +@@ -743,7 +743,7 @@ XCOMM Part 3 + : "ï" idiaeresis # LATIN SMALL LETTER I WITH DIAERESIS + : "ï" idiaeresis # LATIN SMALL LETTER I WITH DIAERESIS + : "ï" idiaeresis # LATIN SMALL LETTER I WITH DIAERESIS +- : "j́" # LATIN SMALL LETTER J U006A with COMBINING ACUTE ACCENT U0301 ++ : "j́" # LATIN SMALL LETTER J U006A with COMBINING ACUTE ACCENT U0301 + : "j́" # LATIN SMALL LETTER J U006A with COMBINING ACUTE ACCENT U0301 + : "j́" # LATIN SMALL LETTER J U006A with COMBINING ACUTE ACCENT U0301 + : "j́" # LATIN SMALL LETTER J U006A with COMBINING ACUTE ACCENT U0301 +-- +cgit v0.9.0.2-2-gbebe + diff --git a/system/base/libX11/pspec.xml b/system/base/libX11/pspec.xml new file mode 100644 index 00000000..c0632479 --- /dev/null +++ b/system/base/libX11/pspec.xml @@ -0,0 +1,157 @@ + + + + + libX11 + http://www.x.org/ + + PisiLinux Community + admins@pisilinux.org + + MIT + library + X.Org X11 library + Core X11 protocol client library. + mirrors://xorg/individual/lib/libX11-1.6.9.tar.bz2 + + libxcb-devel + xorg-proto + util-macros + libxslt-devel + xtrans + xmlto + + + + + + + + libX11 + + libxcb + + + /usr/lib/libX11* + /usr/lib/X11 + /usr/share/X11 + /usr/share/doc/libX11 + + + + + libX11-devel + Development files for X11 library + + libX11 + libxcb-devel + xorg-proto + + + /usr/include/X11 + /usr/lib/pkgconfig + /usr/lib32/pkgconfig + /usr/share/man + + + + + libX11-32bit + emul32 + 32-bit shared libraries for libX11 + emul32 + + libxcb-32bit + libxslt-32bit + + + libX11 + libxcb-32bit + + + /usr/lib32 + + + + + + 2019-12-26 + 1.6.9 + Rebuild + Idris Kalp + idriskalp@gmail.com + + + 2019-10-20 + 1.6.9 + Version bump. + Mustafa Cinasal + muscnsl@gmail.com + + + 2019-01-06 + 1.6.7 + Rebuild + Mustafa Cinasal + muscnsl@gmail.com + + + 2018-11-05 + 1.6.5 + Rebuild + Mustafa Cinasal + muscnsl@gmail.com + + + 2018-10-30 + 1.6.5 + Rebuild + Mustafa Cinasal + muscnsl@gmail.com + + + 2018-09-16 + 1.6.5 + Rebuild + Mustafa Cinasal + muscnsl@gmail.com + + + 2018-02-16 + 1.6.5 + Version bump + Mustafa Cinasal + muscnsl@gmail.com + + + 2017-01-27 + 1.6.4 + Rebuild. + Stefan Gronewold(groni) + groni@pisilinux.org + + + 2016-11-02 + 1.6.4 + Version bump. + Stefan Gronewold(groni) + groni@pisilinux.org + + + 2016-04-30 + 1.6.3 + Release bump + PisiLinux Community + admin@pisilinux.org + + + 2016-03-08 + 1.6.3 + First release + Alihan Öztürk + alihan@pisilinux.org + + + diff --git a/system/base/libX11/translations.xml b/system/base/libX11/translations.xml new file mode 100644 index 00000000..f7b669ff --- /dev/null +++ b/system/base/libX11/translations.xml @@ -0,0 +1,19 @@ + + + + libX11 + X.Org X11 kitaplığı + Librairie X11 de X.Org. + X.Org X11 Bibliothek + + + + libX11-devel + libX11 için geliştirme dosyaları + + + + libX11-32bit + libX11 için 32-bit paylaşımlı kitaplıklar + + From 22fc929192c39447974850009dfa13cb89e7322d Mon Sep 17 00:00:00 2001 From: idriskalp Date: Thu, 26 Dec 2019 15:59:07 +0300 Subject: [PATCH 051/160] pkgconfig rebuild --- system/devel/pkgconfig/actions.py | 2 +- system/devel/pkgconfig/pspec.xml | 11 +++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/system/devel/pkgconfig/actions.py b/system/devel/pkgconfig/actions.py index f07d7439..b9679021 100644 --- a/system/devel/pkgconfig/actions.py +++ b/system/devel/pkgconfig/actions.py @@ -11,7 +11,7 @@ from pisi.actionsapi import get #WorkDir = "pkg-config-%s" % get.srcVERSION() def setup(): - autotools.configure("--with-pc-path=/usr/lib/pkgconfig:/usr/share/pkgconfig") + autotools.configure("--with-pc-path=/usr/lib/pkgconfig:/usr/share/pkgconfig --with-internal-glib") def check(): autotools.make("check") diff --git a/system/devel/pkgconfig/pspec.xml b/system/devel/pkgconfig/pspec.xml index d66c0de2..993b806b 100644 --- a/system/devel/pkgconfig/pspec.xml +++ b/system/devel/pkgconfig/pspec.xml @@ -15,14 +15,14 @@ http://pkgconfig.freedesktop.org/releases/pkg-config-0.29.2.tar.gz gnuconfig - glib2-devel + pkgconfig - glib2 + /usr/bin @@ -35,6 +35,13 @@ + + 2019-12-26 + 0.29.2 + Rebuild glib2 + Idris Kalp + idriskalp@gmail.com + 2018-07-22 0.29.2 From 6eaf5bebbee1a23ea580145424025b1eaef8e396 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Thu, 26 Dec 2019 17:23:44 +0300 Subject: [PATCH 052/160] catbox rebuild --- system/devel/catbox/pspec.xml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/system/devel/catbox/pspec.xml b/system/devel/catbox/pspec.xml index dc623ba0..901c655c 100644 --- a/system/devel/catbox/pspec.xml +++ b/system/devel/catbox/pspec.xml @@ -1,5 +1,5 @@ - - +- + catbox @@ -32,6 +32,13 @@ + + 2019-12-26 + 1.6.1 + Rebuild + Idris Kalp + idriskalp@gmail.com + 2018-07-15 1.6.1 From a368a182478b873e9010327600284a8e8aa65b7a Mon Sep 17 00:00:00 2001 From: idriskalp Date: Thu, 26 Dec 2019 17:28:13 +0300 Subject: [PATCH 053/160] chrpath rebuild --- system/devel/chrpath/pspec.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/system/devel/chrpath/pspec.xml b/system/devel/chrpath/pspec.xml index 6e418b26..c8f3b496 100644 --- a/system/devel/chrpath/pspec.xml +++ b/system/devel/chrpath/pspec.xml @@ -12,7 +12,7 @@ app:console Change the dynamic library load path (rpath) of binaries chrpath allows you to modify the dynamic library load path (rpath and runpath) of compiled programs and libraries. - http://source.pisilinux.org/1.0/chrpath-0.16.tar.gz + http://source.pisilinux.org/charpath/chrpath-0.16.tar.gz docdir.patch @@ -28,6 +28,13 @@ + + 2019-12-26 + 0.16 + Rebuild + Idris Kalp + idriskalp@gmail.com + 2018-07-17 0.16 From 24374aa846f9822e5a68be7fef3ab1890ca5ff77 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Thu, 26 Dec 2019 17:33:32 +0300 Subject: [PATCH 054/160] cython 0.29.14 --- system/devel/cython/actions.py | 4 ++-- system/devel/cython/pspec.xml | 11 ++++++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/system/devel/cython/actions.py b/system/devel/cython/actions.py index 93f8a969..ed68ff6e 100644 --- a/system/devel/cython/actions.py +++ b/system/devel/cython/actions.py @@ -16,5 +16,5 @@ def build(): def install(): pythonmodules.install() - pisitools.dohtml("Doc/*.html") - pisitools.dodoc("COPYING.txt", "LICENSE.txt", "README.txt", "ToDo.txt", "USAGE.txt") + #pisitools.dohtml("Doc/*.html") + pisitools.dodoc("COPYING.txt", "LICENSE.txt", "README.rst", "ToDo.txt", "USAGE.txt") diff --git a/system/devel/cython/pspec.xml b/system/devel/cython/pspec.xml index 37a64382..49d3a1f0 100644 --- a/system/devel/cython/pspec.xml +++ b/system/devel/cython/pspec.xml @@ -13,9 +13,10 @@ library C extensions for the Python Cython is a language that makes writing C extensions for the Python language as easy as Python itself. - https://pypi.python.org/packages/b7/67/7e2a817f9e9c773ee3995c1e15204f5d01c8da71882016cac10342ef031b/Cython-0.25.2.tar.gz + https://files.pythonhosted.org/packages/9c/9b/706dac7338c2860cd063a28cdbf5e9670995eaea408abbf2e88ba070d90d/Cython-0.29.14.tar.gz python-devel + bzip2 @@ -23,6 +24,7 @@ cython python + bzip2 /usr/bin @@ -32,6 +34,13 @@ + + 2019-12-26 + 0.29.14 + Version bump + Idris Kalp + idriskalp@gmail.com + 2018-07-15 0.25.2 From c18833309a9839ceeda6e336df5578350780ca01 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Thu, 26 Dec 2019 17:39:17 +0300 Subject: [PATCH 055/160] dietlibc rebuild --- system/devel/dietlibc/pspec.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/system/devel/dietlibc/pspec.xml b/system/devel/dietlibc/pspec.xml index 65b5535b..a54fa83f 100644 --- a/system/devel/dietlibc/pspec.xml +++ b/system/devel/dietlibc/pspec.xml @@ -34,6 +34,13 @@ + + 2019-12-26 + 0.33.20120825 + Rebuild + Idris Kalp + idriskalp@gmail.com + 2018-07-15 0.33.20120825 From 4e3bce669fdf7c685ed285108015fc856bd94309 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Thu, 26 Dec 2019 17:52:46 +0300 Subject: [PATCH 056/160] guile 2.2.6 --- system/devel/guile/actions.py | 2 +- system/devel/guile/pspec.xml | 11 +++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/system/devel/guile/actions.py b/system/devel/guile/actions.py index 82a6470f..7ccd31c7 100644 --- a/system/devel/guile/actions.py +++ b/system/devel/guile/actions.py @@ -38,6 +38,6 @@ def install(): pisitools.dodir("/etc/env.d") shelltools.echo("%s/etc/env.d/50guile" % get.installDIR(), 'GUILE_LOAD_PATH="/usr/share/guile/%s"' % major) - pisitools.domove("/usr/lib/libguile-2.0.so.22.*.scm", "/usr/share/gdb/auto-load") + pisitools.domove("/usr/lib/libguile-2.2.so.*.scm", "/usr/share/gdb/auto-load") pisitools.dodoc("AUTHORS", "ChangeLog", "HACKING", "NEWS", "README", "THANKS") diff --git a/system/devel/guile/pspec.xml b/system/devel/guile/pspec.xml index fe925c29..284b9fa9 100644 --- a/system/devel/guile/pspec.xml +++ b/system/devel/guile/pspec.xml @@ -14,7 +14,7 @@ library GNU Scheme interpreter and library GUILE (GNU's Ubiquitous Intelligent Language for Extension) is a library implementation of the Scheme programming language, written in C. GUILE provides a machine-independent execution platform that can be linked in as a library during the building of extensible programs. - mirrors://gnu/guile/guile-2.0.14.tar.xz + mirrors://gnu/guile/guile-2.2.6.tar.xz gc-devel gettext-devel @@ -47,7 +47,7 @@ /usr/share/guile /usr/share/emacs /usr/share/gdb/auto-load - /usr/lib/guile/2.0 + /usr/lib/guile/2.2 @@ -69,6 +69,13 @@ + + 2019-10-02 + 2.2.6 + Version bump + Idris Kalp + idriskalp@gmail.com + 2018-07-18 2.0.14 From 8b34b490cd73977d0a5d57f600771287a3e3b836 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Thu, 26 Dec 2019 17:53:00 +0300 Subject: [PATCH 057/160] klibc 2.0.7 --- .../fix_missing_include_in_sys_mman_h.patch | 35 +++++++++++++++++++ system/devel/klibc/pspec.xml | 12 ++++++- 2 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 system/devel/klibc/files/fix_missing_include_in_sys_mman_h.patch diff --git a/system/devel/klibc/files/fix_missing_include_in_sys_mman_h.patch b/system/devel/klibc/files/fix_missing_include_in_sys_mman_h.patch new file mode 100644 index 00000000..e9a1b115 --- /dev/null +++ b/system/devel/klibc/files/fix_missing_include_in_sys_mman_h.patch @@ -0,0 +1,35 @@ +From d4853d030639cf3542ae39129c18b654d8d4f020 Mon Sep 17 00:00:00 2001 +From: Barret Rhoden +Date: Thu, 14 Mar 2019 17:30:38 -0400 +Subject: Fix missing include in sys/mman.h + +Linux commit 746c9398f5ac ("arch: move common mmap flags to +linux/mman.h") moved a few mmap flags, particularly MAP_PRIVATE, from +asm/mman.h to linux/mman.h. This broke klibc's build, which uses +MAP_PRIVATE. + +linux/mman.h includes asm/mman.h, so this commit merely includes +linux/mman.h instead of asm/mman.h. + +Signed-off-by: Barret Rhoden +Signed-off-by: Ben Hutchings +--- + usr/include/sys/mman.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/usr/include/sys/mman.h b/usr/include/sys/mman.h +index 56f0b65c..3fd626e7 100644 +--- a/usr/include/sys/mman.h ++++ b/usr/include/sys/mman.h +@@ -7,7 +7,7 @@ + + #include + #include +-#include ++#include + + #define MAP_FAILED ((void *)-1) + +-- +cgit 1.2-0.3.lf.el7 + diff --git a/system/devel/klibc/pspec.xml b/system/devel/klibc/pspec.xml index 12374a59..f892c7dd 100644 --- a/system/devel/klibc/pspec.xml +++ b/system/devel/klibc/pspec.xml @@ -13,13 +13,16 @@ library A minimal libc subset for use with initramfs klibc, or "early userspace", is library part of an effort which tries to move as much initialization code in Linux as possible out of the kernel. - https://www.kernel.org/pub/linux/libs/klibc/2.0/klibc-2.0.4.tar.xz + https://mirrors.edge.kernel.org/pub/linux/libs/klibc/2.0/klibc-2.0.7.tar.xz perl + + + @@ -40,6 +43,13 @@ + + 2019-12-26 + 2.0.7 + Version bump + Idris Kalp + idriskalp@gmail.com + 2019-04-06 2.0.4 From 8ef5e935ee5116608771c2158f4281d992c5e22e Mon Sep 17 00:00:00 2001 From: idriskalp Date: Thu, 26 Dec 2019 18:00:29 +0300 Subject: [PATCH 058/160] gobject-introspection 1.62.0 --- system/devel/gobject-introspection/actions.py | 24 +++++++++++++++---- system/devel/gobject-introspection/pspec.xml | 11 +++++++-- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/system/devel/gobject-introspection/actions.py b/system/devel/gobject-introspection/actions.py index b265c18b..684e844f 100644 --- a/system/devel/gobject-introspection/actions.py +++ b/system/devel/gobject-introspection/actions.py @@ -12,16 +12,30 @@ from pisi.actionsapi import get def setup(): #autotools.autoreconf("-fiv") - autotools.configure("--disable-static \ - --disable-doctool") + #autotools.configure("--disable-static \ + #--disable-doctool") + + options = " --libdir=/usr/lib \ + --bindir=/usr/bin \ + --sbindir=/usr/sbin \ + --datadir=/usr/share \ + --prefix=/usr" + + shelltools.makedirs("build") + shelltools.cd("build") + shelltools.system("meson .. %s" % options) - pisitools.dosed("libtool", " -shared ", " -Wl,-O1,--as-needed -shared ") + #pisitools.dosed("libtool", " -shared ", " -Wl,-O1,--as-needed -shared ") def build(): - autotools.make() + #autotools.make() + shelltools.cd("build") + shelltools.system("ninja") def install(): - autotools.rawInstall("DESTDIR=%s" % get.installDIR()) + #autotools.rawInstall("DESTDIR=%s" % get.installDIR()) + shelltools.cd("build") + shelltools.system("DESTDIR=%s ninja install" % get.installDIR()) diff --git a/system/devel/gobject-introspection/pspec.xml b/system/devel/gobject-introspection/pspec.xml index 9b7dd3da..808776bf 100644 --- a/system/devel/gobject-introspection/pspec.xml +++ b/system/devel/gobject-introspection/pspec.xml @@ -14,13 +14,13 @@ app:console Introspection system for GObject-based libraries gobject-introspection can scan C header and source files in order to generate introspection typelib files. It also provides an API to examine typelib files, useful for creating language bindings among other things. - mirrors://gnome/gobject-introspection/1.54/gobject-introspection-1.54.1.tar.xz + mirrors://gnome/gobject-introspection/1.62/gobject-introspection-1.62.0.tar.xz libffi-devel python-devel - glib2-devel + glib2-devel chrpath @@ -63,6 +63,13 @@ + + 2019-12-26 + 1.62.0 + Version bump. + Idris Kalp + idriskalp@gmail.com + 2018-07-20 1.54.1 From f31db6b4d361b7627a0d753596efe38caba6b575 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Thu, 26 Dec 2019 18:03:03 +0300 Subject: [PATCH 059/160] lzo 2.10 --- system/base/lzo/pspec.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/system/base/lzo/pspec.xml b/system/base/lzo/pspec.xml index cb13b782..785328e6 100644 --- a/system/base/lzo/pspec.xml +++ b/system/base/lzo/pspec.xml @@ -12,7 +12,7 @@ library An extremely fast compression and decompression library lzo is a library with very high compression and decompression speeds and very small memory usage. Provides low compression ratios but very high speeds. - http://www.oberhumer.com/opensource/lzo/download/lzo-2.09.tar.gz + http://www.oberhumer.com/opensource/lzo/download/lzo-2.10.tar.gz @@ -49,6 +49,13 @@ + + 2019-12-26 + 2.10 + Version bump + idris Kalp + idriskalp@gmail.com + 2018-07-15 2.09 From 0e6ee0af2280d3c6f93e2efb1d23998ca3fbcb8e Mon Sep 17 00:00:00 2001 From: idriskalp Date: Thu, 26 Dec 2019 18:05:00 +0300 Subject: [PATCH 060/160] nettle 3.5.1 --- system/base/nettle/pspec.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/system/base/nettle/pspec.xml b/system/base/nettle/pspec.xml index bb5b4079..9c41c136 100644 --- a/system/base/nettle/pspec.xml +++ b/system/base/nettle/pspec.xml @@ -12,7 +12,7 @@ library The Nettle package contains the low-level cryptographic library The Nettle package contains the low-level cryptographic library that is designed to fit easily in many contexts. - ftp://ftp.gnu.org/gnu/nettle/nettle-3.3.tar.gz + ftp://ftp.gnu.org/gnu/nettle/nettle-3.5.1.tar.gz gmp-devel @@ -64,6 +64,13 @@ + + 2019-12-26 + 3.5.1 + Version bump + Idris Kalp + idriskalp@gmail.com + 2018-07-15 3.3 From 8c7971258d3d12299ec2fb8f612d45791d8988d2 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Thu, 26 Dec 2019 18:16:00 +0300 Subject: [PATCH 061/160] libarchive 3.4.0 --- system/devel/libarchive/pspec.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/system/devel/libarchive/pspec.xml b/system/devel/libarchive/pspec.xml index 9f4e289b..329d9c92 100644 --- a/system/devel/libarchive/pspec.xml +++ b/system/devel/libarchive/pspec.xml @@ -12,7 +12,7 @@ library Library for reading and writing streaming archives libarchive includes a library and command-line tools for reading and writing tar, cpio, zip, ISO, and other archive formats. - http://www.libarchive.org/downloads/libarchive-3.3.3.tar.gz + http://www.libarchive.org/downloads/libarchive-3.4.0.tar.gz acl-devel nettle-devel @@ -60,6 +60,13 @@ + + 2019-12-26 + 3.4.0 + Idris Kalp + Idris Kalp + idriskalp@gmail.com + 2018-12-26 3.3.3 From d59202e4e39e35349cf491e680472136c4fc7122 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Thu, 26 Dec 2019 18:16:17 +0300 Subject: [PATCH 062/160] libuv 1.34.0 --- system/devel/libuv/pspec.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/system/devel/libuv/pspec.xml b/system/devel/libuv/pspec.xml index e96da22c..2f075820 100644 --- a/system/devel/libuv/pspec.xml +++ b/system/devel/libuv/pspec.xml @@ -12,7 +12,7 @@ library Multi-platform support library with a focus on asynchronous I/O libuv is a multi-platform support library with a focus on asynchronous I/O. It was primarily developed for use by Node.js, but it's also used by Luvit, Julia, pyuv, and others. - https://github.com/libuv/libuv/archive/v1.11.0.tar.gz + https://github.com/libuv/libuv/archive/v1.34.0.tar.gz python-sphinx @@ -39,6 +39,13 @@ + + 2019-12-26 + 1.34.0 + Version bump + Idris Kalp + idriskalp@gmail.com + 2018-07-15 1.11.0 From 4b97070b0fa8ade448caea17404a359f32b3f2d1 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Thu, 26 Dec 2019 18:16:31 +0300 Subject: [PATCH 063/160] nasm rebuild --- system/devel/nasm/pspec.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/system/devel/nasm/pspec.xml b/system/devel/nasm/pspec.xml index 59bd8986..f847c33d 100644 --- a/system/devel/nasm/pspec.xml +++ b/system/devel/nasm/pspec.xml @@ -28,6 +28,13 @@ + + 2019-12-26 + 2.14.02 + Rebuild + Idris Kalp + idriskalp@gmail.com + 2019-03-23 2.14.02 From edb5f950a2337180dc0b270bdeb82fd9736895b2 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Thu, 26 Dec 2019 18:18:23 +0300 Subject: [PATCH 064/160] numactl 2.0.13 --- system/devel/numactl/actions.py | 2 +- system/devel/numactl/pspec.xml | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/system/devel/numactl/actions.py b/system/devel/numactl/actions.py index e84eb9a2..f11e2b74 100644 --- a/system/devel/numactl/actions.py +++ b/system/devel/numactl/actions.py @@ -22,4 +22,4 @@ def install(): pisitools.remove("/usr/lib/*.a") pisitools.removeDir("/usr/share/man/man2") - pisitools.dodoc("CHANGES", "DESIGN") + pisitools.dodoc("LICENSE.GPL2", "README.md") diff --git a/system/devel/numactl/pspec.xml b/system/devel/numactl/pspec.xml index ef366af9..0241338b 100644 --- a/system/devel/numactl/pspec.xml +++ b/system/devel/numactl/pspec.xml @@ -14,7 +14,7 @@ app:console Library for tuning NUMA machines numactl consists of a numactl program to run other programs with a specific NUMA policy and a libnuma to do allocations with NUMA policy in applications. - http://ftp.vim.org/ftp/os/Linux/distr/salix/i486/14.2/source/d/numactl/numactl-2.0.11.tar.gz + https://github.com/numactl/numactl/releases/download/v2.0.13/numactl-2.0.13.tar.gz @@ -40,6 +40,13 @@ + + 2019-12-26 + 2.0.13 + Version bump + Idris Kalp + idriskalp@gmail.com + 2018-07-15 2.0.11 From 66cdc81b949e271c1bbea9e9a93c0261721e058f Mon Sep 17 00:00:00 2001 From: idriskalp Date: Thu, 26 Dec 2019 18:22:44 +0300 Subject: [PATCH 065/160] rhash 1.3.9 --- system/devel/rhash/actions.py | 12 ++++++++---- system/devel/rhash/pspec.xml | 9 ++++++++- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/system/devel/rhash/actions.py b/system/devel/rhash/actions.py index c441046e..55986a9c 100755 --- a/system/devel/rhash/actions.py +++ b/system/devel/rhash/actions.py @@ -18,11 +18,15 @@ def setup(): --enable-gettext \ --disable-openssl-runtime \ --enable-openssl") + +def check(): + autotools.make("test test-lib") def install(): - autotools.make("PREFIX=/usr DESTDIR=%s build-shared install-gmo install-lib-shared" % get.installDIR()) - autotools.make("PREFIX=/usr DESTDIR=%s -C librhash install-so-link install-headers" % get.installDIR()) - autotools.rawInstall("PREFIX=/usr DESTDIR=%s" % get.installDIR()) + autotools.make() + autotools.rawInstall("PREFIX=/usr DESTDIR=%s install-lib-headers install-lib-shared install" % get.installDIR()) - pisitools.dodoc("ChangeLog", "INSTALL*", "README", "COPYING") + pisitools.dosym("usr/lib/librhash.so.0", "/usr/lib/librhash.so") + + pisitools.dodoc("ChangeLog", "INSTALL*", "README.md") diff --git a/system/devel/rhash/pspec.xml b/system/devel/rhash/pspec.xml index 180aca48..1e74e0db 100755 --- a/system/devel/rhash/pspec.xml +++ b/system/devel/rhash/pspec.xml @@ -12,7 +12,7 @@ library Hash sums are used to ensure and verify integrity of large volumes of data for a long-term storing or transferring. RHash is a console utility for calculation and verification of magnet links and a wide range of hash sums like CRC32, MD4, MD5, SHA1, SHA256, SHA512, SHA3, AICH, ED2K, Tiger, DC++ TTH, BitTorrent BTIH, GOST R 34.11-94,RIPEMD-160, HAS-160, EDON-R, Whirlpool and Snefru. - https://github.com/rhash/RHash/archive/v1.3.6.tar.gz + https://github.com/rhash/RHash/archive/v1.3.9.tar.gz glibc openssl-devel @@ -46,6 +46,13 @@ + + 2019-12-26 + 1.3.9 + Version bump + Idris Kalp + idriskalp@gmail.com + 2018-07-15 1.3.6 From 5fd041286719a79d553aa269ce42c4206ba8f51f Mon Sep 17 00:00:00 2001 From: idriskalp Date: Thu, 26 Dec 2019 18:23:29 +0300 Subject: [PATCH 066/160] scons 3.1.2 --- system/devel/scons/actions.py | 0 system/devel/scons/files/fix-gnu-link-handling.patch | 0 .../files/scons-1.0.0-qt-handle-missing-moc-files.patch | 0 system/devel/scons/pspec.xml | 9 ++++++++- system/devel/scons/translations.xml | 0 5 files changed, 8 insertions(+), 1 deletion(-) mode change 100644 => 100755 system/devel/scons/actions.py mode change 100644 => 100755 system/devel/scons/files/fix-gnu-link-handling.patch mode change 100644 => 100755 system/devel/scons/files/scons-1.0.0-qt-handle-missing-moc-files.patch mode change 100644 => 100755 system/devel/scons/pspec.xml mode change 100644 => 100755 system/devel/scons/translations.xml diff --git a/system/devel/scons/actions.py b/system/devel/scons/actions.py old mode 100644 new mode 100755 diff --git a/system/devel/scons/files/fix-gnu-link-handling.patch b/system/devel/scons/files/fix-gnu-link-handling.patch old mode 100644 new mode 100755 diff --git a/system/devel/scons/files/scons-1.0.0-qt-handle-missing-moc-files.patch b/system/devel/scons/files/scons-1.0.0-qt-handle-missing-moc-files.patch old mode 100644 new mode 100755 diff --git a/system/devel/scons/pspec.xml b/system/devel/scons/pspec.xml old mode 100644 new mode 100755 index df2d091a..708266fe --- a/system/devel/scons/pspec.xml +++ b/system/devel/scons/pspec.xml @@ -12,7 +12,7 @@ app:console An Open Source software construction tool Think of SCons as an improved, cross-platform substitute for the classic Make utility with integrated functionality similar to autoconf/automake and compiler caches such as ccache. - mirrors://sourceforge/scons/scons-2.5.1.tar.gz + mirrors://sourceforge/scons/scons-3.1.2.tar.gz python @@ -36,6 +36,13 @@ + + 2019-12-26 + 3.1.2 + Version bump + Idris Kalp + idriskalp@gmail.com + 2018-07-15 2.5.1 diff --git a/system/devel/scons/translations.xml b/system/devel/scons/translations.xml old mode 100644 new mode 100755 From ca6938621537f6d14f0b90fc373716e2a97dfc49 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Thu, 26 Dec 2019 18:24:54 +0300 Subject: [PATCH 067/160] unifdef 2.11.23 --- system/devel/unifdef/pspec.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/system/devel/unifdef/pspec.xml b/system/devel/unifdef/pspec.xml index 8dcbe662..7258bce4 100644 --- a/system/devel/unifdef/pspec.xml +++ b/system/devel/unifdef/pspec.xml @@ -12,7 +12,7 @@ app:console The unifdef utility selectively processes conditional cpp(1) directives The unifdef utility selectively processes conditional cpp(1) directives. It removes from a file both the directives and any additional text that they specify should be removed, while otherwise leaving the file alone. - http://dotat.at/prog/unifdef/unifdef-2.11.tar.gz + http://dotat.at/prog/unifdef/unifdef-2.11.23.1cca442.tar.xz @@ -25,6 +25,13 @@ + + 2019-12-26 + 2.11.23 + Version bump + Idris Kalp + idriskalp@gmail.com + 2018-07-15 2.11 From be48ee62be20b1865d83f7d4326548030511131a Mon Sep 17 00:00:00 2001 From: idriskalp Date: Thu, 26 Dec 2019 18:29:45 +0300 Subject: [PATCH 068/160] yacc rebuild --- system/devel/yacc/pspec.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/system/devel/yacc/pspec.xml b/system/devel/yacc/pspec.xml index bd074625..ee5695e7 100644 --- a/system/devel/yacc/pspec.xml +++ b/system/devel/yacc/pspec.xml @@ -12,7 +12,7 @@ app:console Yacc: Yet Another Compiler-Compiler Yacc provides a general tool for describing the input to a computer program. The Yacc user specifies the structures of his input, together with code to be invoked as each such structure is recognized. Yacc turns such a specification into a subroutine that handles the input process - http://ibiblio.org/pub/linux/devel/compiler-tools/yacc-1.9.1.tar.Z + https://sourceforge.net/projects/pisilinux/files/source/yacc-1.9.1.tar.xz mkstemp.patch skeleton.c.diff @@ -30,6 +30,13 @@ + + 2019-12-26 + 1.9.1 + Rebuild + Idris Kalp + idriskalp@gmail.com + 2018-07-15 1.9.1 From 09a498e3581e769ca9b0df6b521206bc78f1dae4 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Thu, 26 Dec 2019 18:29:56 +0300 Subject: [PATCH 069/160] yasm rebuild --- system/devel/yasm/pspec.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/system/devel/yasm/pspec.xml b/system/devel/yasm/pspec.xml index 981f21e9..4534aa79 100644 --- a/system/devel/yasm/pspec.xml +++ b/system/devel/yasm/pspec.xml @@ -51,6 +51,13 @@ + + 2019-12-26 + 1.3.0 + Rebuild + Idris Kalp + idriskalp@gmail.com + 2018-07-15 1.3.0 From 39783e702f7d6ecab714cd6abfdb88985921dab2 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Thu, 26 Dec 2019 19:11:49 +0300 Subject: [PATCH 070/160] cmake 3.16.2 --- system/devel/cmake/actions.py | 1 + system/devel/cmake/pspec.xml | 9 ++++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/system/devel/cmake/actions.py b/system/devel/cmake/actions.py index 4ae7bd61..0d0bba41 100644 --- a/system/devel/cmake/actions.py +++ b/system/devel/cmake/actions.py @@ -13,6 +13,7 @@ def setup(): --no-qt-gui \ --no-system-jsoncpp \ --prefix=/usr \ + --no-system-librhash \ --datadir=/share/cmake \ --docdir=/share/doc/cmake \ --mandir=/share/man" % get.makeJOBS().replace("-j", "")) diff --git a/system/devel/cmake/pspec.xml b/system/devel/cmake/pspec.xml index 3cee81f0..c8989da9 100644 --- a/system/devel/cmake/pspec.xml +++ b/system/devel/cmake/pspec.xml @@ -12,7 +12,7 @@ app:console Cross-platform, open-source make system CMake, the cross-platform, open-source make system. CMake is used to control the software compilation process using simple platform and compiler independent configuration files. CMake generates native makefiles and workspaces that can be used in the compiler environment of your choice. - https://cmake.org/files/v3.11/cmake-3.11.1.tar.gz + https://github.com/Kitware/CMake/releases/download/v3.16.2/cmake-3.16.2.tar.gz curl-devel expat-devel @@ -47,6 +47,13 @@ + + 2019-10-02 + 3.16.2 + Ver bump + Idris Kalp + idriskalp@gmail.com + 2018-07-15 3.11.1 From 0e6c65809eec4277031eb092aa658a02417abe40 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Thu, 26 Dec 2019 19:12:05 +0300 Subject: [PATCH 071/160] busybox-mkinitcpio rebuild --- system/boot/busybox-mkinitcpio/pspec.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/system/boot/busybox-mkinitcpio/pspec.xml b/system/boot/busybox-mkinitcpio/pspec.xml index 5ce9f445..295ec09f 100644 --- a/system/boot/busybox-mkinitcpio/pspec.xml +++ b/system/boot/busybox-mkinitcpio/pspec.xml @@ -30,6 +30,13 @@ + + 2019-12-26 + 1.24.1 + Rebuild + idris Kalp + idriskalp@gmail.com + 2018-07-15 1.24.1 From c4a5cbc16cb332339ace4bb520c2f856895f329a Mon Sep 17 00:00:00 2001 From: idriskalp Date: Thu, 26 Dec 2019 19:12:17 +0300 Subject: [PATCH 072/160] os-prober 1.77 --- system/boot/os-prober/actions.py | 7 +------ system/boot/os-prober/pspec.xml | 25 ++++++------------------- system/boot/os-prober/translations.xml | 0 3 files changed, 7 insertions(+), 25 deletions(-) mode change 100644 => 100755 system/boot/os-prober/actions.py mode change 100644 => 100755 system/boot/os-prober/pspec.xml mode change 100644 => 100755 system/boot/os-prober/translations.xml diff --git a/system/boot/os-prober/actions.py b/system/boot/os-prober/actions.py old mode 100644 new mode 100755 index 056a1065..ed82676e --- a/system/boot/os-prober/actions.py +++ b/system/boot/os-prober/actions.py @@ -9,10 +9,6 @@ from pisi.actionsapi import pisitools from pisi.actionsapi import shelltools def build(): - shelltools.system("sed -i -e 's|grub-probe|grub2-probe|g' os-probes/common/50mounted-tests \ - linux-boot-probes/common/50mounted-tests") - shelltools.system("sed -i -e 's|grub-mount|grub2-mount|g' os-probes/common/50mounted-tests \ - linux-boot-probes/common/50mounted-tests common.sh") shelltools.unlink("Makefile") autotools.make("newns") @@ -20,8 +16,7 @@ def install(): pisitools.dodoc("debian/copyright", "debian/changelog", "README") pisitools.dobin("os-prober") pisitools.dobin("linux-boot-prober") - #pisitools.insinto("/usr/lib/os-prober", "newns") - pisitools.doexe("newns", "/usr/lib/os-prober/") + pisitools.insinto("/usr/lib/os-prober", "newns") pisitools.insinto("/usr/share/os-prober", "common.sh") for d in ("os-probes", "os-probes/mounted", diff --git a/system/boot/os-prober/pspec.xml b/system/boot/os-prober/pspec.xml old mode 100644 new mode 100755 index 8d9bfd22..e10dc820 --- a/system/boot/os-prober/pspec.xml +++ b/system/boot/os-prober/pspec.xml @@ -12,20 +12,7 @@ app:console Utility to detect other OSes on a set of drives os-probe detects other OSes available on a system and outputs the results in a generic machine-readable format. Support for new OSes and Linux distributions can be added easily. - http://cdn-fastly.deb.debian.org/debian/pool/main/o/os-prober/os-prober_1.77.tar.xz - - fedora/os-prober-bootpart-name-fix.patch - fedora/os-prober-btrfsfix.patch - fedora/os-prober-factor-out-logger.patch - fedora/os-prober-factored-logger-efi-fix.patch - fedora/os-prober-gentoo-fix.patch - fedora/os-prober-grepfix.patch - fedora/os-prober-grub2-parsefix.patch - fedora/os-prober-mdraidfix.patch - fedora/os-prober-mounted-partitions-fix.patch - fedora/os-prober-no-dummy-mach-kernel.patch - fedora/os-prober-umount-fix.patch - + http://deb.debian.org/debian/pool/main/o/os-prober/os-prober_1.77.tar.xz os-prober @@ -38,12 +25,12 @@ - - 2019-10-10 + + 2019-12-26 1.77 - Version bump. - Mustafa Cinasal - muscnsl@gmail.com + Version bump + Idris Kalp + idriskalp@gmail.com 2018-07-15 diff --git a/system/boot/os-prober/translations.xml b/system/boot/os-prober/translations.xml old mode 100644 new mode 100755 From 776b8626d740f0f6d761dbd433724e9092411720 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Thu, 26 Dec 2019 19:13:08 +0300 Subject: [PATCH 073/160] baselayout rebuild --- system/base/baselayout/pspec.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/system/base/baselayout/pspec.xml b/system/base/baselayout/pspec.xml index be417e84..92d5fe7b 100644 --- a/system/base/baselayout/pspec.xml +++ b/system/base/baselayout/pspec.xml @@ -69,6 +69,13 @@ + + 2019-12-26 + 3.10.1 + Rebuild + Idris Kalp + idriskalp@gmail.com + 2019-11-07 3.10.1 From f47bed70dddba970344d100674650f43a0822318 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Thu, 26 Dec 2019 19:13:15 +0300 Subject: [PATCH 074/160] tar 1.32 --- system/base/tar/actions.py | 0 system/base/tar/files/tar.1 | 0 system/base/tar/pspec.xml | 9 ++++++++- system/base/tar/translations.xml | 0 4 files changed, 8 insertions(+), 1 deletion(-) mode change 100644 => 100755 system/base/tar/actions.py mode change 100644 => 100755 system/base/tar/files/tar.1 mode change 100644 => 100755 system/base/tar/pspec.xml mode change 100644 => 100755 system/base/tar/translations.xml diff --git a/system/base/tar/actions.py b/system/base/tar/actions.py old mode 100644 new mode 100755 diff --git a/system/base/tar/files/tar.1 b/system/base/tar/files/tar.1 old mode 100644 new mode 100755 diff --git a/system/base/tar/pspec.xml b/system/base/tar/pspec.xml old mode 100644 new mode 100755 index e52cfafb..00e49a14 --- a/system/base/tar/pspec.xml +++ b/system/base/tar/pspec.xml @@ -12,7 +12,7 @@ app:console A GNU file archiving program The GNU tar program saves many files together in one archive and can restore individual files (or all of the files) from that archive. - http://mirrors.kernel.org/gnu/tar/tar-1.30.tar.xz + http://mirrors.kernel.org/gnu/tar/tar-1.32.tar.xz tar.1 @@ -43,6 +43,13 @@ + + 2019-12-23 + 1.32 + Version bump + Idris Kalp + idriskalp@gmail.com + 2018-07-15 1.30 diff --git a/system/base/tar/translations.xml b/system/base/tar/translations.xml old mode 100644 new mode 100755 From 8f24a94be70c40602dd230c1a169f1aea4718f64 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Thu, 26 Dec 2019 19:13:56 +0300 Subject: [PATCH 075/160] ca-certificates ver bump --- system/base/ca-certificates/pspec.xml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/system/base/ca-certificates/pspec.xml b/system/base/ca-certificates/pspec.xml index 8a846c19..e5aa1502 100644 --- a/system/base/ca-certificates/pspec.xml +++ b/system/base/ca-certificates/pspec.xml @@ -11,14 +11,14 @@ app:web Common CA certificates Common CA certificates - http://ftp.debian.org/debian/pool/main/c/ca-certificates/ca-certificates_20180409.tar.xz + http://ftp.debian.org/debian/pool/main/c/ca-certificates/ca-certificates_20190110.tar.xz - no-openssl-rehash.patch + @@ -39,6 +39,13 @@ + + 2019-12-23 + 20190110 + Version Bump + Idris Kalp + idriskalp@gmail.com + 2018-07-20 20180409 From 15071f72371c051a9429137011e2149c00d38bc1 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Thu, 26 Dec 2019 19:14:10 +0300 Subject: [PATCH 076/160] man-db ver bump --- system/base/man-db/pspec.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/system/base/man-db/pspec.xml b/system/base/man-db/pspec.xml index e91d02b2..6b98dce8 100644 --- a/system/base/man-db/pspec.xml +++ b/system/base/man-db/pspec.xml @@ -22,6 +22,7 @@ gdbm-devel zlib-devel gettext-devel + libseccomp-devel libpipeline-devel @@ -33,6 +34,7 @@ gdbm zlib + libseccomp libpipeline From f3151fcb8cb14845f888ec89cc9122eb4b69b699 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Thu, 26 Dec 2019 19:14:33 +0300 Subject: [PATCH 077/160] dbus ver bump --- system/base/dbus/pspec.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/system/base/dbus/pspec.xml b/system/base/dbus/pspec.xml index e9898cc5..4395d402 100644 --- a/system/base/dbus/pspec.xml +++ b/system/base/dbus/pspec.xml @@ -13,7 +13,7 @@ service A message bus system, a simple way for applications to talk to each other D-Bus supplies both a system daemon (for events such as "new hardware device added" or "printer queue changed") and a per-user-login-session daemon (for general IPC needs among user applications). Also, the message bus is built on top of a general one-to-one message passing framework, which can be used by any two apps to communicate directly (without going through the message bus daemon). Currently the communicating applications are on one computer, but TCP/IP option is available and remote support planned. - https://dbus.freedesktop.org/releases/dbus/dbus-1.12.12.tar.gz + https://dbus.freedesktop.org/releases/dbus/dbus-1.12.16.tar.gz expat-devel libX11-devel @@ -98,6 +98,13 @@ + + 2019-12-25 + 2.12.16 + Version bump + idris Kalp + idriskalp@gmail.com + 2019-05-11 1.12.12 From 018c3dc9173690d93b1b07364a140eba7a158e12 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Thu, 26 Dec 2019 19:14:54 +0300 Subject: [PATCH 078/160] libcap-ng ver bump --- system/base/libcap-ng/pspec.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/system/base/libcap-ng/pspec.xml b/system/base/libcap-ng/pspec.xml index e8843577..be287f3c 100644 --- a/system/base/libcap-ng/pspec.xml +++ b/system/base/libcap-ng/pspec.xml @@ -12,7 +12,7 @@ library An alternate POSIX capabilities library libcap-ng is a library that makes using POSIX capabilities easier. - http://people.redhat.com/sgrubb/libcap-ng/libcap-ng-0.7.8.tar.gz + http://people.redhat.com/sgrubb/libcap-ng/libcap-ng-0.7.10.tar.gz attr-devel @@ -76,6 +76,13 @@ + + 2019-12-25 + 0.7.10 + Version bump + idris Kalp + idriskalp@gmail.com + 2018-07-15 0.7.8 From 765bfada10ff1395baa6326dcd6ad17885dcb7d8 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Thu, 26 Dec 2019 19:15:25 +0300 Subject: [PATCH 079/160] ppl --- system/devel/ppl/pspec.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/system/devel/ppl/pspec.xml b/system/devel/ppl/pspec.xml index 6f4c1c2a..8e6caa02 100644 --- a/system/devel/ppl/pspec.xml +++ b/system/devel/ppl/pspec.xml @@ -68,6 +68,13 @@ + + 2019-12-23 + 1.2 + Rebuild + Idris Kalp + idriskalp@gmail.com + 2018-07-15 1.2 From 8bd17a6b4d80c5ee2e045dba70f39d05f36e9edd Mon Sep 17 00:00:00 2001 From: idriskalp Date: Thu, 26 Dec 2019 19:15:55 +0300 Subject: [PATCH 080/160] libgcrypt fix release --- system/base/libgcrypt/pspec.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/base/libgcrypt/pspec.xml b/system/base/libgcrypt/pspec.xml index c71e0f1c..c6f64768 100644 --- a/system/base/libgcrypt/pspec.xml +++ b/system/base/libgcrypt/pspec.xml @@ -70,7 +70,7 @@ - + 2019-12-23 1.8.5 Version bump From d90cfaf3c40fc4c3b70db823a6bad16d75a6b366 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Thu, 26 Dec 2019 19:16:10 +0300 Subject: [PATCH 081/160] pciutils rebuild --- system/base/pciutils/files/pci.ids | 1682 +++++++++++++++++++++++++--- system/base/pciutils/pspec.xml | 7 + 2 files changed, 1514 insertions(+), 175 deletions(-) diff --git a/system/base/pciutils/files/pci.ids b/system/base/pciutils/files/pci.ids index 8fe86137..d96e820b 100644 --- a/system/base/pciutils/files/pci.ids +++ b/system/base/pciutils/files/pci.ids @@ -1,8 +1,8 @@ # # List of PCI ID's # -# Version: 2018.11.21 -# Date: 2018-11-21 03:15:02 +# Version: 2019.12.26 +# Date: 2019-12-26 03:15:04 # # Maintained by Albert Pool, Martin Mares, and other volunteers from # the PCI ID Project at https://pci-ids.ucw.cz/. @@ -13,6 +13,10 @@ # This file can be distributed under either the GNU General Public License # (version 2 or higher) or the 3-clause BSD License. # +# The database is a compilation of factual data, and as such the copyright +# only covers the aggregation and formatting. The copyright is held by +# Martin Mares and Albert Pool. +# # Vendors, devices and subsystems. Please keep sorted. @@ -57,8 +61,7 @@ 0680 Ultra ATA/133 IDE RAID CONTROLLER CARD # Wrong ID used in subsystem ID of the TELES.S0/PCI 2.x ISDN adapter 00a7 Teles AG (Wrong ID) -# nee nCipher -0100 Thales e-Security +0100 nCipher Security 0123 General Dynamics 0128 Dell (wrong ID) # 018a is not LevelOne but there is a board misprogrammed @@ -92,6 +95,7 @@ 6663 Butane II (MPEG2 encoder board) 6666 MediaPress (MPEG2 encoder board) 07d1 D-Link System Inc +0824 T1042 [Freescale] 0925 VIA Technologies, Inc. (Wrong ID) 0a89 BREA Technologies Inc 0b0b Rhino Equipment Corp. @@ -220,8 +224,7 @@ 0eac SHF Communication Technologies AG 0008 Ethernet Powerlink Managing Node 01 0f62 Acrox Technologies Co., Ltd. -# Formerly NCR -1000 LSI Logic / Symbios Logic +1000 Broadcom / LSI 0001 53c810 1000 1000 LSI53C810AE PCI to SCSI I/O Processor 0002 53c820 @@ -266,7 +269,10 @@ 0013 53c875a 1000 1000 LSI53C875A PCI to Ultra SCSI Controller 0014 MegaRAID Tri-Mode SAS3516 + 1028 1f3a PERC H745 Adapter + 1028 1f3b PERC H745 Front 1028 1fd4 PERC H745P MX + 1137 020e UCSC-RAID-M5 12G Modular RAID Controller 1d49 0602 ThinkSystem RAID 930-16i 4GB Flash PCIe 12Gb Adapter 1d49 0604 ThinkSystem RAID 930-8e 4GB Flash PCIe 12Gb Adapter 1d49 0607 ThinkSystem RAID 930-16i 8GB Flash PCIe 12Gb Adapter @@ -274,6 +280,9 @@ 8086 9460 RAID Controller RSP3TD160F 8086 9480 RAID Controller RSP3MD088F 0015 MegaRAID Tri-Mode SAS3416 + 1028 1f3c PERC H345 Adapter + 1028 1f3d PERC H345 Front + 1d49 0503 ThinkSystem RAID 530-16i PCIe 12Gb Adapter 0016 MegaRAID Tri-Mode SAS3508 1028 1fc9 PERC H840 Adapter 1028 1fcb PERC H740P Adapter @@ -281,7 +290,6 @@ 1028 1fcf PERC H740P Mini 1d49 0601 ThinkSystem RAID 930-8i 2GB Flash PCIe 12Gb Adapter 1d49 0603 ThinkSystem RAID 930-24i 4GB Flash PCIe 12Gb Adapter - 1d49 0604 ThinkSystem RAID 930-8e 4GB Flash PCIe 12Gb Adapter 8086 352e Integrated RAID Module RMSP3CD080F 8086 352f Integrated RAID Module RMSP3HD080E 8086 9461 RAID Controller RSP3DD080F @@ -401,7 +409,7 @@ 8086 3510 RMS25PB080 RAID Controller 8086 3511 RMS25PB040 RAID Controller 8086 3512 RMT3PB080 RAID Controller - 8086 3513 RMS25CB080 RAID Controller + 8086 3513 Integrated RAID Module RMS25CB080 8086 3514 RMS25CB040 RAID Controller 8086 351c RMS25PB080N RAID Controller 8086 351d RMS25CB080N RAID Controller @@ -445,6 +453,7 @@ 1028 1f4d PERC H330 Embedded (for monolithic) 1054 306a SAS 3004 iMR ROMB 1d49 04db ServeRAID M1210 SAS/SATA Controller + 1d49 0504 ThinkSystem RAID 520-8i PCIe 12Gb Adapter 0060 MegaRAID SAS 1078 1000 1006 MegaRAID SAS 8888ELP 1000 100a MegaRAID SAS 8708ELP @@ -479,20 +488,25 @@ 0062 SAS1078 PCI-Express Fusion-MPT SAS 1000 0062 SAS1078 PCI-Express Fusion-MPT SAS 0064 SAS2116 PCI-Express Fusion-MPT SAS-2 [Meteor] + 1000 3030 9200-16e 6Gb/s SAS/SATA PCIe x8 External HBA 1000 30c0 SAS 9201-16i + 1000 30d0 9201-16e 6Gb/s SAS/SATA PCIe x8 External HBA 0065 SAS2116 PCI-Express Fusion-MPT SAS-2 [Meteor] 006e SAS2308 PCI-Express Fusion-MPT SAS-2 0070 SAS2004 PCI-Express Fusion-MPT SAS-2 [Spitfire] 1000 3010 SAS9211-4i + 1014 040e ServeRAID H1110 0071 MR SAS HBA 2004 0072 SAS2008 PCI-Express Fusion-MPT SAS-2 [Falcon] + 1000 3040 9210-8i + 1000 3080 9200-8e [LSI SAS 6Gb/s SAS/SATA PCIe x8 External HBA] 1000 30b0 9200-8e [LSI SAS 6Gb/s SAS/SATA PCIe x8 External HBA] 1028 1f1c 6Gbps SAS HBA Adapter 1028 1f1d PERC H200 Adapter 1028 1f1e PERC H200 Integrated 1028 1f1f PERC H200 Modular 1028 1f20 PERC H200 Embedded - 1028 1f22 Internal Tape Adapter + 1028 1f22 PERC H200 Internal Tape Adapter 8086 350f RMS2LL040 RAID Controller 8086 3700 SSD 910 Series 0073 MegaRAID SAS 2008 [Falcon] @@ -500,6 +514,7 @@ 1000 9241 MegaRAID SAS 9240-4i 1000 92a0 MegaRAID SAS 9220-8i 1014 03b1 ServeRAID M1015 SAS/SATA Controller + 1014 040d ServeRAID M1115 SAS/SATA Controller 1028 1f4e PERC H310 Adapter 1028 1f4f PERC H310 Integrated 1028 1f50 PERC H310 Mini Blades @@ -507,6 +522,7 @@ 1028 1f52 PERC H310 Embedded1 1028 1f53 PERC H310 Embedded2 1028 1f54 PERC H310 Reserved + 1028 1f78 PERC H310 1054 3035 LSI MegaRAID SAS 9240-8i 1137 0072 2004 iMR ROMB 1137 0073 2008 ROMB @@ -591,8 +607,13 @@ 15d9 0691 Onboard SAS2308 PCI-Express Fusion-MPT SAS-2 0087 SAS2308 PCI-Express Fusion-MPT SAS-2 1000 3020 9207-8i SAS2.1 HBA + 1000 3030 SAS9207-4i4e 1000 3040 9207-8e SAS2.1 HBA 1000 3050 SAS9217-8i + 1000 3060 SAS9217-4i4e + 1014 0472 N2125 External Host Bus Adapter + 1590 0041 H220i + 1590 0042 H221 / 9207-8e 1590 0044 H220i 8086 3000 RS25GB008 RAID Controller 8086 3060 RS25FB044 RAID Controller @@ -620,16 +641,29 @@ 1028 1f53 HBA330 Mini 1028 1fd2 HBA330 MX 1028 1fd3 HBA330 MMZ +# Supermicro AOC-S3008L-L8e uses 0808 for their SAS3008 SAS controller + 15d9 0808 AOC-S3008L-L8e 1bd4 0011 Inspur 12Gb 8i-3008 IT SAS HBA 00ab SAS3516 Fusion-MPT Tri-Mode RAID On Chip (ROC) +# 8 Internal and 8 External port channel 9400 HBA + 1000 3040 HBA 9400-8i8e 8086 3530 Integrated RAID Module RMSP3JD160J 00ac SAS3416 Fusion-MPT Tri-Mode I/O Controller Chip (IOC) +# Channel 16 internal port HBA + 1000 3000 HBA 9400-16i +# Channel 16 external port HBA + 1000 3020 HBA 9400-16e + 1028 1fe3 HBA345 Adapter + 1028 1fe4 HBA345 Front 1d49 0201 ThinkSystem 430-16i SAS/SATA 12Gb HBA 1d49 0203 ThinkSystem 430-16e SAS/SATA 12Gb HBA 8086 3000 RAID Controller RSP3QD160J 8086 3020 RAID Controller RSP3GD016J 00ae SAS3508 Fusion-MPT Tri-Mode RAID On Chip (ROC) 00af SAS3408 Fusion-MPT Tri-Mode I/O Controller Chip (IOC) + 1000 3010 HBA 9400-8i +# 9400 Channel 8 external port HBA + 1000 3030 HBA 9400-8e 1d49 0200 ThinkSystem 430-8i SAS/SATA 12Gb HBA 1d49 0202 ThinkSystem 430-8e SAS/SATA 12Gb HBA 1d49 0204 ThinkSystem 430-8i SAS/SATA 12Gb Dense HBA @@ -651,16 +685,57 @@ 00cf MegaRAID SAS-3 3324 [Intruder] 1000 9370 MegaRAID SAS 9361-24i 00d0 SAS3716 Fusion-MPT Tri-Mode RAID Controller Chip (ROC) +# 9405W 16 internal port channel HBA + 1000 3050 HBA 9405W-16i +# 9405W 8 internal and 8 external port channel HBA + 1000 3070 HBA 9405W-8i8e 00d1 SAS3616 Fusion-MPT Tri-Mode I/O Controller Chip (IOC) +# 9405W 16 external port Channel HBA + 1000 3080 HBA 9405W-16e +# 9405W 16 internal port Channel HBA + 1000 3090 HBA 9405W-16i 00d3 MegaRAID Tri-Mode SAS3716W 00e0 Fusion-MPT 12GSAS/PCIe Unsupported SAS39xx 00e1 Fusion-MPT 12GSAS/PCIe SAS39xx 00e2 Fusion-MPT 12GSAS/PCIe Secure SAS39xx 00e3 Fusion-MPT 12GSAS/PCIe Unsupported SAS39xx 00e4 Fusion-MPT 12GSAS/PCIe Unsupported SAS38xx +# Invalid part + 1028 200b HBA355i Adapter Invalid +# Invalid part + 1028 200c HBA355i Front Invalid +# Invalid part + 1028 200d HBA355e Adapter Invalid +# Invalid part + 1028 200e HBA350i MX Invalid +# Soft Secure 00e5 Fusion-MPT 12GSAS/PCIe SAS38xx +# Soft Secure + 1028 200b HBA355i Adapter +# Soft Secure + 1028 200c HBA355i Front +# Soft Secure + 1028 200d HBA355e Adapter +# Soft Secure + 1028 200e HBA350i MX + 1d49 0205 ThinkSystem 440-16i SAS/SATA PCIe Gen4 12Gb Internal HBA + 1d49 0206 ThinkSystem 440-16e SAS/SATA PCIe Gen4 12Gb HBA 00e6 Fusion-MPT 12GSAS/PCIe Secure SAS38xx + 1028 200b HBA355i Adapter + 1028 200c HBA355i Front + 1028 200d HBA355e Adapter + 1028 200e HBA355i MX + 1d49 0205 ThinkSystem 440-16i SAS/SATA PCIe Gen4 12Gb Internal HBA + 1d49 0206 ThinkSystem 440-16e SAS/SATA PCIe Gen4 12Gb HBA 00e7 Fusion-MPT 12GSAS/PCIe Unsupported SAS38xx +# Tampered part + 1028 200b HBA355i Adapter Tampered +# Tampered part + 1028 200c HBA355i Front Tampered +# Tampered part + 1028 200d HBA355e Adapter Tampered +# Tampered part + 1028 200e HBA350i MX Tampered 02b0 Virtual Endpoint on PCIe Switch 1d49 0001 ThinkSystem 1610-4P NVMe Switch Adapter 1d49 0002 ThinkSystem 810-4P NVMe Switch Adapter @@ -737,9 +812,37 @@ 0901 61C102 1000 63C815 10e0 MegaRAID 12GSAS/PCIe Unsupported SAS39xx + 1028 1ae0 PERC H755 Adapter - Invalid Device + 1028 1ae1 PERC H755 Front - Invalid Device + 1028 1ae2 PERC H755N Front - Invalid Device + 1028 1ae3 PERC H755 MX - Invalid Device 10e1 MegaRAID 12GSAS/PCIe SAS39xx + 1028 1ae0 PERC H755 Adapter + 1028 1ae1 PERC H755 Front + 1028 1ae2 PERC H755N Front + 1028 1ae3 PERC H755 MX + 1d49 060a ThinkSystem RAID 940-8i 4GB Flash PCIe Gen4 12Gb Adapter + 1d49 060b ThinkSystem RAID 940-8i 8GB Flash PCIe Gen4 12Gb Adapter + 1d49 060c ThinkSystem RAID 940-16i 8GB Flash PCIe Gen4 12Gb Adapter + 1d49 060d ThinkSystem RAID 940-16i 8GB Flash PCIe Gen4 12Gb Internal Adapter + 1d49 060e ThinkSystem RAID 940-32i 8GB Flash PCIe Gen4 12Gb Adapter + 1d49 060f ThinkSystem RAID 940-8e 4GB Flash PCIe Gen4 12Gb Adapter 10e2 MegaRAID 12GSAS/PCIe Secure SAS39xx + 1028 1ae0 PERC H755 Adapter + 1028 1ae1 PERC H755 Front + 1028 1ae2 PERC H755N Front + 1028 1ae3 PERC H755 MX + 1d49 060a ThinkSystem RAID 940-8i 4GB Flash PCIe Gen4 12Gb Adapter + 1d49 060b ThinkSystem RAID 940-8i 8GB Flash PCIe Gen4 12Gb Adapter + 1d49 060c ThinkSystem RAID 940-16i 8GB Flash PCIe Gen4 12Gb Adapter + 1d49 060d ThinkSystem RAID 940-16i 8GB Flash PCIe Gen4 12Gb Internal Adapter + 1d49 060e ThinkSystem RAID 940-32i 8GB Flash PCIe Gen4 12Gb Adapter + 1d49 060f ThinkSystem RAID 940-8e 4GB Flash PCIe Gen4 12Gb Adapter 10e3 MegaRAID 12GSAS/PCIe Unsupported SAS39xx + 1028 1ae0 PERC H755 Adapter - Tampered Device + 1028 1ae1 PERC H755 Front - Tampered Device + 1028 1ae2 PERC H755N Front - Tampered Device + 1028 1ae3 PERC H755 MX - Tampered Device 10e4 MegaRAID 12GSAS/PCIe Unsupported SAS38xx 10e5 MegaRAID 12GSAS/PCIe SAS38xx 10e6 MegaRAID 12GSAS/PCIe Secure SAS38xx @@ -796,11 +899,26 @@ 131b Kaveri [Radeon R4 Graphics] 131c Kaveri [Radeon R7 Graphics] 131d Kaveri [Radeon R6 Graphics] + 13e9 Ariel + 1478 Navi 10 XL Upstream Port of PCI Express Switch + 1479 Navi 10 XL Downstream Port of PCI Express Switch + 154c Kryptos + 154e Garfield + 1551 Arlene + 1552 Pooky + 1561 Anubis 15d8 Picasso + 103c 8615 Pavilion Laptop 15-cw1xxx 15dd Raven Ridge [Radeon Vega Series / Radeon Vega Mobile Series] 103c 83c6 Radeon Vega 8 Mobile 1458 d000 Radeon RX Vega 11 - 15ff Vega 11 [Radeon Vega 28 Mobile] + 15de Raven/Raven2/Fenghuang HDMI/DP Audio Controller + 103c 8615 Pavilion Laptop 15-cw1xxx + 15df Raven/Raven2/Fenghuang/Renoir Cryptographic Coprocessor + 103c 8615 Pavilion Laptop 15-cw1xxx + 15ff Fenghuang [Zhongshan Subor Z+] + 1607 Arden + 1636 Renoir 1714 BeaverCreek HDMI Audio [Radeon HD 6500D and 6400G-6600G series] 103c 168b ProBook 4535s 3150 RV380/M24 [Mobility Radeon X600] @@ -882,19 +1000,28 @@ 4337 RS200M [Radeon IGP 330M/340M/345M/350M] 1014 053a ThinkPad R40e 103c 0850 Radeon IGP 345M - 4341 IXP150 AC'97 Audio Controller - 4342 IXP200 3COM 3C920B Ethernet Controller - 4345 EHCI USB Controller - 4347 OHCI USB Controller #1 - 4348 OHCI USB Controller #2 - 4349 Dual Channel Bus Master PCI IDE Controller - 434d IXP AC'97 Modem - 4353 SMBus + 4341 SB200 AC97 Audio Controller + 4342 SB200 PCI to PCI Bridge + 4345 SB200 EHCI USB Controller + 4346 Crayola 6 [XENOS Parent Die (XBOX 360)] + 4347 SB200 OHCI USB Controller #1 + 4348 SB200 OHCI USB Controller #2 + 4349 SB200 IDE Controller + 434c SB200 PCI to LPC Bridge + 434d SB200 AC97 Modem Controller + 4353 SB200 SMBus Controller 4354 215CT [Mach64 CT PCI] 4358 Mach64 CX [Graphics Xpression] - 4361 IXP SB300 AC'97 Audio Controller - 4363 SMBus - 436e 436E Serial ATA Controller + 4361 SB300 AC'97 Audio Controller + 4362 SB300 PCI to PCI Bridge + 4363 SB300 SMBus Controller + 4365 SB300 USB Controller (EHCI) + 4367 SB300 USB Controller (EHCI) + 4368 SB300 USB Controller (EHCI) + 4369 SB300 IDE Controller + 436c SB300 PCI to LPC Bridge + 436d SB300 AC97 Modem Controller + 436e SB300 Serial ATA Controller 4370 IXP SB400 AC'97 Audio Controller 1025 0079 Aspire 5024WLMMi 1025 0091 Aspire 5032WXMi @@ -1040,6 +1167,7 @@ 103c 1611 Pavilion DM1Z-3000 1043 82ef M3A78-EH Motherboard 1043 8443 M5A88-V EVO + 1043 84dd M5A99X EVO (R1.0) SB950 105b 0e13 N15235/A74MX mainboard / AMD SB700 174b 1001 PURE Fusion Mini 4392 SB7x0/SB8x0/SB9x0 SATA Controller [Non-RAID5 mode] @@ -1075,6 +1203,7 @@ 105b 0e13 N15235/A74MX mainboard / AMD SB700 174b 1001 PURE Fusion Mini 439c SB7x0/SB8x0/SB9x0 IDE Controller + 1002 4392 MSI MS-7713 motherboard 1019 2120 A785GM-M 1043 82ef M3A78-EH Motherboard 105b 0e13 N15235/A74MX mainboard / AMD SB700 @@ -1091,6 +1220,8 @@ 43a3 SB900 PCI to PCI bridge (PCIE port 3) 4437 RS250 [Mobility Radeon 7000 IGP] 4554 210888ET [Mach64 ET] + 4630 XENOS Parent Die (XBOX 360) + 4631 XENOS Daughter Die (XBOX 360) 4654 Mach64 VT 4742 Rage 3 [3D Rage PRO AGP 2X] 1002 0040 Rage Pro Turbo AGP 2X @@ -1171,6 +1302,60 @@ 1002 0084 Rage 3D Pro AGP 2x XPERT 98 1002 0087 Rage 3D IIC 1002 475a Rage IIC AGP + 4845 Xilleon 220 HBIU for HDTV2 + 4846 Xilleon 220 IDE for HDTV2 + 4847 Xilleon 220 USB for HDTV2 + 4848 Xilleon 220 DAIO-0 for HDTV2 + 4849 Xilleon 220 DAIO-1 for HDTV2 + 484a Xilleon 220 LPC for HDTV2 + 4850 Xilleon 215 HBIU for X215 + 4851 Xilleon 215 IDE for X215 + 4852 Xilleon 215 USB for X215 + 4853 Xilleon 215 DAIO-0 for X215 + 4854 Xilleon 215 DAIO-1 for X215 + 4855 Xilleon 225 HBIU for X225 + 4856 Xilleon 225 IDE for X225 + 4857 Xilleon 225 USB for X225 + 4858 Xilleon 225 DAIO-0 for X225 + 4859 Xilleon 225 DAIO-1 for X225 + 4860 Xilleon 210 HBIU for X210 + 4861 Xilleon 210 IDE for X210 + 4862 Xilleon 210 USB for X210 + 4863 Xilleon 210 DAIO-0 for X210 + 4864 Xilleon 210 DAIO-1 for X210 + 4865 Xilleon 226 HBIU for X226 + 4866 Xilleon 226 IDE for X226 + 4867 Xilleon 226 USB for X226 + 4868 Xilleon 226 DAIO-0 for X226 + 4869 Xilleon 226 DAIO-1 for X226 + 486a Xilleon 240S HBIU for X240S + 486b Xilleon 240H HBIU for X240H + 486c Xilleon 240S USB for X240S + 486d Xilleon 240H USB for X240H + 486e Xilleon 250 USB 1.1 for X250 + 486f Xilleon 260 USB 1.1 for X260 + 4870 Xilleon 250 HBIU for X250 + 4871 Xilleon 250 IDE for X250 + 4872 Xilleon 234/235 HBIU for X234/X235 + 4873 Xilleon 244/245 HBIU for X244/X245 + 4874 Xilleon 234/235 USB 1.1 for X234/X235 + 4875 Xilleon 260 HBIU for X260 + 4876 Xilleon 260 IDE for X260 + 4877 Xilleon 244/245 USB 1.1 for X244/X245 + 4878 Xilleon 270 HBIU for X270 + 487b Xilleon 242 HBIU for X242 + 487d Xilleon 242 USB 1.1 for X242 + 4880 Xilleon 254 HBIU for X254 + 4881 Xilleon 254 USB 1.1 for X254 + 4882 Xilleon 255 HBIU for X255 + 4883 Xilleon 255 USB 1.1 for X255 + 4884 Xilleon 243 HBIU for X243 + 4885 Xilleon 243 USB 1.1 for X243 + 4886 Xilleon 233 HBIU for X233 + 4887 Xilleon 233 USB 1.1 for X233 + 4888 Xilleon 143 HBIU for X143 + 4889 Xilleon 143 HBIU for X143L + 488a Xilleon 143 HBIU for X143S 4966 RV250 [Radeon 9000 Series] 10f1 0002 RV250 If [Tachyon G9000 PRO] 148c 2039 RV250 If [Radeon 9000 Pro "Evil Commando"] @@ -1400,9 +1585,9 @@ 1002 0028 Rage 128 AIW 1002 0029 Rage 128 AIW 1002 0068 Rage 128 AIW - 5246 Rage 4 [Rage Fury/Xpert 128/Xpert 2000 AGP] + 5246 Rage 128 (Rage 4) series 1002 0004 Magnum/Xpert 128/Xpert 99 - 1002 0008 Magnum/Xpert128/X99/Xpert2000 + 1002 0008 Rage 128 AGP 2x 1002 0028 Rage 128 AIW AGP 1002 0044 Rage Fury/Xpert 128/Xpert 2000 1002 0068 Rage 128 AIW AGP @@ -1645,8 +1830,6 @@ 103c 1952 ProBook 455 G1 6601 Mars [Radeon HD 8730M] 103c 2100 FirePro M4100 - 6602 Mars - 6603 Mars 6604 Opal XT [Radeon R7 M265/M365X/M465] 1025 0776 Aspire V5 Radeon R7 M265 103c 8006 FirePro M4170 @@ -1679,9 +1862,6 @@ 6613 Oland PRO [Radeon R7 240/340] 148c 7340 Radeon R7 340 1682 7240 R7 240 2048 MB - 6620 Mars - 6621 Mars PRO - 6623 Mars 6631 Oland 6640 Saturn XT [FirePro M6100] 106b 014b Tropo XT [Radeon R9 M380 Mac Edition] @@ -1723,7 +1903,7 @@ 1462 2938 Radeon R9 360 OEM 1462 3271 Radeon R9 360 OEM 1682 7360 Radeon R7 360 - 6660 Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330 / M430 / R7 M520] + 6660 Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330 / M430 / Radeon 520 Mobile] 1028 05ea Radeon HD 8670M 1028 06bf Radeon R5 M335 103c 1970 Radeon HD 8670M @@ -1739,7 +1919,8 @@ 1025 0846 Radeon HD 8570A 17aa 3805 Radeon HD 8570M 6664 Jet XT [Radeon R5 M240] - 6665 Jet PRO [Radeon R5 M230] + 6665 Jet PRO [Radeon R5 M230 / R7 M260DX / Radeon 520 Mobile] + 17aa 1309 Radeon R7 M260DX 17aa 368f Radeon R5 A230 6667 Jet ULT [Radeon R5 M230] 666f Sun LE [Radeon HD 8550M / R5 M230] @@ -1748,7 +1929,7 @@ 66a2 Vega 20 66a3 Vega 20 66a7 Vega 20 [Radeon Pro Vega 20] - 66af Vega 20 + 66af Vega 20 [Radeon VII] 6704 Cayman PRO GL [FirePro V7900] 6707 Cayman LE GL [FirePro V5900] 6718 Cayman XT [Radeon HD 6970] @@ -2368,18 +2549,22 @@ 1462 3413 Radeon RX 480 Gaming X 8GB 1462 3416 Radeon RX 570 1462 3418 Radeon RX 580 Armor 4G OC + 1462 341e Radeon RX 570 Armor 4G OC + 1462 8a92 Radeon RX 580 148c 2372 Radeon RX 480 148c 2373 Radeon RX 470 1682 9470 Radeon RX 470 1682 9480 Radeon RX 480 1682 9588 Radeon RX 580 XTR + 1682 c570 Radeon RX 570 174b e347 Radeon RX 470/480 174b e349 Radeon RX 470 1787 a470 Radeon RX 470 1787 a480 Radeon RX 480 1849 5001 Phantom Gaming X RX 580 OC + 1849 5030 Phantom Gaming D Radeon RX580 8G OC 1da2 e353 Radeon RX 570 Pulse 4GB - 1da2 e366 Nitro+ Radeon RX 580 4GB + 1da2 e366 Nitro+ Radeon RX 570/580/590 67e0 Baffin [Radeon Pro WX 4170] 103c 8270 Radeon Pro WX 4170 103c 8272 Radeon Pro WX 4170 @@ -2397,6 +2582,8 @@ 67e9 Baffin [Polaris11] 67eb Baffin [Radeon Pro V5300X] 67ef Baffin [Radeon RX 460/560D / Pro 450/455/460/555/555X/560/560X] + 1028 1703 RX 560D OEM OC 2 GB + 103c 3421 Radeon RX 460 106b 0160 Radeon Pro 460 106b 0166 Radeon Pro 455 106b 0167 Radeon Pro 450 @@ -2412,6 +2599,7 @@ 1028 1726 Radeon RX 560DX 103c 8479 Radeon RX 560X Mobile 1043 04bc Radeon RX 560 + 1043 052f Radeon RX 560 1458 22ed Radeon RX 560 148c 2381 Radeon RX 560 1682 9560 Radeon RX 560 @@ -2632,9 +2820,11 @@ 6863 Vega 10 XTX [Radeon Vega Frontier Edition] 6864 Vega 6867 Vega 10 XL [Radeon Pro Vega 56] - 6868 Vega 10 [Radeon PRO WX 8100] + 6868 Vega 10 [Radeon PRO WX 8100/8200] 686c Vega 10 [Radeon Instinct MI25 MxGPU] 687f Vega 10 XL/XT [Radeon RX Vega 56/64] + 1002 0b36 RX Vega64 + 1002 6b76 RX Vega56 6880 Lexington [Radeon HD 6550M] 103c 163c Pavilion dv6 Radeon HD 6550M 6888 Cypress XT [FirePro V8800] @@ -3102,12 +3292,13 @@ 174b e180 Radeon HD 7350 17af 3015 Radeon HD 7350 68fe Cedar LE - 6900 Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445] + 6900 Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445 / 530/535 / 620/625 Mobile] 1025 1056 Radeon R7 M360 / R8 M365DX 1028 0640 Radeon R7 M260/M265 1028 0643 Radeon R7 M260/M265 1028 067f Radeon R7 M260 1028 0767 Radeon R7 M445 + 1028 0810 Radeon 530 1028 130a Radeon R7 M260 103c 2263 Radeon R7 M260 103c 2269 Radeon R7 M260 @@ -3150,15 +3341,16 @@ 148c 9380 Radeon R9 380 # Make naming scheme consistent 174b e308 Radeon R9 380 Nitro 4G D5 - 694c Polaris 22 [Radeon RX Vega M GH] + 694c Polaris 22 XT [Radeon RX Vega M GH] 694e Polaris 22 XL [Radeon RX Vega M GL] + 694f Polaris 22 MGL XL [Radeon Pro WX Vega M GL] 6980 Polaris12 - 6981 Polaris12 + 6981 Lexa XT [Radeon PRO WX 3200] 6985 Lexa XT [Radeon PRO WX 3100] 6986 Polaris12 - 6987 Lexa [Radeon E9171 MCM] + 6987 Lexa [Radeon 540X/550X/630 / RX 640 / E9171 MCM] 6995 Lexa XT [Radeon PRO WX 2100] - 699f Lexa PRO [Radeon RX 550/550X] + 699f Lexa PRO [Radeon 540/540X/550/550X / RX 540X/550/550X] 1028 1720 Radeon RX 550X 148c 2380 Lexa XL [Radeon RX 550] 1da2 e367 Lexa PRO [Radeon RX 550] @@ -3166,7 +3358,7 @@ 69a1 Vega 12 69a2 Vega 12 69a3 Vega 12 - 69af Vega 12 + 69af Vega 12 [Radeon Pro Vega 20] 6fdf Polaris 20 XL [Radeon RX 580 2048SP] 700f RS100 AGP Bridge 7010 RS200/RS250 AGP Bridge @@ -3310,6 +3502,9 @@ 1043 049e Radeon R9 FURY 1043 04a0 Radeon R9 FURY X 174b e329 Radeon R9 FURY + 7310 Navi 10 + 731f Navi 10 [Radeon RX 5700 / 5700 XT] + 7340 Navi 14 [Radeon RX 5500 / 5500M] 7833 RS350 Host Bridge 7834 RS350 [Radeon 9100 PRO/XT IGP] 7835 RS350M [Mobility Radeon 9000 IGP] @@ -3523,16 +3718,16 @@ 9613 RS780MC [Mobility Radeon HD 3100] 9614 RS780D [Radeon HD 3300] 9616 RS780L [Radeon 3000] - 9640 BeaverCreek [Radeon HD 6550D] - 9641 BeaverCreek [Radeon HD 6620G] - 9642 Sumo [Radeon HD 6370D] - 9643 Sumo [Radeon HD 6380G] - 9644 Sumo [Radeon HD 6410D] - 9645 Sumo [Radeon HD 6410D] - 9647 BeaverCreek [Radeon HD 6520G] + 9640 Sumo [Radeon HD 6550D] + 9641 Sumo [Radeon HD 6620G] + 9642 SuperSumo [Radeon HD 6370D] + 9643 SuperSumo [Radeon HD 6380G] + 9644 SuperSumo [Radeon HD 6410D] + 9645 SuperSumo [Radeon HD 6410D] + 9647 Sumo [Radeon HD 6520G] 9648 Sumo [Radeon HD 6480G] - 9649 Sumo [Radeon HD 6480G] - 964a BeaverCreek [Radeon HD 6530D] + 9649 SuperSumo [Radeon HD 6480G] + 964a Sumo [Radeon HD 6530D] 964b Sumo 964c Sumo 964e Sumo @@ -3602,6 +3797,8 @@ 17aa 5113 Radeon R6 Graphics 17aa 5116 Radeon R6 Graphics 17aa 5118 Radeon R5 Graphics + 9890 Amur + 98c0 Nolan 98e4 Stoney [Radeon R2/R3/R4/R5 Graphics] 9900 Trinity [Radeon HD 7660G] 103c 1985 Pavilion 17-e163sg Notebook PC @@ -3630,13 +3827,19 @@ 9917 Trinity [Radeon HD 7620G] 9918 Trinity [Radeon HD 7600G] 9919 Trinity [Radeon HD 7500G] + 991e Bishop 9920 Liverpool [Playstation 4 APU] 9921 Liverpool HDMI/DP Audio Controller - 9990 Trinity [Radeon HD 7520G] - 9991 Trinity [Radeon HD 7540D] - 9992 Trinity [Radeon HD 7420G] - 9993 Trinity [Radeon HD 7480D] - 9994 Trinity [Radeon HD 7400G] + 9922 Starshp + 9923 Starsha2 [Kingston/Clayton] + 9924 Gladius + 9925 Kingston/Clayton/Jupiter/Gladius/Montego HDMI Controller + 9926 Jupiter + 9990 Trinity 2 [Radeon HD 7520G] + 9991 Trinity 2 [Radeon HD 7540D] + 9992 Trinity 2 [Radeon HD 7420G] + 9993 Trinity 2 [Radeon HD 7480D] + 9994 Trinity 2 [Radeon HD 7400G] 9995 Richland [Radeon HD 8450G] 9996 Richland [Radeon HD 8470D] 9997 Richland [Radeon HD 8350G] @@ -3644,12 +3847,12 @@ 9999 Richland [Radeon HD 8510G] 999a Richland [Radeon HD 8410G] 999b Richland [Radeon HD 8310G] - 999c Richland + 999c Richland [Radeon HD 8650D] # AMD Quad-Core A8-Series APU A8-6500T with Radeon HD 8550D 999d Richland [Radeon HD 8550D] - 99a0 Trinity [Radeon HD 7520G] - 99a2 Trinity [Radeon HD 7420G] - 99a4 Trinity [Radeon HD 7400G] + 99a0 Trinity 2 [Radeon HD 7520G] + 99a2 Trinity 2 [Radeon HD 7420G] + 99a4 Trinity 2 [Radeon HD 7400G] aa00 R600 HDMI Audio [Radeon HD 2900 GT/PRO/XT] aa01 RV635 HDMI Audio [Radeon HD 3650/3730/3750] aa08 RV630 HDMI Audio [Radeon HD 2600 PRO/XT / HD 3610] @@ -3678,17 +3881,38 @@ aa98 Caicos HDMI Audio [Radeon HD 6450 / 7450/8450/8490 OEM / R5 230/235/235X OEM] 174b aa98 Radeon HD 6450 1GB DDR3 aaa0 Tahiti HDMI Audio [Radeon HD 7870 XT / 7950/7970] - aab0 Cape Verde/Pitcairn HDMI Audio [Radeon HD 7700/7800 Series] + aab0 Oland/Hainan/Cape Verde/Pitcairn HDMI Audio [Radeon HD 7000 Series] + aab8 Tiran HDMI Audio aac0 Tobago HDMI Audio [Radeon R7 360 / R9 360 OEM] aac8 Hawaii HDMI Audio [Radeon R9 290/290X / 390/390X] -# I have a Tonga card and this is the HDMI Audio part aad8 Tonga HDMI Audio [Radeon R9 285/380] 174b aad8 Radeon R9 285/380 HDMI Audio aae0 Baffin HDMI/DP Audio [Radeon RX 550 640SP / RX 560/560X] aae8 Fiji HDMI/DP Audio [Radeon R9 Nano / FURY/FURY X] - aaf0 Ellesmere [Radeon RX 580] - ac00 Theater 600 Pro + aaf0 Ellesmere HDMI Audio [Radeon RX 470/480 / 570/580/590] + aaf8 Vega 10 HDMI Audio [Radeon Vega 56/64] + ab00 Baffin HDMI/DP Audio [Radeon RX 550 640SP / RX 560/560X] + ab08 Polaris 22 HDMI Audio + ab10 Lexa HDMI Audio + ab18 Vega 12 HDMI Audio + ab20 Vega 20 HDMI Audio [Radeon VII] + ab38 Navi 10 HDMI Audio + ac00 Theater 506 World-Wide Analog Decoder + ac01 Theater 506 World-Wide Analog Decoder ac02 TV Wonder HD 600 PCIe + ac03 Theater 506 PCIe + ac04 Theater 506 USB + ac05 Theater 506 USB + ac06 Theater 506 External USB + ac07 Theater 506 External USB + ac08 Theater 506A World-Wide Analog Decoder + Demodulator + ac09 Theater 506A World-Wide Analog Decoder + Demodulator + ac0a Theater 506A PCIe + ac0b Theater 506A PCIe + ac0c Theater 506A USB + ac0d Theater 506A USB + ac0e Theater 506A External USB + ac0f Theater 506A External USB ac12 Theater HD T507 (DVB-T) TV tuner/capture device cab0 RS100 Host Bridge cab2 RS200 Host Bridge @@ -4200,6 +4424,35 @@ 1302 Family 11h Processor DRAM Controller 1303 Family 11h Processor Miscellaneous Control 1304 Family 11h Processor Link Control + 1305 Griffin Function 5 + 1306 Griffin Function 6 + 1307 Griffin Function 7 + 1308 Kaveri Audio Controller + 1314 Wrestler/Bheem/Ontario/Krishna Audio Controller + 13e0 Ariel Root Complex + 13e1 Ariel IOMMU + 13e2 Ariel PCIe Dummy Host Bridge + 13e3 Ariel PCIe GPP Bridge + 13e4 Ariel PCIe Dummy Host Bridge + 13e5 Ariel Internal PCIe GPP Bridge 0 to Bus A + 13e6 Ariel Internal PCIe GPP Bridge 0 to Bus B + 13e7 Ariel SMBus Controller + 13e8 Ariel LPC Bridge + 13e9 Ariel Internal GPU + 13ea Ariel HD Audio Controller + 13eb Ariel HD Audio Coprocessor + 13ec Ariel Cryptographic Coprocessor + 13ed Ariel USB 3.1 Type C: Gen2 x 1port + DP Alt Mode + 13ee Ariel USB 3.1 Type A: Gen2 x 2 ports + 13ef Ariel ZCN/MP4 + 13f0 Ariel Device 24: Function 0 + 13f1 Ariel Device 24: Function 1 + 13f2 Ariel Device 24: Function 2 + 13f3 Ariel Device 24: Function 3 + 13f4 Ariel Device 24: Function 4 + 13f5 Ariel Device 24: Function 5 + 13f6 Ariel Device 24: Function 6 + 13f7 Ariel Device 24: Function 7 1400 Family 15h (Models 10h-1fh) Processor Function 0 1401 Family 15h (Models 10h-1fh) Processor Function 1 1402 Family 15h (Models 10h-1fh) Processor Function 2 @@ -4227,26 +4480,51 @@ 1422 Family 15h (Models 30h-3fh) Processor Root Complex 1423 Family 15h (Models 30h-3fh) I/O Memory Management Unit 1424 Family 15h (Models 30h-3fh) Processor Root Port + 1425 Kaveri P2P Bridge for GFX PCIe Port [1:0] 1426 Family 15h (Models 30h-3fh) Processor Root Port - 142e Liverpool Processor Function 0 - 142f Liverpool Processor Function 1 - 1430 Liverpool Processor Function 2 - 1431 Liverpool Processor Function 3 - 1432 Liverpool Processor Function 4 + 142e Liverpool Processor HT configuration + 142f Liverpool Processor Address Maps + 1430 Liverpool Processor DRAM configuration + 1431 Liverpool Processor Misc configuration + 1432 Liverpool Processor PM configuration + 1433 Liverpool Processor NB Performance Monitor + 1434 Liverpool Processor SPLL Configuration 1436 Liverpool Processor Root Complex 1437 Liverpool I/O Memory Management Unit - 1438 Liverpool Processor Root Port + 1438 Liverpool UMI PCIe Dummy Host Bridge 1439 Family 16h Processor Functions 5:1 + 143a Kingston/Clayton/Gladius/Montego Root Complex + 143b Kingston/Clayton/Gladius/Montego P2P Bridge for UMI Link + 1440 Matisse Device 24: Function 0 + 1441 Matisse Device 24: Function 1 + 1442 Matisse Device 24: Function 2 + 1443 Matisse Device 24: Function 3 + 1444 Matisse Device 24: Function 4 + 1445 Matisse Device 24: Function 5 + 1446 Matisse Device 24: Function 6 + 1447 Matisse Device 24: Function 7 + 1448 Renoir Device 24: Function 0 + 1449 Renoir Device 24: Function 1 + 144a Renoir Device 24: Function 2 + 144b Renoir Device 24: Function 3 + 144c Renoir Device 24: Function 4 + 144d Renoir Device 24: Function 5 + 144e Renoir Device 24: Function 6 + 144f Renoir Device 24: Function 7 1450 Family 17h (Models 00h-0fh) Root Complex 1451 Family 17h (Models 00h-0fh) I/O Memory Management Unit - 1452 Family 17h (Models 00h-0fh) PCIe Dummy Host Bridge + 1452 Family 17h (Models 00h-1fh) PCIe Dummy Host Bridge 1453 Family 17h (Models 00h-0fh) PCIe GPP Bridge 1454 Family 17h (Models 00h-0fh) Internal PCIe GPP Bridge 0 to Bus B + 1455 Zeppelin/Renoir PCIe Dummy Function 1456 Family 17h (Models 00h-0fh) Platform Security Processor 1457 Family 17h (Models 00h-0fh) HD Audio Controller + 145a Zeppelin/Raven/Raven2 PCIe Dummy Function 145b Zeppelin Non-Transparent Bridge 145c Family 17h (Models 00h-0fh) USB 3.0 Host Controller - 145f USB 3.0 Host controller + 145d Zeppelin Switch Upstream (PCIE SW.US) + 145e Zeppelin Switch Downstream (PCIE SW.DS) + 145f Zeppelin USB 3.0 Host controller 1460 Family 17h (Models 00h-0fh) Data Fabric: Device 18h; Function 0 1461 Family 17h (Models 00h-0fh) Data Fabric: Device 18h; Function 1 1462 Family 17h (Models 00h-0fh) Data Fabric: Device 18h; Function 2 @@ -4255,6 +4533,39 @@ 1465 Family 17h (Models 00h-0fh) Data Fabric: Device 18h; Function 5 1466 Family 17h (Models 00h-0fh) Data Fabric: Device 18h; Function 6 1467 Family 17h (Models 00h-0fh) Data Fabric: Device 18h; Function 7 + 1468 Zeppelin Cryptographic Coprocessor NTBCCP + 1480 Starship/Matisse Root Complex + 1462 7c37 X570-A PRO motherboard + 1481 Starship/Matisse IOMMU + 1482 Starship/Matisse PCIe Dummy Host Bridge + 1483 Starship/Matisse GPP Bridge + 1484 Starship/Matisse Internal PCIe GPP Bridge 0 to bus[E:B] + 1485 Starship/Matisse Reserved SPP + 1486 Starship/Matisse Cryptographic Coprocessor PSPCPP + 1487 Starship/Matisse HD Audio Controller + 1462 9c37 X570-A PRO motherboard + 1488 Starship Reserved SSP + 1489 Starship Reserved SSP + 148a Starship/Matisse PCIe Dummy Function + 148b Starship/Matisse Non-Transparent Bridge + 148c Starship USB 3.0 Host Controller + 148d Starship/Matisse Switch Upstream (PCIE SW.US) + 148e Starship/Matisse Switch Downstream (PCIE SW.DS) + 148f Starship Reserved SSP + 1490 Starship Device 24; Function 0 + 1491 Starship Device 24; Function 1 + 1492 Starship Device 24; Function 2 + 1493 Starship Device 24; Function 3 + 1494 Starship Device 24; Function 4 + 1495 Starship Device 24; Function 5 + 1496 Starship Device 24; Function 6 + 1497 Starship Device 24; Function 7 + 1498 Starship/Matisse PTDMA + 1499 Starship/Matisse NVMe + 149a Starship PCIe GPP Bridge [1:0] + 149b Starship Reserved SSP + 149c Matisse USB 3.0 Host Controller + 1462 7c37 X570-A PRO motherboard 1510 Family 14h Processor Root Complex 174b 1001 PURE Fusion Mini 1512 Family 14h Processor Root Port @@ -4269,7 +4580,33 @@ 1534 Family 16h Processor Function 4 1535 Family 16h Processor Function 5 1536 Family 16h Processor Root Complex + 1537 Kabini/Mullins PSP-Platform Security Processor 1538 Family 16h Processor Function 0 + 1539 Kabini P2P Bridge for PCIe Ports[4:0] + 1540 Kryptos/Cato/Garfield/Garfield+/Arlene/Pooky HT Configuration + 1541 Kryptos/Cato/Garfield/Garfield+/Arlene/Pooky Address Maps + 1542 Kryptos/Cato/Garfield/Garfield+/Arlene/Pooky DRAM Configuration + 1543 Kryptos/Cato/Garfield/Garfield+/Arlene/Pooky Miscellaneous Configuration + 1544 Kryptos/Cato/Garfield/Garfield+/Arlene/Pooky PM Configuration + 1545 Kryptos/Cato/Garfield/Garfield+/Arlene/Pooky NB Performance Monitor + 1546 Kryptos/Cato/Garfield/Garfield+/Arlene/Pooky Root Complex + 1547 Kryptos/Cato/Garfield/Garfield+/Arlene/Pooky IOMMU + 1548 Kryptos/Cato/Garfield/Garfield+/Arlene/Pooky UMI PCIe Dummy Host Bridge + 1549 Kryptos/Cato/Garfield/Garfield+ P2P Bridge for PCIe Port [3:0] + 154a Kryptos/Cato/Garfield/Garfield+/Arlene/Pooky Audio Processor + 154b Kryptos/Cato/Garfield/Garfield+/Arlene/Pooky Security Processor + 154d Kryptos/Cato/Garfield/Garfield+/Arlene/Pooky/Anubis HDMI Controller + 154f Anubis Audio Processor + 1550 Garfield+/Arlene/Pooky/Anubis SPLL Configuration + 1553 Arlene/Pooky P2P Bridge for PCIE (3:0) + 155b Anubis Root Complex + 155c Anubis IOMMU + 155d Anubis UMI PCIe Dummy Bridge + 155e Anubis P2P Bridge for PCIe Ports [4:0] + 1560 Anubis Security Processor + 1566 Family 16h (Models 30h-3fh) Processor Root Complex + 1567 Mullins IOMMU + 156b Family 16h (Models 30h-3fh) Host Bridge 1570 Family 15h (Models 60h-6fh) Processor Function 0 1571 Family 15h (Models 60h-6fh) Processor Function 1 1572 Family 15h (Models 60h-6fh) Processor Function 2 @@ -4278,21 +4615,132 @@ 1575 Family 15h (Models 60h-6fh) Processor Function 5 1576 Family 15h (Models 60h-6fh) Processor Root Complex 1577 Family 15h (Models 60h-6fh) I/O Memory Management Unit + 1578 Carrizo Platform Security Processor + 1579 Carrizo Audio Processor 157a Family 15h (Models 60h-6fh) Audio Controller 157b Family 15h (Models 60h-6fh) Host Bridge 157c Family 15h (Models 60h-6fh) Processor Root Port + 157d Carrizo Audio Dummy Host Bridge + 157e Carrizo Audio Controller + 1580 Family 16h (Models 30h-3fh) Processor Function 0 + 1581 Family 16h (Models 30h-3fh) Processor Function 1 + 1582 Family 16h (Models 30h-3fh) Processor Function 2 + 1583 Family 16h (Models 30h-3fh) Processor Function 3 + 1584 Family 16h (Models 30h-3fh) Processor Function 4 + 1585 Family 16h (Models 30h-3fh) Processor Function 5 + 1590 Amur/Nolan HT Configuration + 1591 Amur/Nolan Address Maps + 1592 Amur/Nolan DRAM Configuration + 1593 Amur/Nolan Miscellaneous Configuration + 1594 Amur/Nolan PM Configuration + 1595 Amur/Nolan NB Performance Monitor + 1596 Amur/Nolan Root Complex + 1597 Amur/Nolan IOMMU + 1598 Amur/Nolan Platform Security Processor + 1599 Amur/Nolan PCIe Dummy Host Bridge + 159d Amur Function 6: Gasket + 15b0 Stoney HT Configuration + 15b1 Stoney Address Maps + 15b2 Stoney DRAM Configuration + 15b3 Stoney Miscellaneous Configuration + 15b4 Stoney PM Configuration + 15b5 Stoney NB Performance Monitor + 15bc Stoney PCIe [GFX,GPP] Bridge [4:0] + 15be Stoney Audio Processor + 15d0 Raven/Raven2 Root Complex + 103c 8615 Pavilion Laptop 15-cw1xxx + 15d1 Raven/Raven2 IOMMU + 103c 8615 Pavilion Laptop 15-cw1xxx + 15d2 Raven/Raven2 PCIe Dummy Host Bridge + 15d3 Raven/Raven2 PCIe GPP Bridge [6:0] + 15d4 FireFlight USB 3.1 + 15d5 FireFlight USB 3.1 + 15da Raven/Raven2 PCIe Dummy Host Bridge + 15db Raven/Raven2 Internal PCIe GPP Bridge 0 to Bus A + 15dc Raven/Raven2 Internal PCIe GPP Bridge 0 to Bus B + 15de Raven/Raven2/FireFlight HD Audio Controller + 15df Family 17h (Models 10h-1fh) Platform Security Processor + 15e0 Raven USB 3.1 + 103c 8615 Pavilion Laptop 15-cw1xxx + 15e1 Raven USB 3.1 + 103c 8615 Pavilion Laptop 15-cw1xxx + 15e2 Raven/Raven2/FireFlight/Renoir Audio Processor + 15e3 Family 17h (Models 10h-1fh) HD Audio Controller + 103c 8615 Pavilion Laptop 15-cw1xxx + 15e4 Raven/Raven2/Renoir Sensor Fusion Hub + 15e5 Raven2 USB 3.1 + 15e6 Raven/Raven2/Renoir Non-Sensor Fusion Hub KMDF driver + 1022 15e4 Raven/Raven2/Renoir Sensor Fusion Hub + 15e8 Raven/Raven2 Device 24: Function 0 + 15e9 Raven/Raven2 Device 24: Function 1 + 15ea Raven/Raven2 Device 24: Function 2 + 15eb Raven/Raven2 Device 24: Function 3 + 15ec Raven/Raven2 Device 24: Function 4 + 15ed Raven/Raven2 Device 24: Function 5 + 15ee Raven/Raven2 Device 24: Function 6 + 15ef Raven/Raven2 Device 24: Function 7 + 15f0 FireFlight Device 24: Function 0 + 15f1 FireFlight Device 24: Function 1 + 15f2 FireFlight Device 24: Function 2 + 15f3 FireFlight Device 24: Function 3 + 15f4 FireFlight Device 24: Function 4 + 15f5 FireFlight Device 24: Function 5 + 15f6 FireFlight Device 24: Function 6 + 15f7 FireFlight Device 24: Function 7 + 15f8 FireFlight Root Complex + 15f9 FireFlight IOMMU + 15fa FireFlight PCIe Dummy Host Bridge + 15fb FireFlight PCIe GPP Bride 3:0 + 15fc FireFlight PCIe Dummy Host Bridge + 15fd FireFlight Internal PCIe GPP Bridge 0 to Bus A + 15fe FireFlight Internal PCIe GPP Bridge 0 to Bus B + 15ff FireFlight Bus A; Device 0: Function 0: Internal GPU 1600 Family 15h Processor Function 0 1601 Family 15h Processor Function 1 1602 Family 15h Processor Function 2 1603 Family 15h Processor Function 3 1604 Family 15h Processor Function 4 1605 Family 15h Processor Function 5 + 1606 Arden Security Processor + 1608 Arden Device 18h: Function 0 + 1609 Arden Device 18h: Function 1 + 160a Arden Device 18h: Function 2 + 160b Arden Device 18h: Function 3 + 160c Arden Device 18h: Function 4 + 160d Arden Device 18h: Function 5 + 160e Arden Device 18h: Function 6 + 160f Arden Device 18h: Function 7 + 1620 Anubis HT Configuration + 1621 Anubis Address Maps + 1622 Anubis DRAM Configuration + 1623 Anubis Miscellaneous Configuration + 1624 Anubis PM Configuration + 1625 Anubis NB Performance Monitor + 1626 Arden Root Complex + 1627 Arden IOMMU + 1628 Arden PCIe Dummy Host Bridge + 1629 Arden PCIe GPP Bridge + 162a Arden Internal PCIe GPP Bridge 0 to bus X + 162b Arden PCIe Non-Transparent Bridge + 1630 Renoir Root Complex + 1631 Renoir IOMMU + 1632 Renoir PCIe Dummy Host Bridge + 1633 Renoir PCIe GPP Bridge + 1634 Renoir PCIe GPP Bridge + 1635 Renoir Internal PCIe GPP Bridge to Bus + 1637 Renoir HD Audio Controller + 1639 Renoir USB 3.1 + 1641 Renoir 10GbE Controller Port 0 (XGBE0/1) + 1642 Renoir WLAN + 1643 Renoir BT + 1644 Renoir I2S 1700 Family 12h/14h Processor Function 0 1701 Family 12h/14h Processor Function 1 1702 Family 12h/14h Processor Function 2 1703 Family 12h/14h Processor Function 3 1704 Family 12h/14h Processor Function 4 1705 Family 12h Processor Root Complex + 1706 Llano P2P Bridge to external GPU 1707 Family 12h Processor Root Port 1708 Family 12h Processor Root Port 1709 Family 12h Processor Root Port @@ -4362,6 +4810,13 @@ 1849 43d0 Fatal1ty X370 Professional Gaming 43ba X399 Series Chipset USB 3.1 xHCI Controller 43bb 300 Series Chipset USB 3.1 xHCI Controller + 43c6 400 Series Chipset PCIe Bridge + 43c7 400 Series Chipset PCIe Port + 43c8 400 Series Chipset SATA Controller + 43d5 400 Series Chipset USB 3.1 XHCI Controller + 57a3 Matisse PCIe GPP Bridge + 57a4 Matisse PCIe GPP Bridge + 57ad Matisse Switch Upstream 7006 AMD-751 [Irongate] System Controller 7007 AMD-751 [Irongate] AGP Bridge 700a AMD-IGR4 AGP Host to PCI Bridge @@ -4434,6 +4889,7 @@ 103c 1985 Pavilion 17-e163sg Notebook PC 7809 FCH USB OHCI Controller 103c 194e ProBook 455 G1 Notebook + 780a Kabini/Mullins SATA Raid/AHCI Mode (DotHill driver) 780b FCH SMBus Controller 103c 194e ProBook 455 G1 Notebook 103c 1985 Pavilion 17-e163sg Notebook PC @@ -4453,13 +4909,19 @@ 103c 1985 Pavilion 17-e163sg Notebook PC 7900 FCH SATA Controller [IDE mode] 7901 FCH SATA Controller [AHCI mode] + 103c 8615 Pavilion Laptop 15-cw1xxx + 1462 7c37 X570-A PRO motherboard 7902 FCH SATA Controller [RAID mode] 7903 FCH SATA Controller [RAID mode] 7904 FCH SATA Controller [AHCI mode] 7906 FCH SD Flash Controller 7908 FCH USB EHCI Controller 790b FCH SMBus Controller + 103c 8615 Pavilion Laptop 15-cw1xxx + 1462 7c37 X570-A PRO motherboard 790e FCH LPC Bridge + 103c 8615 Pavilion Laptop 15-cw1xxx + 1462 7c37 X570-A PRO motherboard 790f FCH PCI Bridge 7914 FCH USB XHCI Controller 9600 RS780 Host Bridge @@ -4467,6 +4929,7 @@ 1043 82f1 M3A78-EH Motherboard 9601 RS880 Host Bridge 1019 2120 A785GM-M + 1043 83a2 M4A785-M Mainboard 1043 843e M5A88-V EVO 9602 RS780/RS880 PCI to PCI bridge (int gfx) 9603 RS780 PCI to PCI bridge (ext gfx port 0) @@ -5326,6 +5789,7 @@ 122e PCI-X Local Bus Adapter 127b sx1000 System Bus Adapter 127c sx1000 I/O Controller + 128d Diva [GSP] Management Board 1290 Auxiliary Diva Serial Port 103c 1291 Diva SP2 1291 Auxiliary Diva Serial Port @@ -5855,10 +6319,20 @@ 104d Sony Corporation 8004 DTL-H2500 [Playstation development board] 8009 CXD1947Q i.LINK Controller + 800c DTL-H800 [PS1 sound development board] 8039 CXD3222 i.LINK Controller + 8047 PS2 TOOL MRP 8056 Rockwell HCF 56K modem 808a Memory Stick Controller + 80ff PS2 Performance Analyzer + 814a PS2 Performance Analyzer + 8183 ATHENS [PS3 prototype developer interface card] + 81b0 BM-1 [PSP TOOL Board Management Device] + 81c3 VO-4 [PSP TOOL Video Output Device] 81ce SxS Pro memory card + 81ff PS3 TOOL MRP + 8200 PS3 TOOL RSX Tracing FPGA + 820e CXD9208GP [PS3 PS2 emulation subsystem adapter] # 2nd ID 905c SxS Pro memory card # 2nd ID @@ -6296,6 +6770,7 @@ 1645 Broadcom NetXtreme BCM5701 Gigabit Ethernet 1801 T2 Bridge Controller 1802 T2 Secure Enclave Processor + 1803 Apple Audio Device 2001 S1X NVMe Controller 2002 S3ELab NVMe Controller 2003 S3X NVMe Controller @@ -6366,19 +6841,23 @@ 1654 FastLinQ QL45000 Series 50GbE Controller 1077 0032 QL45212 Flex 50Gb 2-port Ethernet Adapter 1590 0223 Synergy 6810C 25/50Gb Ethernet Adapter + 1590 0287 Synergy 6820C 25/50Gb CNA 1656 FastLinQ QL45000 Series 25GbE Controller 1077 0033 QL45214 Flex 25Gb 4-port Ethernet Adapter 1077 02a7 QL45212-DE 25GbE Adapter 1077 e4f6 FastLinQ QL45211H 25GbE Adapter 1077 e4f7 FastLinQ QL45212H 25GbE Adapter + 1590 0245 10/20/25GbE 2P 4820c CNA 165c FastLinQ QL45000 Series 10/25/40/50GbE Controller (FCoE) 1077 0034 QL45262 Flex 50Gb 2-port Ethernet Adapter w/ iSCSI/FCoE 1077 e4f1 FastLinQ QL45462H 40GbE FCoE Adapter 1077 e4f2 FastLinQ QL45461H 40GbE FCoE Adapter + 1590 0245 10/20/25GbE 2P 4820c CNA FCoE 165e FastLinQ QL45000 Series 10/25/40/50GbE Controller (iSCSI) 1077 0034 QL45262 Flex 50Gb 2-port Ethernet Adapter w/ iSCSI/FCoE 1077 e4f1 FastLinQ QL45462H 40GbE iSCSI Adapter 1077 e4f2 FastLinQ QL45461H 40GbE iSCSI Adapter + 1590 0245 10/20/25GbE 2P 4820c CNA iSCSI 1664 FastLinQ QL45000 Series Gigabit Ethernet Controller (SR-IOV VF) 1077 e4f1 FastLinQ QL45462H 40GbE Adapter (SR-IOV VF) 1077 e4f2 FastLinQ QL45461H 40GbE Adapter (SR-IOV VF) @@ -6387,6 +6866,7 @@ 1077 e4f6 FastLinQ QL45211H 25GbE Adapter (SR-IOV VF) 1077 e4f7 FastLinQ QL45212H 25GbE Adapter (SR-IOV VF) 1077 e4f8 FastLinQ QL45611H 100GbE Adapter (SR-IOV VF) + 1590 0245 10/20/25GbE 2P 4820c CNA SRIOV 2020 ISP2020A Fast!SCSI Basic Adapter 2031 ISP8324-based 16Gb Fibre Channel to PCI Express Adapter 103c 17e7 SN1000Q 16Gb Single Port Fibre Channel Adapter @@ -6398,6 +6878,9 @@ 1077 029e QLE2694 Quad Port 16Gb Fibre Channel to PCIe Adapter 1077 02a2 QLE2694L Quad Port 16Gb Fibre Channel to PCIe Adapter 1077 02ad QLE2694U Quad Port 16/32Gb Fibre Channel to PCIe Adapter + 2081 ISP2814-based 64/32G Fibre Channel to PCIe Controller + 1077 02e1 QLE2874 Quad Port 64GFC PCIe Gen4 x16 Adapter + 1077 02e3 QLE2774 Quad Port 32GFC PCIe Gen4 x16 Adapter 2100 QLA2100 64-bit Fibre Channel Adapter 1077 0001 QLA2100 64-bit Fibre Channel Adapter 2200 QLA2200 64-bit Fibre Channel Adapter @@ -6417,6 +6900,14 @@ 1590 00fa StoreFabric SN1100Q 16Gb Dual Port Fibre Channel Host Bus Adapter 1590 0203 StoreFabric SN1600Q 32Gb Single Port Fibre Channel Host Bus Adapter 1590 0204 StoreFabric SN1600Q 32Gb Dual Port Fibre Channel Host Bus Adapter + 1590 022d 5830C 32Gb Dual Port Fibre Channel Adapter + 2281 ISP2812-based 64/32G Fibre Channel to PCIe Controller + 1077 02e2 QLE2872 Dual Port 64GFC PCIe Gen4 x8 Adapter + 1077 02e4 QLE2772 Dual Port 32GFC PCIe Gen4 x8 Adapter + 1077 02ee QLE2870 Single Port 64GFC PCIe Gen4 x8 Adapter + 1077 02f0 QLE2770 Single Port 32GFC PCIe Gen4 x8 Adapter + 1590 02d3 SN1610Q - 1P Enhanced 32GFC Single Port Fibre Channel Host Bus Adapter + 1590 02d4 SN1610Q – 2P Enhanced 32GFC Dual Port Fibre Channel Host Bus Adapter 2300 QLA2300 64-bit Fibre Channel Adapter 2312 ISP2312-based 2Gb Fibre Channel to PCI-X HBA 103c 0131 2Gb Fibre Channel - Single port [A7538A] @@ -6488,12 +6979,25 @@ 1077 0012 FastLinQ QL41112H 10GbE Adapter 1077 0019 QL41232HOCU - Dual Port 25/10GbE SFP28 OCP Adapter 1077 0039 QLogic QL41262 PCIe 25Gb 2-Port SFP28 Ethernet Adapter + 1077 0053 QLogic 2x25GE QL41232HQCU NIC + 1077 0054 2x10GE QL41132HQRJ NIC + 1077 0055 QLogic 2x10GE QL41132HQCU NIC + 1077 0056 2x10GE QL41132HxRJ NIC + 1077 0057 2x25GE QL41232HxCU NIC + 1077 0068 10GbE 2p SFP+ QL41132HLCU-HC Adapter + 1077 0069 10GbE 2p BASE-T QL41132HQRJ-HC OCP3 Adapter + 1077 0070 10GbE 2p BASE-T QL41132HLRJ-HC Adapter + 1077 0071 10GbE 2p SFP+ QL41132HQCU-HC OCP3 Adapter + 1077 0072 10GbE 4p SFP+ QL41134HLCU-HC Adapter + 1077 0073 10/25GbE 2p SFP28 QL41232HQCU-HC OCP3 Adapter + 1077 0074 10/25GbE 2p SFP28 QL41232HLCU-HC Adapter 1590 021a 10GbE 2P QL41162HLRJ-HP Adapter 1590 021b 10GbE 2P QL41162HLRJ-HP Adapter 1590 021d 10/25GbE 2P QL41222HLCU-HP Adapter 1590 021e 10/25GbE 2P QL41162HMRJ-HP Adapter 1590 021f 10/25GbE 2P QL41262HMCU-HP Adapter 1590 0220 10/25GbE 2P QL41122HLRJ-HP Adapter + 1590 02bd 10Gb 2P 524SFP+ NIC 8080 FastLinQ QL41000 Series 10/25/40/50GbE Controller (FCoE) 1077 0001 10GE 2P QL41162HxRJ-DE Adapter 1077 0002 10GE 2P QL41112HxCU-DE Adapter @@ -6542,10 +7046,16 @@ 1077 0010 2x25GE QL41232HMKR NIC 1077 0011 FastLinQ QL41212H 25GbE Adapter (SR-IOV VF) 1077 0012 FastLinQ QL41112H 10GbE Adapter (SR-IOV VF) + 1077 0053 QLogic 2x25GE QL41232HQCU NIC + 1077 0054 QLogic 2x10GE QL41132HQRJ NIC + 1077 0055 QLogic 2x10GE QL41132HQCU NIC + 1077 0056 2x10GE QL41132HxRJ NIC + 1077 0057 2x25GE QL41232HxCU NIC 1590 021a 10GbE 2P QL41162HLRJ-HP Adapter 1590 021b 10GbE 2P QL41162HLRJ-HP Adapter 1590 021e 10/25GbE 2P QL41162HMRJ-HP Adapter 1590 021f 10/25GbE 2P QL41262HMCU-HP Adapter + 1590 02bd 10Gb 2P 524SFP+ NIC 8430 ISP8324 1/10GbE Converged Network Controller (NIC VF) 8431 8300 Series 10GbE Converged Network Adapter (FCoE VF) 8432 ISP2432M-based 10GbE Converged Network Adapter (CNA) @@ -7443,7 +7953,18 @@ 1093 7802 PXIe-4302 1093 7803 PXIe-4303 1093 7805 PXIe-4305 + 1093 786f PXIe-4163 1093 788e PXIe-4304 + 1093 78f8 NI FlexRIO Module (KU035) + 1093 78f9 NI FlexRIO Module (KU040) + 1093 78fa NI FlexRIO Module (KU060) + 1093 78ff PXIe-4162 + 1093 7995 PXIe-7911R + 1093 7996 PXIe-7912R + 1093 7997 PXIe-7915R + 1093 79d3 NI FlexRIO PCIe Module (KU035) + 1093 79d4 NI FlexRIO PCIe Module (KU040) + 1093 79d5 NI FlexRIO PCIe Module (KU060) c801 PCI-GPIB c811 PCI-GPIB+ c821 PXI-GPIB @@ -7966,12 +8487,14 @@ 9056 PCI9056 32-bit 66MHz PCI <-> IOBus Bridge 10b5 2979 CellinkBlade 11 - CPCI board VoATM AAL1 10b5 3268 IXXAT iPC-I XC16/PCIe CAN Board + 10b5 3334 Cambridge Pixel HPx Radar Input Card 10b5 3352 Alpermann+Velte PCL PCIe HD: Timecode Reader Board 10b5 3353 Alpermann+Velte PCL PCIe D: Timecode Reader Board 10b5 3354 Alpermann+Velte PCL PCIe LV: Timecode Reader Board 10b5 3355 Alpermann+Velte PCL PCIe L: Timecode Reader Board 10b5 3415 Alpermann+Velte PCIe TS: Time Synchronisation Board 10b5 3493 Alpermann+Velte PCL PCIe 3G: Timecode Reader Board + 10b5 3565 Cambridge Pixel HPx Radar Output Card 1369 c001 LX6464ES 1369 c201 LX1616ES 14b4 d10a DekTec DTA-110T @@ -8876,6 +9399,7 @@ 0111 NV11 [GeForce2 MX200] 0112 NV11M [GeForce2 Go] 0113 NV11GL [Quadro2 MXR/EX/Go] + 1028 00e5 Quadro2 Go 0140 NV43 [GeForce 6600 GT] 1458 3125 GV-NX66T128D 1458 3126 GV-NX66T256DE @@ -8977,7 +9501,6 @@ 018b NV18GL [Quadro4 380 XGL] 018c NV18GL [Quadro NVS 50 PCI] 018d NV18M [GeForce4 448 Go] - 018f NV18 0190 G80 [GeForce 8800 GTS / 8800 GTX] 0191 G80 [GeForce 8800 GTX] 0192 G80 [GeForce 8800 GTS] @@ -8987,7 +9510,7 @@ 0197 G80GL [Tesla C870] 019d G80GL [Quadro FX 5600] 019e G80GL [Quadro FX 4600] - 01a0 nForce 220/420 NV11 [GeForce2 MX] + 01a0 nForce 220/420 NV1A [GeForce2 MX] 01a4 nForce CPU bridge 01ab nForce 420 Memory Controller (DDR) 01ac nForce 220/420 Memory Controller @@ -9040,7 +9563,7 @@ a0a0 03b9 UK79G-1394 motherboard 01ef nForce2 Memory Controller 5 a0a0 03b9 UK79G-1394 motherboard - 01f0 C17 [GeForce4 MX IGP] + 01f0 NV1F C17 [GeForce4 MX IGP] a0a0 03b5 UK79G-1394 motherboard 0200 NV20 [GeForce3] 1043 402f AGP-V8200 DDR @@ -9750,45 +10273,45 @@ 0638 G94GL [Quadro FX 1800] 063a G94GLM [Quadro FX 2700M] 063f G94 [GeForce 9600 GE] - 0640 G96 [GeForce 9500 GT] - 0641 G96 [GeForce 9400 GT] + 0640 G96C [GeForce 9500 GT] + 0641 G96C [GeForce 9400 GT] 1682 4009 PV-T94G-ZAFG 0642 G96 [D9M-10] 0643 G96 [GeForce 9500 GT] 0644 G96 [GeForce 9500 GS] 174b 9600 Geforce 9500GS 512M DDR2 V/D/HDMI - 0645 G96 [GeForce 9500 GS] - 0646 G96 [GeForce GT 120] - 0647 G96M [GeForce 9600M GT] - 0648 G96M [GeForce 9600M GS] - 0649 G96M [GeForce 9600M GT] + 0645 G96C [GeForce 9500 GS] + 0646 G96C [GeForce GT 120] + 0647 G96CM [GeForce 9600M GT] + 0648 G96CM [GeForce 9600M GS] + 0649 G96CM [GeForce 9600M GT] 1043 202d GeForce GT 220M 064a G96M [GeForce 9700M GT] 064b G96M [GeForce 9500M G] - 064c G96M [GeForce 9650M GT] - 064d G96 [GeForce 9600 GT] - 064e G96 [GeForce 9600 GT / 9800 GT] - 0651 G96M [GeForce G 110M] - 0652 G96M [GeForce GT 130M] + 064c G96CM [GeForce 9650M GT] + 064e G96C [GeForce 9600 GSO / 9800 GT] + 0651 G96CM [GeForce G 110M] + 0652 G96CM [GeForce GT 130M] 152d 0850 GeForce GT 240M LE - 0653 G96M [GeForce GT 120M] - 0654 G96M [GeForce GT 220M] + 0653 G96CM [GeForce GT 120M] + 0654 G96CM [GeForce GT 220M] 1043 14a2 GeForce GT 320M 1043 14d2 GeForce GT 320M - 0655 G96 [GeForce GT 120] - 0656 G96 [GeForce 9650 S] + 0655 G96 [GeForce GT 120 Mac Edition] + 0656 G96 [GeForce GT 120 Mac Edition] 0658 G96GL [Quadro FX 380] - 0659 G96GL [Quadro FX 580] + 0659 G96CGL [Quadro FX 580] 065a G96GLM [Quadro FX 1700M] - 065b G96 [GeForce 9400 GT] + 065b G96C [GeForce 9400 GT] 065c G96GLM [Quadro FX 770M] 065d G96 [GeForce 9500 GA / 9600 GT / GTS 250] - 065f G96 [GeForce G210] + 065f G96C [GeForce G210] 06c0 GF100 [GeForce GTX 480] 06c4 GF100 [GeForce GTX 465] 06ca GF100M [GeForce GTX 480M] 06cb GF100 [GeForce GTX 480] 06cd GF100 [GeForce GTX 470] + 06d0 GF100GL 06d1 GF100GL [Tesla C2050 / C2070] 10de 0771 Tesla C2050 10de 0772 Tesla C2070 @@ -10364,7 +10887,7 @@ 0e0f GK208 HDMI/DP Audio Controller 0e12 TegraK1 PCIe x4 Bridge 0e13 TegraK1 PCIe x1 Bridge - 0e1a GK110 HDMI Audio + 0e1a GK110 High Definition Audio Controller 0e1b GK107 HDMI Audio Controller 103c 197b ZBook 15 1043 8428 GTX650-DC-1GD5 @@ -10391,7 +10914,7 @@ 0fc0 GK107 [GeForce GT 640 OEM] 0fc1 GK107 [GeForce GT 640] 0fc2 GK107 [GeForce GT 630 OEM] - 0fc5 GK107 + 0fc5 GK107 [GeForce GT 1030] 0fc6 GK107 [GeForce GTX 650] 1043 8428 GTX650-DC-1GD5 0fc8 GK107 [GeForce GT 740] @@ -10482,7 +11005,7 @@ 1022 GK110GL [Tesla K20c] 1023 GK110BGL [Tesla K40m] 10de 097e 12GB Computational Accelerator - 1024 GK110BGL [Tesla K40c] + 1024 GK180GL [Tesla K40c] 1026 GK110GL [Tesla K20s] 1027 GK110BGL [Tesla K40st] 1028 GK110GL [Tesla K20m] @@ -10569,6 +11092,9 @@ 10f0 GP104 High Definition Audio Controller 10f1 GP106 High Definition Audio Controller 10f7 TU102 High Definition Audio Controller + 10f8 TU104 HD Audio Controller + 10f9 TU106 High Definition Audio Controller + 1043 8673 TURBO-RTX2070-8G 1140 GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] 1019 0799 GeForce 820M 1019 999f GeForce GT 720M @@ -10950,8 +11476,7 @@ 106b 010d iMac 13,2 11a7 GK104M [GeForce GTX 675MX] 11af GK104GLM [GRID IceCube] -# GRID K2 Quadro USM - 11b0 GK104GL [GRID K240Q\K260Q vGPU] + 11b0 GK104GL [GRID K240Q / K260Q vGPU] 10de 101a GRID K240Q 10de 101b GRID K260Q 11b1 GK104GL [GRID K2 Tesla USM] @@ -11186,12 +11711,21 @@ 17c2 GM200 [GeForce GTX TITAN X] 17c8 GM200 [GeForce GTX 980 Ti] 17f0 GM200GL [Quadro M6000] + 10de 1141 VCA 6000 17f1 GM200GL [Quadro M6000 24GB] 17fd GM200GL [Tesla M40] - 1ad6 TU102 USB 3.1 Controller - 1ad7 TU102 UCSI Controller + 1ad6 TU102 USB 3.1 Host Controller + 1ad7 TU102 USB Type-C UCSI Controller + 1ad8 TU104 USB 3.1 Host Controller + 1ad9 TU104 USB Type-C UCSI Controller + 1ada TU106 USB 3.1 Host Controller + 1043 8673 TURBO-RTX2070-8G + 1adb TU106 USB Type-C UCSI Controller + 1043 8673 TURBO-RTX2070-8G + 1aeb TU116 High Definition Audio Controller + 1aed TU116 [GeForce GTX 1650 SUPER] 1b00 GP102 [TITAN X] - 1b01 GP102 + 1b01 GP102 [GeForce GTX 1080 Ti 10GB] 1b02 GP102 [TITAN Xp] 1b04 GP102 1b06 GP102 [GeForce GTX 1080 Ti] @@ -11213,6 +11747,8 @@ 1462 11e9 GeForce GTX 1070 Max-Q 1558 9501 GeForce GTX 1070 Max-Q 1ba2 GP104M [GeForce GTX 1070 Mobile] + 1ba9 GP104M + 1baa GP104M 1bad GP104 [GeForce GTX 1070 Engineering Sample] 1bb0 GP104GL [Quadro P5000] 1bb1 GP104GL [Quadro P4000] @@ -11247,7 +11783,9 @@ 1c22 GP106M [GeForce GTX 1050 Mobile] 1c23 GP106M [GeForce GTX 1060 Mobile Rev. 2] 1414 0020 GTX 1060 Mobile + 1c2d GP106M 1c30 GP106GL [Quadro P2000] + 1c31 GP106GL [Quadro P2200] 1c35 GP106 1c60 GP106BM [GeForce GTX 1060 Mobile 6GB] 103c 8390 GeForce GTX 1060 Max-Q 6GB @@ -11256,11 +11794,15 @@ 1c70 GP106GL 1c81 GP107 [GeForce GTX 1050] 1c82 GP107 [GeForce GTX 1050 Ti] + 1043 8613 PH-GTX1050TI-4G + 1458 3763 GV-N105TOC-4GD 1c83 GP107 [GeForce GTX 1050 3GB] 1c8c GP107M [GeForce GTX 1050 Ti Mobile] 1c8d GP107M [GeForce GTX 1050 Mobile] 1c8e GP107M 1c8f GP107M [GeForce GTX 1050 Ti Max-Q] + 1c90 GP107M [GeForce MX150] + 1c91 GP107M [GeForce GTX 1050 3 GB Max-Q] 1c92 GP107M [GeForce GTX 1050 Mobile] 1ca7 GP107GL 1ca8 GP107GL @@ -11278,40 +11820,99 @@ 103c 842f P1000 [Zbook 17 G5 mobile workstation] 103c 8451 P1000 [Zbook Studio x360 G5 mobile workstation] 1cbc GP107GLM [Quadro P600 Mobile] + 1cbd GP107GLM [Quadro P620] 1ccc GP107BM [GeForce GTX 1050 Ti Mobile] 1ccd GP107BM [GeForce GTX 1050 Mobile] 1d01 GP108 [GeForce GT 1030] 1d10 GP108M [GeForce MX150] 17aa 225e ThinkPad T480 + 1d11 GP108M [GeForce MX230] 1d12 GP108M [GeForce MX150] 1d72 1701 Mi Notebook Pro [GeForce MX150] + 1d13 GP108M [GeForce MX250] 1d33 GP108GLM [Quadro P500 Mobile] + 1d34 GP108GLM [Quadro P520] + 1d52 GP108BM [GeForce MX250] 1d81 GV100 [TITAN V] 1db1 GV100GL [Tesla V100 SXM2 16GB] - 1db2 GV100 [Tesla V100-DGXS-16GB] + 1db2 GV100GL [Tesla V100 DGXS 16GB] 1db3 GV100GL [Tesla V100 FHHL 16GB] 1db4 GV100GL [Tesla V100 PCIe 16GB] 1db5 GV100GL [Tesla V100 SXM2 32GB] 1db6 GV100GL [Tesla V100 PCIe 32GB] 1db7 GV100GL [Tesla V100 DGXS 32GB] + 1db8 GV100GL [Tesla V100 SXM3 32GB] + 10de 131d Tesla V100-SXM3-32GB-H 1dba GV100GL [Quadro GV100] 10de 12eb TITAN V CEO Edition - 1e02 TU102 + 1df5 GV100GL [Tesla V100 SXM2 16GB] + 1df6 GV100GL [Tesla V100S PCIe 32GB] + 1e02 TU102 [TITAN RTX] 1e04 TU102 [GeForce RTX 2080 Ti] 1e07 TU102 [GeForce RTX 2080 Ti Rev. A] 1462 3715 RTX 2080 Ti GAMING X TRIO - 1e30 TU102GL [Quadro RTX 6000] + 1e2d TU102B + 1e2e TU102B + 1e30 TU102GL [Quadro RTX 6000/8000] + 10de 129e Quadro RTX 8000 + 10de 12ba Quadro RTX 6000 + 1e38 TU102GL 1e3c TU102GL 1e3d TU102GL + 1e3e TU102GL + 1e78 TU102GL [Quadro RTX 6000/8000] + 10de 13d8 Quadro RTX 8000 + 10de 13d9 Quadro RTX 6000 + 1e81 TU104 [GeForce RTX 2080 SUPER] 1e82 TU104 [GeForce RTX 2080] + 1e84 TU104 [GeForce RTX 2070 SUPER] 1e87 TU104 [GeForce RTX 2080 Rev. A] - 1eab TU104M [GeForce RTX 2080 Mobile] + 1e89 TU104 [GeForce RTX 2060] + 1e90 TU104M [GeForce RTX 2080 Mobile] + 1eab TU104M 1eae TU104M 1eb0 TU104GL [Quadro RTX 5000] 1eb1 TU104GL [Quadro RTX 4000] + 1eb5 TU104GLM [Quadro RTX 5000 Mobile / Max-Q] + 1eb6 TU104GLM [Quadro RTX 4000 Mobile / Max-Q] 1eb8 TU104GL [Tesla T4] + 1eb9 TU104GL + 1ebe TU104GL + 1ec2 TU104 [GeForce RTX 2070 SUPER] + 1ec7 TU104 [GeForce RTX 2070 SUPER] + 1ed0 TU104BM [GeForce RTX 2080 Mobile] 1f02 TU106 [GeForce RTX 2070] + 1043 8673 TURBO RTX 2070 + 1f04 TU106 + 1f06 TU106 [GeForce RTX 2060 SUPER] 1f07 TU106 [GeForce RTX 2070 Rev. A] + 1f08 TU106 [GeForce RTX 2060 Rev. A] + 1f10 TU106M [GeForce RTX 2070 Mobile] + 1f11 TU106M [GeForce RTX 2060 Mobile] + 1f2e TU106M + 1f36 TU106GLM [Quadro RTX 3000 Mobile / Max-Q] + 1f42 TU106 [GeForce RTX 2060 SUPER] + 1f47 TU106 [GeForce RTX 2060 SUPER] + 1f50 TU106BM [GeForce RTX 2070 Mobile] + 1f51 TU106BM [GeForce RTX 2060 Mobile] + 1f81 TU117 + 1f82 TU117 [GeForce GTX 1650] + 1f91 TU117M [GeForce GTX 1650 Mobile / Max-Q] + 1f92 TU117M [GeForce GTX 1650 Mobile] + 1f96 TU117M [GeForce GTX 1650 Mobile / Max-Q] + 1fae TU117GL + 1fb8 TU117GLM [Quadro T2000 Mobile / Max-Q] + 1fb9 TU117GLM [Quadro T1000 Mobile] + 1fbf TU117GL + 2182 TU116 [GeForce GTX 1660 Ti] + 2183 TU116 + 2184 TU116 [GeForce GTX 1660] + 2187 TU116 [GeForce GTX 1650 SUPER] + 2191 TU116M [GeForce GTX 1660 Ti Mobile] + 21ae TU116GL + 21bf TU116GL + 21c4 TU116 [GeForce GTX 1660 SUPER] + 21d1 TU116BM [GeForce GTX 1660 Ti Mobile] 10df Emulex Corporation 0720 OneConnect NIC (Skyhawk) 103c 1934 FlexFabric 20Gb 2-port 650M Adapter @@ -11335,8 +11936,12 @@ e100 Proteus-X: LightPulse IOV Fibre Channel Host Adapter e131 LightPulse 8Gb/s PCIe Shared I/O Fibre Channel Adapter e180 Proteus-X: LightPulse IOV Fibre Channel Host Adapter - e200 LightPulse LPe16002 - 1014 03f1 PCIe2 16 Gb 2-port Fibre Channel Adapter (FC EL5B; CCIN 577F) + e200 LPe15000/LPe16000 Series 8Gb/16Gb Fibre Channel Adapter + 1014 03f1 PCIe2 2-Port 16Gb Fibre Channel Adapter for POWER (FC EL5B; CCIN 577F) + 1014 04e3 PCIe3 4-Port 10GbE SR Adapter for POWER (FC EN15/EN16; CCIN 2CE3) + 1014 04e4 PCIe3 4-Port 10GbE SFP+ Adapter for POWER (FC EN18; CCIN 2CE4) + 10df e280 LPe16002B-M6 2-Port 16Gb Fibre Channel Adapter + 10df e281 LPe16000B-M6 1-Port 16Gb Fibre Channel Adapter 10df e282 Flex System FC5054 4-port 16Gb FC Adapter e208 LightPulse 16Gb Fibre Channel Host Adapter (Lancer-VF) e220 OneConnect NIC (Lancer) @@ -11345,14 +11950,29 @@ e240 OneConnect iSCSI Initiator (Lancer) e260 OneConnect FCoE Initiator (Lancer) e268 OneConnect 10Gb FCoE Converged Network Adapter (Lancer-VF) - e300 Lancer Gen6: LPe32000 Fibre Channel Host Adapter - 10df e310 Lancer Gen6: LPe31000 Fibre Channel Host Adapter - 10df e311 Lancer Gen6: LPe31000 Fibre Channel Host Adapter - 10df e312 Lancer Gen6: LPe31000 Fibre Channel Host Adapter - 10df e322 Lancer Gen6: LPe31000 Fibre Channel Host Adapter - 10df e323 Lancer Gen6: LPe31000 Fibre Channel Host Adapter - 10df e325 Lancer Gen6: LPe31000 Fibre Channel Host Adapter - e333 Lancer Gen6: LPe32000 Fibre Channel Host Adapter + e300 LPe31000/LPe32000 Series 16Gb/32Gb Fibre Channel Adapter + 1014 0614 PCIe3 4-Port 16Gb Fibre Channel Adapter for POWER (FC EN1C/EN1D; CCIN 578E) + 1014 0615 PCIe3 2-Port 32Gb Fibre Channel Adapter for POWER (FC EN1A/EN1B; CCIN 578F) + 10df e300 LPe32002-M2 2-Port 32Gb Fibre Channel Adapter + 10df e301 LPe32000-M2 1-Port 32Gb Fibre Channel Adapter + 10df e310 LPe31002-M6 2-Port 16Gb Fibre Channel Adapter + 10df e311 LPe31000-M6 1-Port 16Gb Fibre Channel Adapter + 10df e312 LPe31004-M6 4-Port 16Gb Fibre Channel Adapter + 10df e320 LPe32002-M2-D 2-Port 32Gb Fibre Channel Adapter + 10df e321 LPe32000-M2-D 1-Port 32Gb Fibre Channel Adapter + 10df e322 LPe31002-M6-D 2-Port 16Gb Fibre Channel Adapter + 10df e323 LPe31000-M6-D 1-Port 16Gb Fibre Channel Adapter + 10df e324 LPm32002-D 2-Port 32Gb Fibre Channel Mezz Card + 10df e325 LPm31002-D 2-Port 16Gb Fibre Channel Mezz Card + 10df e330 LPe32002-M2-L 2-Port 32Gb PCIe Fibre Channel Adapter + 10df e331 LPe32000-M2-L 1-Port 32Gb PCIe Fibre Channel Adapter + 10df e332 LPe31002-M6-L 2-Port 16Gb PCIe Fibre Channel Adapter + 10df e333 LPe31000-M6-L 1-Port 16Gb PCIe Fibre Channel Adapter + 1590 0201 StoreFabric SN1600E 1-Port 32Gb Fibre Channel Adapter + 1590 0202 StoreFabric SN1600E 2-Port 32Gb Fibre Channel Adapter + 1590 0213 StoreFabric SN1200E 1-Port 16Gb Fibre Channel Adapter + 1590 0214 StoreFabric SN1200E 2-Port 16Gb Fibre Channel Adapter + 1590 022e Synergy 5330C 2-Port 32Gb Fibre Channel Mezz Card f011 Saturn: LightPulse Fibre Channel Host Adapter f015 Saturn: LightPulse Fibre Channel Host Adapter f085 LP850 Fibre Channel Host Adapter @@ -11366,16 +11986,27 @@ f0e1 Zephyr LightPulse Fibre Channel Host Adapter f0e5 Zephyr LightPulse Fibre Channel Host Adapter f0f5 Neptune LightPulse Fibre Channel Host Adapter - f100 Saturn-X: LightPulse Fibre Channel Host Adapter + f100 LPe12000 Series 8Gb Fibre Channel Adapter 1014 038a 8Gb PCI Express Dual Port FC Adapter for POWER 103c 3282 8Gb Dual-port PCI-e FC HBA + 10df f140 LPe12000-M8-L 1-Port 8Gb PCIe Fibre Channel Adapter + 10df f141 LPe12002-M8-L 2-Port 8Gb PCIe Fibre Channel Adapter f111 Saturn-X LightPulse Fibre Channel Host Adapter f112 Saturn-X LightPulse Fibre Channel Host Adapter f180 LPSe12002 EmulexSecure Fibre Channel Adapter - f400 LPe36000 Fibre Channel Host Adapter [Prism] - 10df f401 LPe35000 Fibre Channel Host Adapter [Prism] - 10df f402 LPe35000 Fibre Channel Host Adapter [Prism] + f400 LPe35000/LPe36000 Series 32Gb/64Gb Fibre Channel Adapter + 10df f401 LPe35000-M2 1-Port 32Gb Fibre Channel Adapter + 10df f402 LPe35002-M2 2-Port 32Gb Fibre Channel Adapter + 10df f403 LPe36000-M64 1-Port 64Gb Fibre Channel Adapter + 10df f404 LPe36002-M64 2-Port 64Gb Fibre Channel Adapter + 10df f405 LPe35004-M2 4-Port 32Gb Fibre Channel Adapter + 10df f406 LPe35004-X6 4-Port Fibre Channel Adapter 10df f410 LPe35002-M2-D 2-Port 32Gb Fibre Channel Adapter + 10df f411 LPe35000-M2-D 1-Port 32Gb Fibre Channel Adapter + 10df f418 LPe35000-M2-L 1-Port 32Gb PCIe Fibre Channel Adapter + 10df f419 LPe35002-M2-L 2-Port 32Gb PCIe Fibre Channel Adapter + 1590 02d5 StoreFabric SN1610E 1-Port 32Gb Fibre Channel Adapter + 1590 02d6 StoreFabric SN1610E 2-Port 32Gb Fibre Channel Adapter f700 LP7000 Fibre Channel Host Adapter f701 LP7000 Fibre Channel Host Adapter Alternate ID (JX1:2-3, JX2:1-2) f800 LP8000 Fibre Channel Host Adapter @@ -11494,6 +12125,7 @@ 103c 1985 Pavilion 17-e163sg Notebook PC 17aa 3832 Yoga 520 522a RTS522A PCI Express Card Reader + 103c 8079 EliteBook 840 G3 5249 RTS5249 PCI Express Card Reader 103c 1909 ZBook 15 524a RTS524A PCI Express Card Reader @@ -11502,6 +12134,7 @@ 1028 06dc Latitude E7470 1028 06e4 XPS 15 9550 17aa 224f ThinkPad X1 Carbon 5th Gen + 5260 RTS5260 PCI Express Card Reader 5286 RTS5286 PCI Express Card Reader 5287 RTL8411B PCI Express Card Reader 5288 RTS5288 PCI Express Card Reader @@ -11514,6 +12147,7 @@ 1186 0300 DE-528 1259 2400 AT-2400 1af4 1100 QEMU Virtual Machine + 8125 RTL8125 2.5GbE Controller 8129 RTL-8129 10ec 8129 RT8129 Fast Ethernet Adapter 11ec 8129 RTL8111/8168 PCIe Gigabit Ethernet (misconfigured) @@ -11588,10 +12222,13 @@ 1028 0283 Vostro 220 1028 04b2 Vostro 3350 1028 04da Vostro 3750 + 1028 06f2 Latitude 3470 1028 06f3 Latitude 3570 103c 1611 Pavilion DM1Z-3000 103c 1950 ProBook 450/455 103c 2a6f Asus IPIBL-LB Motherboard + 103c 8615 Pavilion Laptop 15-cw1xxx + 1043 11f5 Notebook motherboard (one of many models) 1043 16d5 U6V/U31J laptop 1043 81aa P5B 1043 82c6 M3A78 Series Motherboard @@ -11607,6 +12244,7 @@ 1462 368c K9AG Neo2 1462 4180 Wind PC MS-7418 1462 7522 X58 Pro-E + 1462 7c37 X570-A PRO motherboard 1775 11cc CC11/CL11 1849 8168 Motherboard (one of many) 7470 3468 TG-3468 Gigabit PCI Express Network Adapter @@ -11659,6 +12297,7 @@ b723 RTL8723BE PCIe Wireless Network Adapter 10ec 8739 Dell Wireless 1801 b822 RTL8822BE 802.11a/b/g/n/ac WiFi adapter + 103c 831b Realtek RTL8822BE 802.11ac 2 × 2 Wi-Fi + Bluetooth 4.2 Combo Adapter (MU-MIMO supported) c821 RTL8821CE 802.11ac PCIe Wireless Network Adapter d723 RTL8723DE 802.11b/g/n PCIe Adapter 10ed Ascii Corporation @@ -11690,6 +12329,7 @@ ebf0 SED Systems Modulator/Demodulator ebf1 SED Systems Audio Interface Card ebf2 SED Systems Common PCI Interface + ebf3 SED Systems PCIe-AXI Bridge 10ef Racore Computer Products, Inc. 8154 M815x Token Ring Adapter 10f0 Peritek Corporation @@ -12800,6 +13440,7 @@ 112f Dalsa Inc. 0000 MVC IC-PCI 0001 MVC IM-PCI Video frame grabber/processor + 0004 PCDig Digital Image Capture 0008 PC-CamLink PCI framegrabber 1130 Computervision 1131 Philips Semiconductors @@ -13180,6 +13821,15 @@ 1137 012e VIC 1227 PCIe Ethernet NIC 1137 0137 VIC 1380 Mezzanine Ethernet NIC 1137 014d VIC 1385 PCIe Ethernet NIC + 1137 015d VIC 1387 MLOM Ethernet NIC + 1137 0215 VIC 1440 Mezzanine Ethernet NIC + 1137 0216 VIC 1480 MLOM Ethernet NIC + 1137 0217 VIC 1455 PCIe Ethernet NIC + 1137 0218 VIC 1457 MLOM Ethernet NIC + 1137 0219 VIC 1485 PCIe Ethernet NIC + 1137 021a VIC 1487 MLOM Ethernet NIC + 1137 024a VIC 1495 PCIe Ethernet NIC + 1137 024b VIC 1497 MLOM Ethernet NIC 0044 VIC Ethernet NIC Dynamic 1137 0047 VIC P81E PCIe Ethernet NIC Dynamic 1137 0048 VIC M81KR Mezzanine Ethernet NIC Dynamic @@ -13597,11 +14247,20 @@ 1177 Silicon Engineering 1178 Alfa, Inc. afa1 Fast Ethernet Adapter -1179 Toshiba America Info Systems +1179 Toshiba Corporation 0102 Extended IDE Controller 0103 EX-IDE Type-B 010f NVMe Controller 0110 NVMe SSD Controller Cx5 + 1028 1ffb Express Flash NVMe 960G (RI) U.2 (CD5) + 1028 1ffc Express Flash NVMe 1.92T (RI) U.2 (CD5) + 1028 1ffd Express Flash NVMe 3.84T (RI) U.2 (CD5) + 1028 1ffe Express Flash NVMe 7.68T (RI) U.2 (CD5) + 1179 0001 KIOXIA CM5-R series SSD + 1179 0021 KIOXIA CD5 series SSD + 1d49 4039 Thinksystem U.2 CM5 NVMe SSD + 1d49 403a Thinksystem AIC CM5 NVMe SSD + 0113 BG3 NVMe SSD Controller 0115 XG4 NVMe SSD Controller 0404 DVD Decoder card 0406 Tecra Video Capture device @@ -13738,6 +14397,7 @@ 103c 30cf Pavilion dv95xx/96xx/97xx/98xx series 1043 1237 A6J-Q008 1043 1967 V6800V + 104d 9035 VAIO VGN-FW11ZRU 144d c018 X20 IV 17aa 20ca ThinkPad T61/T400 0811 R5C811 @@ -14166,6 +14826,7 @@ 7820 MV78200 [Discovery Innovation] ARM SoC 7823 MV78230 [Armada XP] ARM SoC 7846 88F6820 [Armada 385] ARM SoC + d40f Bobcat3 Ethernet Switch f003 GT-64010 Primary Image Piranha Image Generator 11ac Canon Information Systems Research Aust. 11ad Lite-On Communications Inc @@ -14340,7 +15001,9 @@ 103c 2a6f Asus IPIBL-LB Motherboard 103c 2a9e Pavilion p6310f 1043 8294 LSI FW322/323 IEEE 1394a FireWire Controller + 11bd 000e LSI FW323 8086 524c D865PERL mainboard + 9005 0033 Adaptec AFW-2100 (HP) 2102900-R dead 0800 FireWire Host Bus Adapter 5901 FW643 [TrueFire] PCIe 1394b Controller 11c1 5900 FW643 [TrueFire] PCIe 1394b Controller @@ -14494,7 +15157,7 @@ 11fb Datel Inc 11fc Silicon Magic 11fd High Street Consultants -11fe Comtrol Corporation +11fe Pepperl+Fuchs Comtrol, Inc. 0001 RocketPort PCI 32-port w/external I/F 0002 RocketPort PCI 8-port w/external I/F 0003 RocketPort PCI 16-port w/external I/F @@ -14737,7 +15400,7 @@ 000e PM/PPC 1224 Interactive Images 1225 Power I/O, Inc. -1227 Tech-Source +1227 EIZO Rugged Solutions 0006 Raptor GFX 8P 0023 Raptor GFX [1100T] 0045 Raptor 4000-L [Linux version] @@ -15326,7 +15989,7 @@ 12b4 FutureTel Inc 12b5 Granite Systems Inc. 12b6 Natural Microsystems -12b7 Cognex Modular Vision Systems Div. - Acumen Inc. +12b7 Cognex Corporation 12b8 Korg # Nee US Robotics 12b9 3Com Corp, Modem Division @@ -15459,8 +16122,11 @@ 1000 BSP15 12d6 Analogic Corp 12d7 Biotronic SRL +# acquired by Diodes Inc. 12d8 Pericom Semiconductor 01a7 7C21P100 2-port PCI-X to PCI-X Bridge + 2304 PI7C9X2G304 EL/SL PCIe2 3-Port/4-Lane Packet Switch + 2404 PI7C9X2G404 EL/SL PCIe2 4-Port/4-Lane Packet Switch 2608 PI7C9X2G608GP PCIe2 6-Port/8-Lane Packet Switch 400a PI7C9X442SL PCI Express Bridge Port 400e PI7C9X442SL USB OHCI Controller @@ -16290,6 +16956,7 @@ 1043 8428 Virtuoso 100 (Xonar Xense) 1043 8467 CMI8786 (Xonar DG) 1043 8521 CMI8786 (Xonar DGX) + 1043 8522 Xonar DSX 1043 85f4 Virtuoso 100 (Xonar Essence STX II) 13f6 8782 PCI 2.0 HD Audio 13f6 ffff CMI8787-HG2PCI @@ -16321,16 +16988,19 @@ 1612 0004 PCI-1612 4-port RS-232/422/485 1603 PCI-1603 2-port isolated RS-232/current loop 1604 PCI-1604 2-port RS-232 + 1680 PCI-1680 Rev.A1 2-port CAN-bus with isolation protection 16ff PCI-16xx series PCI multiport serial board (function 1: RX/TX steering CPLD) 1601 0000 PCI-1601 2-port unisolated RS-422/485 PCI communications card 1602 0000 PCI-1602 2-port isolated RS-422/485 1612 0000 PCI-1612 4-port RS-232/422/485 1711 PCI-1711 16-channel data acquisition card 12-bit, 100kS/s + 1713 PCI-1713 32-channel isolated analog input card 1733 PCI-1733 32-channel isolated digital input card 1734 PCI-1734 32-channel isolated digital output card 1752 PCI-1752 64-channel Isolated Digital Output Card 1754 PCI-1754 64-channel Isolated Digital Input Card 1756 PCI-1756 64-ch Isolated Digital I/O PCI Card + a004 PCI-1612 4-port RS-232/422/485 # FPGA bridge to two SJA1000 c302 MIOe-3680 2-Port CAN-Bus MIOe Module with Isolation Protection 13ff Silicon Spice Inc @@ -17308,7 +17978,8 @@ a800 XP941 PCIe SSD a802 NVMe SSD Controller SM951/PM951 a804 NVMe SSD Controller SM961/PM961 - a808 NVMe SSD Controller SM981/PM981 + a808 NVMe SSD Controller SM981/PM981/PM983 + 1d49 403b Thinksystem U.2 PM983 NVMe SSD a820 NVMe SSD Controller 171X 1028 1f95 Express Flash NVMe XS1715 SSD 400GB 1028 1f96 Express Flash NVMe XS1715 SSD 800GB @@ -17568,6 +18239,9 @@ e010 VScom 100HV2 1 port serial adaptor e020 VScom 200HV2 2 port serial adaptor 14d3 CIRTECH (UK) Ltd + 0002 DTL-T14000 Rev. 1 [PS2 TOOL CD/DVD Emulator] + 0003 DTL-T14000 Rev. 2 [PS2 TOOL CD/DVD Emulator] + 0004 DTL-T14000 Rev. 3 [PS2 TOOL CD/DVD Emulator] 14d4 Panacom Technology Corp 14d5 Nitsuko Corporation 14d6 Accusys Inc @@ -17793,6 +18467,14 @@ 10cf 1279 LifeBook E8010D 165f NetXtreme BCM5720 2-port Gigabit Ethernet PCIe 1028 04f7 PowerEdge R320 server + 1028 08fd PowerEdge R6515/R7515 LOM + 1028 08ff PowerEdge Rx5xx LOM Board + 1028 0900 PowerEdge C6525 LOM + 103c 1786 NC332T Adapter + 103c 193d NC332i Adapter + 103c 2133 NC332i Adapter + 103c 22e8 NC332i Adapter + 103c 22eb NC332i Adapter 1662 NetXtreme II BCM57712 10 Gigabit Ethernet 1663 NetXtreme II BCM57712 10 Gigabit Ethernet Multi Function 1665 NetXtreme BCM5717 Gigabit Ethernet PCIe @@ -17813,6 +18495,7 @@ 1028 0179 Optiplex GX280 1028 0182 Latitude D610 1028 0187 Precision M70 + 1028 01a3 Latitude X1 1028 01a8 Precision 380 1028 01ad OptiPlex GX620 103c 3006 DC7100 SFF(DX878AV) @@ -18017,14 +18700,19 @@ 16d4 BCM57402 NetXtreme-E Ethernet Partition 16d5 BCM57407 NetXtreme-E 10GBase-T Ethernet Controller 16d6 BCM57412 NetXtreme-E 10Gb RDMA Ethernet Controller + 14e4 4120 NetXtreme E-Series Advanced Dual-port 10Gb SFP+ Ethernet Network Daughter Card + 152d 8b20 BCM57412 NetXtreme-E 10Gb RDMA Ethernet Controller + 152d 8b22 BCM57412 NetXtreme-E 25Gb RDMA Ethernet Controller 16d7 BCM57414 NetXtreme-E 10Gb/25Gb RDMA Ethernet Controller 14e4 1202 BCM957412M4122C OCP 1x25G Type1 wRoCE 14e4 1402 BCM957414A4142CC 10Gb/25Gb Ethernet PCIe 14e4 1404 BCM957414M4142C OCP 2x25G Type1 wRoCE + 14e4 4140 NetXtreme E-Series Advanced Dual-port 25Gb SFP28 Network Daughter Card 1590 020e Ethernet 25Gb 2-port 631SFP28 Adapter 1590 0211 Ethernet 25Gb 2-port 631FLR-SFP28 Adapter 16d8 BCM57416 NetXtreme-E Dual-Media 10G RDMA Ethernet Controller 1028 1feb NetXtreme-E 10Gb SFP+ Adapter + 14e4 4163 BCM957416M4163C OCP 2x10GBT Type1 wRoCE 1590 020c Ethernet 10Gb 2-port 535T Adapter 1590 0212 Ethernet 10Gb 2-port 535FLR-T Adapter 16d9 BCM57417 NetXtreme-E 10GBASE-T RDMA Ethernet Controller @@ -18072,6 +18760,11 @@ 1028 0209 XPS M1330 103c 30c0 Compaq 6710b 17aa 3a23 IdeaPad S10e + 1750 BCM57508 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb/200Gb Ethernet + 1751 BCM57504 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb/200Gb Ethernet + 1752 BCM57502 NetXtreme-E 10Gb/25Gb/40Gb/50Gb Ethernet + 1806 BCM5750X NetXtreme-E Ethernet Virtual Function + 1807 BCM5750X NetXtreme-E RDMA Virtual Function 3352 BCM3352 3360 BCM3360 4210 BCM4210 iLine10 HomePNA 2.0 @@ -18256,6 +18949,7 @@ 43bc BCM43602 802.11ac Wireless LAN SoC 43d3 BCM43567 802.11ac Wireless Network Adapter 43d9 BCM43570 802.11ac Wireless Network Adapter + 43dc BCM4355 802.11ac Wireless LAN SoC 43df BCM4354 802.11ac Wireless LAN SoC 43e9 BCM4358 802.11ac Wireless LAN SoC 43ec BCM4356 802.11ac Wireless Network Adapter @@ -18272,6 +18966,9 @@ 4412 BCM4412 10/100BaseT 4430 BCM44xx CardBus iLine32 HomePNA 2.0 4432 BCM4432 CardBus 10/100BaseT + 4464 BCM4364 802.11ac Wireless Network Adapter +# brcmfmac reports it as BCM4377/4 but macOS drivers call it BCM4377b + 4488 BCM4377b Wireless Network Adapter 4610 BCM4610 Sentry5 PCI to SB Bridge 4611 BCM4610 Sentry5 iLine32 HomePNA 1.0 4612 BCM4610 Sentry5 V.90 56k Modem @@ -18318,6 +19015,7 @@ 5841 BCM5841 Crypto Accelerator 5850 BCM5850 Crypto Accelerator 5e87 Valkyrie offload engine + 5e88 Viper Offload Engine 8602 BCM7400/BCM7405 Serial ATA Controller 9026 CN99xx [ThunderX2] Integrated USB 3.0 xHCI Host Controller 9027 CN99xx [ThunderX2] Integrated AHCI/SATA 3 Host Controller @@ -18332,16 +19030,24 @@ b376 BCM56376 Switch ASIC b377 BCM56377 Switch ASIC b379 Broadcom BCM56379 Switch ASIC + b470 BCM56470 SWITCH ASIC + b471 BCM56471 SWITCH ASIC + b472 BCM56472 SWITCH ASIC b800 BCM56800 StrataXGS 10GE Switch Controller b842 BCM56842 Trident 10GE Switch Controller # Trident2 b850 Broadcom BCM56850 Switch ASIC + b880 BCM56880 Switch ASIC # Tomahawk b960 Broadcom BCM56960 Switch ASIC +# Tomahawk4 + b990 BCM56990 Switch ASIC d802 BCM58802 Stingray 50Gb Ethernet SoC 14e4 8021 Stingray Dual-Port 25Gb Ethernet PCIe SmartNIC w16GB DRAM (Part No BCM958802A8046C) + 14e4 8023 PS410T-H04 NetXtreme-S 4x10G 10GBaseT PCIe SmartNIC 14e4 8024 Stingray Dual-Port 25Gb Ethernet PCIe SmartNIC w4GB DRAM (Part No BCM958802A8044C) 14e4 8028 Stingray Dual-Port 25Gb Ethernet PCIe SmartNIC w8GB DRAM (Part No BCM958802A8048C) + 1bb0 0021 HPE SimpliVity Accelerator d804 BCM58804 Stingray 100Gb Ethernet SoC 14e5 Pixelfusion Ltd 14e6 SHINING Technology Inc @@ -18628,6 +19334,7 @@ 0070 2259 WinTV HVR-1250 0070 6a18 WinTV-quadHD 0070 c108 WinTV-HVR-4400-HD model 1278 + 1461 3100 CE310B SD PCIe Video Capture Card 5654 2389 GoTView X5 DVD Hybrid PCI-E 5654 2390 GoTView X5 3D HYBRID PCI-E 14f2 MOBILITY Electronics @@ -18817,6 +19524,9 @@ 9278 10 Volt Delta Sigma Converter Card 9287 Analog Output Card 9290 FPGA Card + 9300 Universal Exhaust Gas Oxygen Sensor Simulator + 9310 Digital Programmable Resistor + 9350 Analog Input Card 1543 SILICON Laboratories 3052 Intel 537 [Winmodem] 4c22 Si3036 MC'97 DAA @@ -18843,6 +19553,7 @@ 110f PCI Express Core Reference Design Virtual Function 1110 XpressRich Reference Design 1113 XpressSwitch + be00 PCI Express Bridge 1557 MEDIASTAR Co Ltd 1558 CLEVO/KAPOK Computer 1559 SI LOGIC Ltd @@ -19000,12 +19711,27 @@ 020f MT28908A0 Family [ConnectX-6 Flash Recovery] 0210 MT28908A0 Family [ConnectX-6 Secure Flash Recovery] 0211 MT416842 Family [BlueField SoC Flash Recovery] + 0212 MT2892 Family [ConnectX-6 Dx Flash Recovery] + 0213 MT2892 Family [ConnectX-6 Dx Secure Flash Recovery] + 0214 MT42822 Family [BlueField-2 SoC Flash Recovery] + 0215 MT42822 Family [BlueField-2 Secure Flash Recovery] + 0216 MT2894 Family [ConnectX-6 Lx Flash Recovery] + 0217 MT2894 Family [ConnectX-6 Lx Secure Flash Recovery] 024e MT53100 [Spectrum-2, Flash recovery mode] 024f MT53100 [Spectrum-2, Secure Flash recovery mode] + 0250 Spectrum-3, Flash recovery mode + 0251 Spectrum-3, Secure Flash recovery mode + 0252 Amos chiplet + 0254 Spectrum-4, Flash recovery mode + 0255 Spectrum-4, Secure Flash recovery mode + 0256 Ofek chiplet + 0257 Quantum-2 in Flash Recovery Mode 0262 MT27710 [ConnectX-4 Lx Programmable] EN 0263 MT27710 [ConnectX-4 Lx Programmable Virtual Function] EN 0264 Innova-2 Flex Burn image 0281 NPS-600 Flash Recovery + 0538 MT2910 Family [ConnectX-7 Flash Recovery] + 0539 MT2910 Family [ConnectX-7 Secure Flash Recovery] 1002 MT25400 Family [ConnectX-2 Virtual Function] 1003 MT27500 Family [ConnectX-3] 1014 04b5 PCIe3 40GbE RoCE Converged Host Bus Adapter for Power @@ -19060,6 +19786,7 @@ 15b3 0003 Mellanox Technologies ConnectX-4 Stand-up single-port 40GbE MCX413A-BCAT 15b3 0005 Mellanox Technologies ConnectX-4 Stand-up single-port 40GbE MCX415A-BCAT 15b3 0006 MCX416A-BCAT, ConnectX-4 EN, 40/56GbE 2P, PCIe3.0 x16 + 15b3 0007 ConnectX-4 EN network interface card, 40/56GbE dual-port QSFP28, PCIe3.0 x16, tall bracket 15b3 0008 ConnectX-4 Stand-up dual-port 100GbE MCX416A-CCAT 15b3 0033 ConnectX-4 VPI IB EDR/100 GbE Single Port QSFP28 Adapter 15b3 0034 ConnectX-4 VPI IB EDR/100 GbE Dual Port QSFP28 Adapter @@ -19076,18 +19803,25 @@ 193d 100a 620F-B 1016 MT27710 Family [ConnectX-4 Lx Virtual Function] 1017 MT27800 Family [ConnectX-5] + 15b3 0006 ConnectX®-5 EN network interface card, 100GbE single-port QSFP28, PCIe3.0 x16, tall bracket; MCX515A-CCAT + 15b3 0020 ConnectX®-5 EN network interface card, 10/25GbE dual-port SFP28, PCIe3.0 x8, tall bracket ; MCX512A-ACAT + 15b3 0068 ConnectX®-5 EN network interface card for OCP2.0, Type 1, with host management, 25GbE dual-port SFP28, PCIe3.0 x8, no bracket Halogen free ; MCX542B-ACAN 1018 MT27800 Family [ConnectX-5 Virtual Function] 1019 MT28800 Family [ConnectX-5 Ex] + 15b3 0008 ConnectX-5 Ex EN network interface card, 100GbE dual-port QSFP28, PCIe4.0 x16, tall bracket; MCX516A-CDAT 101a MT28800 Family [ConnectX-5 Ex Virtual Function] 101b MT28908 Family [ConnectX-6] 101c MT28908 Family [ConnectX-6 Virtual Function] - 101d MT28841 - 101e MT28850 - 101f MT28851 + 101d MT2892 Family [ConnectX-6 Dx] + 101e ConnectX Family mlx5Gen Virtual Function + 101f MT2894 Family [ConnectX-6 Lx] 1020 MT28860 - 1021 MT28861 + 1021 MT2910 Family [ConnectX-7] 1974 MT28800 Family [ConnectX-5 PCIe Bridge] 1975 MT416842 Family [BlueField SoC PCIe Bridge] + 1976 MT28908 Family [ConnectX-6 PCIe Bridge] + 1977 MT2892 Family [ConnectX-6 Dx PCIe Bridge] + 1978 MT42822 Family [BlueField-2 SoC PCIe Bridge] 4117 MT27712A0-FDCF-AE 1bd4 0039 SN10XMP2P25 1bd4 004d SN10XMP2P25,YZPC-01191-101 @@ -19097,6 +19831,7 @@ 5a46 MT23108 PCI Bridge 5e8c MT24204 [InfiniHost III Lx HCA] 5e8d MT25204 [InfiniHost III Lx HCA Flash Recovery] + 6001 NVMe SNAP Controller 6274 MT25204 [InfiniHost III Lx HCA] 6278 MT25208 InfiniHost III Ex (Tavor compatibility mode) 6279 MT25208 [InfiniHost III Ex HCA Flash Recovery] @@ -19137,6 +19872,11 @@ a2d1 MT416842 BlueField SoC Crypto disabled a2d2 MT416842 BlueField integrated ConnectX-5 network controller a2d3 MT416842 BlueField multicore SoC family VF + a2d4 MT42822 BlueField-2 SoC Crypto enabled + a2d5 MT42822 BlueField-2 SoC Crypto disabled + a2d6 MT42822 BlueField-2 integrated ConnectX-6 Dx network controller + c2d2 MT416842 BlueField SoC management interfac + c2d3 MT42822 BlueField-2 SoC Management Interface # SwitchX-2, 40GbE switch c738 MT51136 c739 MT51136 GW @@ -19145,9 +19885,12 @@ caf1 ConnectX-4 CAPI Function # Spectrum, 100GbE Switch cb84 MT52100 - cf08 MT53236 + cf08 Switch-IB2 cf6c MT53100 [Spectrum-2] + cf70 Spectrum-3 + cf80 Spectrum-4 d2f0 Quantum HDR (200Gbps) switch + d2f2 Quantum-2 NDR (400Gbps) switch 15b4 CCI/TRIAD 15b5 Cimetrics Inc 15b6 Texas Memory Systems Inc @@ -19171,6 +19914,7 @@ 2001 Skyhawk Series NVME SSD 5001 WD Black NVMe SSD 5002 WD Black 2018/PC SN720 NVMe SSD + 5003 WD Black 2018/PC SN520 NVMe SSD 15b8 ADDI-DATA GmbH 1001 APCI1516 SP controller (16 digi outputs) 1003 APCI1032 SP controller (32 digi inputs w/ opto coupler) @@ -19656,6 +20400,7 @@ 1a32 0303 EM303 802.11bgn Wireless Mini PCIe Card [AR9281] 1a32 0306 EM306 802.11bgn Wireless Half-size Mini PCIe Card [AR9283] 1a3b 1067 AW-NE771 802.11bgn Wireless Mini PCIe Card [AR9281] + 1a3b 1071 AW-NE772 802.11abgn Wireless Mini PCIe Card [AR9280] 1a3b 1081 AW-NE773 802.11abgn Wireless Half-size Mini PCIe Card [AR9280] 002b AR9285 Wireless Network Adapter (PCI-Express) 1028 0204 Wireless 1502 802.11bgn Half-size Mini PCIe Card @@ -19740,6 +20485,9 @@ 16b8 Sonnet Technologies, Inc. 16be Creatix Polymedia GmbH 16c3 Synopsys, Inc. + abcd DWC_usb3 / PCIe bridge + abce DWC_usb3 + abcf DWC_usb31 edda EPMockUp 16c6 Micrel-Kendin 8695 Centaur KS8695 ARM processor @@ -19854,6 +20602,10 @@ 7042 AP482 Counter Timer Module with TTL Level Input/Output 7043 AP483 Counter Timer Module with TTL Level and RS422 Input/Output 7044 AP484 Counter Timer Module with RS422 Input/Output + 7051 APA7-501 Reconfigurable Artix-7 52,160 Cell FPGA module 48 TTL channels + 7052 APA7-502 Reconfigurable Artix-7 52,160 Cell FPGA module 24 RS485 channels + 7053 APA7-503 Reconfigurable Artix-7 52,160 Cell FPGA module 24 TTL & 12 RS485 channels + 7054 APA7-504 Reconfigurable Artix-7 52,160 Cell FPGA module 24 LVDS channels 16da Advantech Co., Ltd. 0011 INES GPIB-PCI 16df PIKA Technologies Inc. @@ -19930,10 +20682,10 @@ 0216 PCT-7424E (F0) PC card with standard counters 0217 PCT-7424E (F1) PC card with standard counters 0303 PCD-7006C Digital Input & Output PCI Card + ff00 CTU CAN FD PCIe Card 1761 Pickering Interfaces Ltd 1771 InnoVISION Multimedia Ltd. -# nee SBS Technologies -1775 GE Intelligent Platforms +1775 General Electric 177d Cavium, Inc. 0001 Nitrox XL N1 0003 Nitrox XL N1 Lite @@ -20043,13 +20795,28 @@ 0004 CAMAC Controller 0005 PROFIBUS 0006 AMCC HOTlink + 0007 LVD Cable Bus + 0008 100MHz, 64bit Sequence Generator based on VirtexII + 0009 double 14bit-ADC + 000a SIS1100 with N110 TDC + 000b double 14bit-ADC with memory 000d Synchronisation Slave 000e SIS1100-eCMC 000f TDC (GPX) 0010 PCIe Counter Timer 0011 SIS1100-e single link 0012 SIS1100-e quad link + 0013 4x2.5GHz SFP to 4 lane PCIe bridge + 0014 SIS1100 with GPX piggy back 0015 SIS8100 [Gigabit link, MicroTCA] + 0016 SIS1100e with 4 lanes + 0017 Quad 14bit, 50MHz ADC with 2.5GHz SFP + 0018 SIS8300 4-lane PCI Express, Micro TCA for Physics ADC + 0019 SIS SIS8300-Lx MTCA.4 Digitizer + 001a 100MHz, 64bit Sequence Generator based on VirtexII + 001c Quad 16bit, 150MHz ADC with 2.5GHz SFP + 0030 100MHz, 64bit Sequence Generator based on Spartan6 + 0031 200MHz 64bit Sequence Generator based on Spartan7 # nee Techwell, Inc. 1797 Intersil Techwell 5864 TW5864 multimedia video controller @@ -20158,6 +20925,7 @@ 17d3 1882 ARC-1882 8/12/16/24 Port PCIe 3.0 to SAS/SATA 6Gb RAID Controller 17d3 1883 ARC-1883 8/12/16/24 Port PCIe 3.0 to SAS/SATA 12Gb RAID Controller 1884 ARC-1884 series PCIe 3.0 to SAS/SATA 12/6Gb RAID Controller + 188a ARC-1886 series PCIe 4.0 to NVMe/SAS/SATA 16/12/6Gb RAID Controller # nee Neterion Inc., previously S2io Inc. 17d5 Exar Corp. 5731 Xframe 10-Gigabit Ethernet PCI-X @@ -20222,6 +20990,8 @@ 1915 Arria10 PCIe MainRef Design [DNPCIe_80G_A10_LL] 1916 VirtexUS PCIe Accelerator Board [DNVUF2_HPC_PCIe] 1917 UltrascalePlus PCIe Accelerator Board [DNPCIe_400G_VU_LL] + 1918 VirtexUS+ ASIC Emulation Board [DNVUPF4A] + 1919 UltrascalePlus PCIe Accelerator Board [DNPCIe_400G_VUP_HBM_LL] 1a00 Virtex6 PCIe DMA Netlist Design 1a01 Virtex6 PCIe Darklite Design [DNPCIe_HXT_10G_LL] 1a02 Virtex7 PCIe DMA Netlist Design @@ -20234,6 +21004,8 @@ 1a0a VirtexUS PCIe Darklite Design [DNVUF2_HPC_PCIe] 1a0b UltrascalePlus PCIe Darklite Design [DNPCIe_400G_VU_LL] 1a0c KintexUS PCIe DRAM Packet Capture Design [DNPCIe_40G_KU_LL] + 1a0d KintexUS PCIe DRAM Packet Capture Design [DNPCIe_40G_KU_LL_2QSFP] + 1a0e UltrascalePlus PCIe Darklite Design [DNPCIe_400G_VUP_HBM_LL] 17e4 Sectra AB 0001 KK671 Cardbus encryption board 0002 KK672 Cardbus encryption board @@ -20250,6 +21022,9 @@ 17f2 Albatron Corp. 17f3 RDC Semiconductor, Inc. 1010 R1010 IDE Controller + 1011 R1011 IDE Controller + 1012 R1012 IDE Controller + 1031 PCI/PCI-X to PCI-E Bridge 2012 M2012/R3308 VGA-compatible graphics adapter 6020 R6020 North Bridge 6021 R6021 Host Bridge @@ -20271,6 +21046,8 @@ 1800 Qualcore Logic Inc. 1100 Nanospeed Trading Gateway 1803 ProdaSafe GmbH +1804 Ralink corp. (wrong ID) + 3060 RT3060 Wireless 802.11n 1T/1R 1805 Euresys S.A. 1809 Lumanate, Inc. 180c IEI Integration Corp @@ -20377,6 +21154,10 @@ # HT1000 uses 3 IDs 1166:024a (Native SATA Mode), 1166:024b (PATA/IDE Mode), 182f:000b (RAID Mode) depends on SATA BIOS setting 000b BCM5785 [HT1000] SATA (RAID Mode) 1830 Credence Systems Corporation + 8000 CPIn + 8001 CPId + 8002 CPIx + 8003 CPIq 183b MikroM GmbH 08a7 MVC100 DVI 08a8 MVC101 SDI @@ -20410,6 +21191,7 @@ 0624 MF624 Multifunction I/O PCI Card 0625 MF625 3-phase Motor Driver 0634 MF634 Multifunction I/O PCIe Card + 0644 MF644 Multifunction I/O Thb Card 186f WiNRADiO Communications 1876 L-3 Communications a101 VigraWATCH PCI @@ -20556,6 +21338,7 @@ 0175 NT20E3-2-PTP Network Adapter 2x10Gb 0185 NT40A01 Network Adapter 01a5 NT200A01 Network Adapter + 01c5 NT200A02 Network Adapter 18f6 NextIO 1000 [Nexsis] Switch Virtual P2P PCIe Bridge 1001 [Texsis] Switch Virtual P2P PCIe Bridge @@ -20727,7 +21510,13 @@ 1924 801d x2522-R1 2000 Series 10/25G Adapter 1924 801e x2542-R1 2000 Series 40/100G Adapter 1924 8022 XtremeScale X2522 10G Network Adapter + 1924 8024 XtremeScale X2562 OCP 3.0 Dual Port SFP28 + 1924 8027 XtremeScale X2541 PCIe Single Port QSFP28 1924 8028 XtremeScale X2522-25G Network Adapter + 1924 802a XtremeScale X2542 PCIe Dual Port QSFP28 + 1924 802b XtremeScale X2552 OCP 2.0 Dual Port SFP28 + 1924 802c XtremeScale X2522-25G PCIe Dual Port SFP28 + 1924 802d XtremeScale X2562 OCP 3.0 Dual Port SFP28 1803 SFC9020 10G Ethernet Controller (Virtual Function) 1813 SFL9021 10GBASE-T Ethernet Controller (Virtual Function) 1903 SFC9120 10G Ethernet Controller (Virtual Function) @@ -20895,7 +21684,7 @@ 1026 AR8121/AR8113/AR8114 Gigabit or Fast Ethernet 1043 8304 P5KPL-CM Motherboard 1048 Attansic L1 Gigabit Ethernet - 1043 8226 P5KPL-VM Motherboard + 1043 8226 P5B-MX/WiFi-AP, P5KPL-VM Motherboard 1062 AR8132 Fast Ethernet 1063 AR8131 Gigabit Ethernet 1458 e000 GA-G31M-ES2L Motherboard @@ -20968,6 +21757,9 @@ 1600 OX16C954 HOST-A 16ff OX16C954 HOST-B 1987 Phison Electronics Corporation + 5007 E7 NVMe Controller + 5012 E12 NVMe Controller + 5016 E16 PCIe4 NVMe Controller 1989 Montilio Inc. 0001 RapidFile Bridge 8001 RapidFile @@ -21049,12 +21841,20 @@ 19e5 3033 NVMe SSD ES3600C V3 1200GB HHHL AIC 19e5 3034 NVMe SSD ES3600C V3 1600GB HHHL AIC 19e5 3036 NVMe SSD ES3600C V3 3200GB HHHL AIC - 0200 Hi1822 Family (2*25GE) - 0201 Hi1822 Family (2*100GE) + 0200 Hi1822 Family (2*100GE) + 0202 Hi1822 Family (2*32G FC) + 0203 Hi1822 Family (2*16G FC) + 0205 Hi1822 Family (2*100GE) + 0206 Hi1822 Family (2*25GE) + 0210 Hi1822 Family (4*25GE) + 0211 Hi1822 Family (4*25GE) + 0212 Hi1822 Family (2*8G FC) 1710 iBMA Virtual Network Adapter 1711 Hi1710 [iBMC Intelligent Management system chip w/VGA support] 1822 Hi1822 Family (4*25GE) 371e Hi1822 Family Virtual Bridge + 375e Hi1822 Family Virtual Function + 379e Hi1822 Family Virtual Function a120 HiSilicon PCIe Root Port with Gen4 a121 HiSilicon PCI-PCI Bridge a122 HiSilicon Embedded DMA Engine @@ -21098,6 +21898,7 @@ 1150 AST1150 PCI-to-PCI Bridge 2000 ASPEED Graphics Family 15d9 0832 X10SRL-F +1a05 deltaww 1a07 Kvaser AB 0006 CAN interface PC104+ HS/HS 0007 CAN interface PCIcanx II HS or HS/HS @@ -21116,6 +21917,7 @@ 1a29 Fortinet, Inc. 4338 CP8 Content Processor ASIC 4e36 NP6 Network Processor + 4e37 NP7 Network Processor 1a2b Ascom AG 0000 GESP v1.2 0001 GESP v1.3 @@ -21200,7 +22002,7 @@ 0009 RAIDCore Controller 000a RAIDCore Controller 1aae Global Velocity, Inc. -1ab4 Distributed Management Task Force, Inc. (DMTF)Distributed Management Task Force, Inc. (DMTF) +1ab4 Distributed Management Task Force, Inc. (DMTF) 1ab6 CalDigit, Inc. 6201 RAID Card # Parallels VM virtual devices @@ -21220,6 +22022,8 @@ 13c2 3016 TT-budget S2-4200 Twin 4254 0552 S952 v3 1ae0 Google, Inc. + 0042 Compute Engine Virtual Ethernet [gVNIC] +1ae3 SANBlaze Technology, Inc. 1ae7 First Wise Media GmbH 0520 HFC-S PCI A [X-TENSIONS XC-520] 1ae8 Silicon Software GmbH @@ -21394,6 +22198,7 @@ 1028 1fd6 BOSS-S1 Adapter 1028 1fdf BOSS-S1 Modular 1028 1fe2 BOSS-S1 Adapter + 1028 2010 BOSS-S2 Adapter 1d49 0300 ThinkSystem M.2 with Mirroring Enablement Kit 9235 88SE9235 PCIe 2.0 x2 4-port SATA 6 Gb/s Controller 9445 88SE9445 PCIe 2.0 x4 4-Port SAS/SATA 6 Gbps RAID Controller @@ -21436,6 +22241,8 @@ 1b9a XAVi Technologies Corp. 1baa QNAP Systems, Inc. 1bad ReFLEX CES + c001 XpressGXA10-LP1150 + c002 XpressGXA10-LP1151 1bb0 SimpliVity Corporation 0002 OmniCube Accelerator OA-3000 0010 OmniCube Accelerator OA-3000-2 @@ -21461,12 +22268,32 @@ 1bb1 0103 Nytro 5000 1bb1 0105 Nytro 5020 1bb1 0106 Nytro 5020 TCG +# Larkspur 2.5" + 1bb1 0107 Nytro 5320 +# Larkspur 2.5" TCG + 1bb1 0108 Nytro 5320 TCG 1bb1 0121 Nytro XM1440 1bb1 0123 Nytro 5000 # Kiowa M.2 1bb1 0125 Nytro 5020 # Kiowa M.2 TCG 1bb1 0126 Nytro 5020 +# Larkspur M.2 22110mm + 1bb1 0127 Nytro 5320 M.2 +# Larkspur M.2 22110mm TCG + 1bb1 0128 Nytro 5320 M.2 TCG +# Larkspur M.2 2280mm + 1bb1 0131 Nytro 5320 M.2 +# Larkspur M.2 2280mm TCG + 1bb1 0132 Nytro 5320 M.2 TCG +# Larkspur E1.S + 1bb1 0141 Nytro 5320 E1.S +# Larkspur E1.S TCG + 1bb1 0142 Nytro 5320 E1.S TCG +# Kersey 2.5" + 1bb1 0151 Nytro 5520 +# Kersey 2.5" TCG + 1bb1 0152 Nytro 5520 TCG 1bb1 01a1 Nytro XP7102 1bb3 Bluecherry 4304 BC-04120A MPEG4 4 port video encoder / decoder @@ -21499,6 +22326,7 @@ 0011 MIPS SoC PCI Express Port 1bf4 VTI Instruments Corporation 0001 SentinelEX + 7011 RX0xxx 1bfd EeeTOP 1c09 CSP, Inc. 4254 10G-PCIE3-8D-2S @@ -21515,22 +22343,38 @@ 5001 25G-PCIE3-8B-2S Security Intelligent Adapter 1c1c Symphony 0001 82C101 +1c1f SoftLab-NSK 1c28 Lite-On IT Corp. / Plextor 0122 M6e PCI Express SSD [Marvell 88SS9183] -1c2c Fiberblaze +# previously Fiberblaze +1c2c Silicom Denmark 000a Capture 000f SmartNIC - 00a0 FBC4G Capture 4x1Gb - 00a1 FBC4XG Capture 4x10Gb - 00a2 FBC8XG Capture 8x10Gb - 00a3 FBC2XG Capture 2x10Gb - 00a4 FBC4XGG3 Capture 4x10Gb - 00a5 FBC2XLG Capture 2x40Gb + 00a0 FBC4G Capture 4x1Gb [Herculaneum] + 00a1 FBC4XG Capture 4x10Gb [Ancona] + 00a2 FBC8XG Capture 8x10Gb [Livorno] + 00a3 FBC2XG Capture 2x10Gb [Genoa] + 00a4 FBC4XGG3 Capture 4x10Gb [Livigno] + 00a5 FBC2XLG Capture 2x40Gb [Livorno] 00a6 FBC1CG Capture 1x100Gb 00a9 FBC2XGHH Capture 2x10Gb - 00ad FBC2CGG3HL Capture 2x200Gb + 00ad FBC2CGG3HL Capture 2x100Gb [Padua] 00af Capture slave device - a001 FBC2CGG3 Capture 2x200Gb + 00e0 PacketMover 2x100Gb [Savona] + 00e1 PacketMover 2x100Gb [Tivoli] + 00e3 PacketMover 2x10Gb [Tivoli] + 00e5 PacketMover 2x10Gb [Corfu] + a000 FBC2CGG3 Capture 2x40Gb [Mango_02] + a001 FBC2CGG3 Capture 2x100Gb [Mango_02] + a003 FBC2CGG3 Capture 16x10Gb [Mango] + a007 FBC2CGG3 Capture 2x40Gb [Mango] + a008 FBC2CGG3 Capture 2x25Gb [Mango] + a009 FBC2CGG3 Capture 16x10Gb [Mango] + a00a FBC2CGG3 Capture 8x10Gb [Mango] + a00e FB2CG Capture 2x100Gb [Savona] + a00f FB2CG Capture 2x40Gb [Savona] + a011 FB2CG Capture 2x25Gb [Savona] + a012 FB2CG Capture 8x10Gb [Savona] # Used on V120 VME Crate Controller 1c32 Highland Technology, Inc. 1c33 Daktronics, Inc @@ -21548,10 +22392,14 @@ 0003 Ultrastar SN100 Series NVMe SSD 1014 04f5 PCIe3 1.6TB NVMe Flash Adapter 1014 04f6 PCIe3 3.2TB NVMe Flash Adapter + 1c58 0003 Ultrastar SN100/SN150 NVMe SSD 0023 Ultrastar SN200 Series NVMe SSD 1c58 8823 Ultrastar Memory (ME200) 1c5c SK hynix - 1283 PC300 NVMe Solid State Drive + 1283 PC300 NVMe Solid State Drive 256GB + 1284 PC300 NVMe Solid State Drive 512GB + 1285 PC300 NVMe Solid State Drive 1TB + 1504 SC300 512GB M.2 2280 SATA Solid State Drive 1c5f Beijing Memblaze Technology Co. Ltd. 0540 PBlaze4 NVMe SSD # http://www.nicevt.ru/ (in Russian) @@ -21565,8 +22413,22 @@ 1c8a TSF5 Corporation 0001 Hunter PCI Express 1c8c Mobiveil, Inc. +1cb0 Shannon Systems + d000 Venice NVMe SSD + 1cb0 2f10 Venice-E Series U.2 SSD + 1cb0 2f11 Venice Series U.2 SSD + 1cb0 2f12 Venice-X Series U.2 SSD + 1cb0 af10 Venice-E Series AIC SSD + 1cb0 af11 Venice Series AIC SSD + 1cb0 af12 Venice-X Series AIC SSD 1cb1 Collion UG & Co.KG +1cb5 Focusrite Audio Engineering Ltd + 0002 Clarett 1cb8 Dawning Information Industry Co., Ltd. +1cc1 ADATA Technology Co., Ltd. + 8201 XPG SX8200 Pro PCIe Gen3x4 M.2 2280 Solid State Drive +1cc4 Union Memory (Shenzhen) + 17ab NVMe 256G SSD device 1cc5 Embedded Intelligence, Inc. 0100 CAN-PCIe-02 1cc7 Radian Memory Systems Inc. @@ -21580,6 +22442,8 @@ 0303 Simulyzer-RT CompactPCI Serial PSI5-SIM-1 card 0304 Simulyzer-RT CompactPCI Serial PWR-ANA-1 card 0305 Simulyzer-RT CompactPCI Serial CAN-1 card +# supports 8x CAN (-FD) interfaces + 0306 Simulyzer-RT CompactPCI Serial CAN-2 card (CAN-FD) 1cd7 Nanjing Magewell Electronics Co., Ltd. 0010 Pro Capture Endpoint 0014 PRO CAPTURE AIO 4K PLUS @@ -21595,6 +22459,8 @@ 0007 ExaNIC X40 0008 ExaNIC V5P 0009 ExaNIC X25 + 000a ExaNIC X100 + 000b ExaNIC V9P 0100 ExaDISK FX1 1cf0 Akitio 1cf7 Subspace Dynamics @@ -21603,6 +22469,7 @@ 1d0f Amazon.com, Inc. cd01 NVMe SSD Controller ec20 Elastic Network Adapter (ENA) + efa0 Elastic Fabric Adapter (EFA) 1d17 Zhaoxin 070f ZX-100 PCI Express Root Port 0710 ZX-100/ZX-200 PCI Express Root Port @@ -21612,53 +22479,57 @@ 0714 ZX-100/ZX-200 PCI Express Root Port 0715 ZX-100/ZX-200 PCI Express Root Port 0716 ZX-D PCI Express Root Port - 0717 ZX-D PCI Express Root Port - 0718 ZX-D PCI Express Root Port - 0719 ZX-D PCI Express Root Port - 071a ZX-D PCI Express Root Port - 071b ZX-D PCI Express Root Port - 071c ZX-D PCI Express Root Port - 071d ZX-D PCI Express Root Port - 071e ZX-D PCI Express Root Port + 0717 ZX-D/ZX-E PCI Express Root Port + 0718 ZX-D/ZX-E PCI Express Root Port + 0719 ZX-D/ZX-E PCI Express Root Port + 071a ZX-D/ZX-E PCI Express Root Port + 071b ZX-D/ZX-E PCI Express Root Port + 071c ZX-D/ZX-E PCI Express Root Port + 071d ZX-D/ZX-E PCI Express Root Port + 071e ZX-D/ZX-E PCI Express Root Port 071f ZX-200 Upstream Port of PCI Express Switch 0720 ZX-200 PCIE RC6 controller 0721 ZX-200 Downstream Port of PCI Express Switch 0722 ZX-200 PCIE P2C bridge 1000 ZX-D Standard Host Bridge - 1001 ZX-D Miscellaneous Bus + 1001 ZX-D/ZX-E Miscellaneous Bus + 1003 ZX-E Standard Host Bridge 3001 ZX-100 Standard Host Bridge 300a ZX-100 Miscellaneous Bus - 3038 ZX-100/ZX-200 Standard Universal PCI to USB Host Controller - 3104 ZX-100/ZX-200 Standard Enhanced PCI to USB Host Controller + 3038 ZX-100/ZX-200/ZX-E Standard Universal PCI to USB Host Controller + 3104 ZX-100/ZX-200/ZX-E Standard Enhanced PCI to USB Host Controller 31b0 ZX-100/ZX-D Standard Host Bridge 31b1 ZX-100/ZX-D Standard Host Bridge 31b2 ZX-100/ZX-D DRAM Controller 31b3 ZX-100/ZX-D Power Management Controller 31b4 ZX-100/ZX-D I/O APIC 31b5 ZX-100/ZX-D Scratch Device - 31b7 ZX-100/ZX-D Standard Host Bridge + 31b7 ZX-100/ZX-D/ZX-E Standard Host Bridge 31b8 ZX-100/ZX-D PCI to PCI Bridge - 3288 ZX-100/ZX-D High Definition Audio Controller - 345b ZX-100/ZX-D Miscellaneous Bus + 3288 ZX-100/ZX-D/ZX-E High Definition Audio Controller + 345b ZX-100/ZX-D/ZX-E Miscellaneous Bus 3a02 ZX-100 C-320 GPU 3a03 ZX-D C-860 GPU + 3a04 ZX-E C-960 GPU 9002 ZX-100/ZX-200 EIDE Controller - 9003 ZX-100 EIDE Controller - 9045 ZX-100/ZX-D RAID Accelerator - 9046 ZX-D RAID Accelerator - 9083 ZX-100/ZX-200 StorX AHCI Controller + 9003 ZX-100/ZX-E EIDE Controller + 9045 ZX-100/ZX-D/ZX-E RAID Accelerator 0 + 9046 ZX-D/ZX-E RAID Accelerator 1 + 9083 ZX-100/ZX-200/ZX-E StorX AHCI Controller 9084 ZX-100 StorX AHCI Controller 9100 ZX-200 Cross bus 9101 ZX-200 Traffic Controller 9141 ZX-100 High Definition Audio Controller 9142 ZX-D High Definition Audio Controller + 9144 ZX-E High Definition Audio Controller 9180 ZX-200 Networking Gigabit Ethernet Adapter 9202 ZX-100 USB eXtensible Host Controller 9203 ZX-200 USB eXtensible Host Controller + 9204 ZX-E USB eXtensible Host Controller 9286 ZX-D eMMC Host Controller - 9300 ZX-D eSPI Host Controller + 9300 ZX-D/ZX-E eSPI Host Controller 95d0 ZX-100 Universal SD Host Controller - f410 ZX-100/ZX-D PCI Com Port + f410 ZX-100/ZX-D/ZX-E PCI Com Port 1d18 RME 0001 Fireface UFX+ 1d1d CNEX Labs @@ -21666,12 +22537,19 @@ 2807 8800 series NVMe SSD # CEM Solutions Pvt. Ltd. 1d21 Allo +1d22 Baidu Technology + 1380 Cloud Storage Device 1d26 Kalray Inc. 0040 Turbocard2 Accelerator 0080 Open Network Interface Card 80G 00c0 Turbocard3 Accelerator 0140 Open Network Interface Card 40G e004 AB01/EMB01 Development Board +1d37 NovaSparks + 0013 PM3 + 0014 PM4 + 0015 PM4edge + 0016 PM4edge User Device 1d40 Techman Electronics (Changshu) Co., Ltd. 1d44 DPT a400 PM2x24/PM3224 @@ -21709,14 +22587,26 @@ 1d6c 2001 DPDK-Aware Virtual Function [Arkville VF] 100e AR-ARKA-FX1 [Arkville 64B DPDK Data Mover] 1d6c 2001 DPDK-Aware Virtual Function [Arkville VF] + 100f AR-ARKA-FX1 [Arkville 64B DPDK Data Mover for Versal] + 1010 AR-ARKA-FX1 [Arkville 64B DPDK Data Mover for Agilex] + 1011 AR-MAN-U50 [Manitou Class Accelerator for U50] + 1012 AR-MAN-U200 [Manitou Class Accelerator for U200] + 1013 AR-MAN-U250 [Manitou Class Accelerator for U250] + 1014 AR-MAN-U280 [Manitou Class Accelerator for U280] 4200 A5PL-E1-10GETI [10 GbE Ethernet Traffic Instrument] 1d72 Xiaomi 1d78 DERA 1d7c Aerotech, Inc. 1d82 NETINT Technologies Inc. + 0101 Codensity D400 SSD + 0102 Codensity D408 PCIe Gen4 NVMe SSD + 0202 Codensity T408 Video Encoding-Decoding Accelerator 1d87 Fuzhou Rockchip Electronics Co., Ltd + 0100 RK3399 PCI Express Root Port + 1808 RK1808 Neural Network Processor Card 1d8f Enyx -1d94 Chengdu Higon IC Design Co.Ltd +1d93 YADRO (KNS Group) +1d94 Chengdu Haiguang IC Design Co., Ltd. 1450 Root Complex 1451 I/O Memory Management Unit 1452 PCIe Dummy Host Bridge @@ -21749,11 +22639,45 @@ 1d95 Graphcore Ltd 0001 Colossus GC2 [C2] 0002 Colossus GC1 [S1] +1d9b Facebook, Inc. + 0010 Networking DOM Engine + 0011 IO Bridge 1da1 Teko Telecom S.r.l. 1da2 Sapphire Technology Limited +1da3 Habana Labs Ltd. + 0001 HL-1000 AI Inference Accelerator [Goya] +# PCIe accelerator card for Deep Learning training tasks + 1000 HL-2000 AI Training Accelerator [Gaudi] 1dbb NGD Systems, Inc. 1dbf Guizhou Huaxintong Semiconductor Technology Co., Ltd 0401 StarDragon4800 PCI Express Root Port +1dd8 Pensando Systems Inc + 1000 DSC Capri Upstream Port + 1dd8 4000 Naples 100Gb 2-port QSFP28 x16 8GB + 1dd8 4001 Naples 100Gb 2-port QSFP28 x16 4GB + 1dd8 4002 Naples 25Gb 2-port SFP28 x8 4GB + 1001 DSC Virtual Downstream Port + 1dd8 4000 Naples 100Gb 2-port QSFP28 x16 8GB + 1dd8 4001 Naples 100Gb 2-port QSFP28 x16 4GB + 1dd8 4002 Naples 25Gb 2-port SFP28 x8 4GB + 1002 DSC Ethernet Controller + 1dd8 4000 Naples 100Gb 2-port QSFP28 x16 8GB + 1dd8 4001 Naples 100Gb 2-port QSFP28 x16 4GB + 1dd8 4002 Naples 25Gb 2-port SFP28 x8 4GB + 1003 DSC Ethernet Controller VF + 1dd8 4000 Naples 100Gb 2-port QSFP28 x16 8GB + 1dd8 4001 Naples 100Gb 2-port QSFP28 x16 4GB + 1dd8 4002 Naples 25Gb 2-port SFP28 x8 4GB + 1004 DSC Management Controller + 1dd8 4000 Naples 100Gb 2-port QSFP28 x16 8GB + 1dd8 4001 Naples 100Gb 2-port QSFP28 x16 4GB + 1dd8 4002 Naples 25Gb 2-port SFP28 x8 4GB + 1007 DSC Storage Accelerator + 1dd8 4000 Naples 100Gb 2-port QSFP28 x16 8GB + 1dd8 4001 Naples 100Gb 2-port QSFP28 x16 4GB + 1dd8 4002 Naples 25Gb 2-port SFP28 x8 4GB +1de0 Groq + 0000 Q100 Tensor Streaming Processor 1de1 Tekram Technology Co.,Ltd. 0391 TRM-S1040 [DC-315 / DC-395 series] 2020 DC-390 @@ -21771,12 +22695,56 @@ e00a eMAG PCI Express Root Port 5 e00b eMAG PCI Express Root Port 6 e00c eMAG PCI Express Root Port 7 +1df3 Ethernity Networks + 0201 ACE-NIC40 Programmable Network Accelerator + 1df3 0001 ENA1040 + 1df3 0002 ENA1044 + 1df3 0003 ENA1044S + 0202 ACE-NIC50 Programmable Network Accelerator + 1df3 0001 ENA2050F + 1df3 0002 ENA2050FS + 0203 ACE-NIC100 Programmable Network Accelerator + 1df3 0000 Maintenance Mode + 1df3 0001 ENA2080F + 1df3 0002 ENA2080FS + 1df3 0003 ENA2100F + 1df3 0004 ENA2040F + 0204 ACE-NIC-NID Programmable Network Accelerator + 1df3 0001 ENA1020Z + 1df3 0002 ENA1020ZS 1df7 opencpi.org 0001 ml605 0002 alst4 0003 alst4x 1dfc JSC NT-COM 1181 TDM 8 Port E1/T1/J1 Adapter +1e17 Arnold & Richter Cine Technik GmbH & Co. Betriebs KG +1e24 Squirrels Research Labs + 0101 Acorn CLE-101 + 0215 Acorn CLE-215 + 021f Acorn CLE-215+ + 1525 Xilinx BCU-1525 +# VU33P FPGA Accelerator + 1533 ForestKitten 33 +# JungleCat VU33P Module + 1633 JCM33 +# JungleCat VU35P Module + 1635 JCM35 +1e26 Fujitsu Client Computing Limited +1e38 Thinci, Inc +1e3d Burlywood, Inc +1e49 Yangtze Memory Technologies Co.,Ltd +1e4c GSI Technology +# Associative Processing Unit chip + 0010 Gemini [ Lida ] + 1e4c 0120 SE120 +1e57 Beijing Panyi Technology Co., Ltd + 0100 The device has already been deleted. + 0000 0100 PY8800 64GB Accelerator +1e6b Axiado Corp. +1e89 ID Quantique SA + 0002 Quantis-PCIe-40M + 0003 Quantis-PCIe-240M # nee Tumsan Oy 1fc0 Ascom (Finland) Oy 0300 E2200 Dual E1/Rawpipe Card @@ -21851,6 +22819,8 @@ 20f4 TRENDnet 2116 ZyDAS Technology Corp. 21c3 21st Century Computer Corp. +22b8 Flex-Logix Technologies + 22a0 Flex Logix InferX X1 Inference Accelerator 22db Missing Link Electronics, Inc. 2304 Colorgraphic Communications Corp. 2348 Racore @@ -22246,6 +23216,11 @@ 0030 [mvHYPERION-HD-SDI-Merger] HD-SDI PCI Express x4 Frame Grabber 4ddc ILC Data Device Corp 0100 DD-42924I5-300 (ARINC 429 Data Bus) + 0300 SB-3620 Motion Feedback Device + 0340 SB-3623 Motion Feedback Device + 0400 SB-3622 Motion Feedback Device + 0500 SB-3621 Motion Feedback Device + 0510 SB-3624 Motion Feedback Device 0801 BU-65570I1 MIL-STD-1553 Test and Simulation 0802 BU-65570I2 MIL-STD-1553 Test and Simulation 0811 BU-65572I1 MIL-STD-1553 Test and Simulation @@ -22262,6 +23237,10 @@ 0b02 BU-65569I2 MIL-STD-1553 Data Bus 0b03 BU-65569I3 MIL-STD-1553 Data Bus 0b04 BU-65569I4 MIL-STD-1553 Data Bus + 0d01 SB-3641 Motion Feedback Device + 0d10 SB-365x Motion Feedback Device + 2f00 SB-3642 Motion Feedback Device + 3000 SB-3644 Motion Feedback Device 5045 University of Toronto 4243 BLASTbus PCI Interface Card v1 5046 GemTek Technology Corporation @@ -22627,6 +23606,7 @@ 0122 2nd Generation Core Processor Family Integrated Graphics Controller 0126 2nd Generation Core Processor Family Integrated Graphics Controller 1028 04cc Vostro 3350 + 17aa 21ce ThinkPad T420 17aa 21cf ThinkPad T520 0150 Xeon E3-1200 v2/3rd Gen Core processor DRAM Controller 1043 84ca P8 series motherboard @@ -22672,6 +23652,14 @@ 1043 844d P8B WS Motherboard 0172 Xeon E3-1200 v2/3rd Gen Core processor Graphics Controller 0176 3rd Gen Core processor Graphics Controller + 02a4 Comet Lake SPI (flash) Controller + 02a6 Comet Lake North Peak + 02d3 Comet Lake SATA AHCI Controller + 02e0 Comet Lake Management Engine Interface + 02e8 Serial IO I2C Host Controller + 02f0 Wireless-AC 9462 + 02f9 Comet Lake Thermal Subsytem + 02fc Comet Lake Integrated Sensor Solution 0309 80303 I/O Processor PCI-to-PCI Bridge 030d 80312 I/O Companion Chip PCI-to-PCI Bridge 0326 6700/6702PXH I/OxAPIC Interrupt Controller A @@ -23175,7 +24163,23 @@ 1028 2005 Express Flash NVMe 4.0TB 2.5" U.2 (P4510) 108e 4870 NVMe PCIe 3.0 SSD 6.4TB AIC (P4608) 108e 4871 NVMe PCIe 3.0 SSD 6.4TB 2.5-inch (P4600) + 108e 4879 NVMe PCIe 3.0 SSD v2 6.4TB AIC (P4618) 108e 487a NVMe PCIe 3.0 SSD v2 6.4TB 2.5-inch (P4610) + 1137 0227 NVMe Datacenter SSD [3DNAND] 1.6TB 2.5" U.2 (P4600) + 1137 0228 NVMe Datacenter SSD [3DNAND] 2.0TB 2.5" U.2 (P4600) + 1137 0229 NVMe Datacenter SSD [3DNAND] 3.2TB 2.5" U.2 (P4600) + 1137 022b NVMe Datacenter SSD [3DNAND] 1.0TB 2.5" U.2 (P4500) + 1137 022c NVMe Datacenter SSD [3DNAND] 2.0TB 2.5" U.2 (P4500) + 1137 022d NVMe Datacenter SSD [3DNAND] 4.0TB 2.5" U.2 (P4500) + 1137 0231 NVMe Datacenter SSD [3DNAND] 0.5TB 2.5" U.2 (P4501) + 1137 0232 NVMe Datacenter SSD [3DNAND] 1.0TB 2.5" U.2 (P4501) + 1137 0233 NVMe Datacenter SSD [3DNAND] 2.0TB 2.5" U.2 (P4501) + 1137 0258 NVMe Datacenter SSD [3DNAND] 1.6TB 2.5" U.2 (P4610) + 1137 025a NVMe Datacenter SSD [3DNAND] 3.2TB 2.5" U.2 (P4610) + 1137 025b NVMe Datacenter SSD [3DNAND] 1.0TB 2.5" U.2 (P4510) + 1137 025c NVMe Datacenter SSD [3DNAND] 2.0TB 2.5" U.2 (P4510) + 1137 025d NVMe Datacenter SSD [3DNAND] 4.0TB 2.5" U.2 (P4510) + 1137 025e NVMe Datacenter SSD [3DNAND] 8.0TB 2.5" U.2 (P4510) 1590 025d NVMe Datacenter SSD [3DNAND] 1.0TB 2.5" U.2 (P4500) 1590 025e NVMe Datacenter SSD [3DNAND] 2.0TB 2.5" U.2 (P4500) 1590 025f NVMe Datacenter SSD [3DNAND] 4.0TB 2.5" U.2 (P4500) @@ -23183,6 +24187,12 @@ 1590 0264 NVMe Datacenter SSD [3DNAND] 3.2TB 2.5" U.2 (P4600) 1590 0265 NVMe Datacenter SSD [3DNAND] 6.4TB 2.5" U.2 (P4600) 1590 026c NVMe Datacenter SSD [3DNAND] 4.0TB AIC (P4500) + 1d49 4702 Thinksystem Intel P4500 NVMe U.2 + 1d49 4704 Thinksystem Intel P4500 NVMe AIC + 1d49 4712 Thinksystem Intel P4600 NVMe U.2 + 1d49 4714 Thinksystem Intel P4600 NVMe AIC + 1d49 4802 Thinksystem U.2 P4510 NVMe SSD + 1d49 4812 Thinksystem U.2 P4610 NVMe SSD 8086 4308 Intel SSD D5-P4320 and D5-P4326 8086 4702 NVMe Datacenter SSD [3DNAND] SE 2.5" U.2 (P4500) 8086 4704 NVMe Datacenter SSD [3DNAND] SE AIC (P4500) @@ -23273,6 +24283,9 @@ 0c7d Atom Processor S1200 Internal 0c7e Atom Processor S1200 Internal 0c7f Atom Processor S1200 Internal + 0cf8 Ethernet Controller X710 Intel(R) FPGA Programmable Acceleration Card N3000 for Networking + 8086 0000 Ethernet Controller X710 Intel(R) FPGA Programmable Acceleration Card N3000 for Networking + 8086 0001 Ethernet Controller X710 Intel(R) FPGA Programmable Acceleration Card N3000 for Networking 0d00 Crystal Well DRAM Controller 0d01 Crystal Well PCI Express x16 Controller 0d04 Crystal Well DRAM Controller @@ -23282,6 +24295,15 @@ 0d16 Crystal Well Integrated Graphics Controller 0d26 Crystal Well Integrated Graphics Controller 0d36 Crystal Well Integrated Graphics Controller + 0d4c Ethernet Connection (11) I219-LM + 0d4d Ethernet Connection (11) I219-V + 0d4e Ethernet Connection (10) I219-LM + 0d4f Ethernet Connection (10) I219-V + 0d53 Ethernet Connection (12) I219-LM + 0d55 Ethernet Connection (12) I219-V + 0d58 Ethernet Controller XXV710 Intel(R) FPGA Programmable Acceleration Card N3000 for Networking + 8086 0000 Ethernet Controller XXV710 Intel(R) FPGA Programmable Acceleration Card N3000 for Networking + 8086 0001 Ethernet Controller XXV710 Intel(R) FPGA Programmable Acceleration Card N3000 for Networking 0e00 Xeon E7 v2/Xeon E5 v2/Core i7 DMI2 1028 04f7 Xeon E5 v2 on PowerEdge R320 server 15d9 066b X9SRL-F @@ -23663,7 +24685,10 @@ 104b 82566DC Gigabit Network Connection 104c 82562V 10/100 Network Connection 104d 82566MC Gigabit Network Connection + 104e Ethernet Controller X710 for 10 Gigabit SFP+ + 104f Ethernet Controller X710 for 10 Gigabit backplane 1050 82562EZ 10/100 Ethernet Controller + 1014 0287 ThinkCentre S50 1028 019d Dimension 3000 1462 728c 865PE Neo2 (MS-6728) 1462 758c MS-6758 (875P Neo) @@ -23958,6 +24983,7 @@ 103c 2159 Ethernet 10Gb 2-port 562i Adapter 108e 7b11 Ethernet Server Adapter X520-2 1170 004c 82599 DP 10G Mezzanine Adapter + 15d9 0611 AOC-STGN-I2S [REV 1.01] 1734 11a9 10 Gigabit Dual Port Network Connection 17aa 1071 ThinkServer X520-2 AnyFabric 17aa 4007 82599ES 10-Gigabit SFI/SFP+ Network Connection @@ -24224,6 +25250,7 @@ 1043 849c P8P67 Deluxe Motherboard 1507 Ethernet Express Module X520-P2 1508 82598EB Gigabit BX Network Connection + 1509 82580 Gigabit Network Connection 150a 82576NS Gigabit Network Connection 150b 82598EB 10-Gigabit AT2 Server Adapter 8086 a10c 82598EB 10-Gigabit AT2 Server Adapter @@ -24291,10 +25318,14 @@ 1bd4 0035 1G base-T QP EP014Ti1 Adapter 8086 0001 Ethernet Server Adapter I350-T4 8086 0002 Ethernet Server Adapter I350-T2 + 8086 0003 Ethernet Network Adapter I350-T4 for OCP NIC 3.0 8086 00a1 Ethernet Server Adapter I350-T4 8086 00a2 Ethernet Server Adapter I350-T2 + 8086 00a3 Ethernet Network Adapter I350-T4 for OCP NIC 3.0 + 8086 00aa Ethernet Network Adapter I350-T4 for OCP NIC 3.0 8086 5001 Ethernet Server Adapter I350-T4 8086 5002 Ethernet Server Adapter I350-T2 + 8086 5003 Ethernet 1G 4P I350-t OCP 1522 I350 Gigabit Fiber Network Connection 108e 7b17 Quad Port GbE PCIe 2.0 ExpressModule, MMF 108e 7b19 Dual Port GbE PCIe 2.0 Low Profile Adapter, MMF @@ -24348,8 +25379,10 @@ 152e 82599 Virtual Function 152f I350 Virtual Function 1530 X540 Virtual Function + 1531 I210 Gigabit Unprogrammed 1533 I210 Gigabit Network Connection 103c 0003 Ethernet I210-T1 GbE NIC + 1059 0180 RD10019 1GbE interface 1093 7706 Compact Vision System Ethernet Adapter 10a9 802c UV300 BaseIO single-port GbE 10a9 802d UV3000 BaseIO GbE Network @@ -24402,6 +25435,8 @@ 1563 Ethernet Controller 10G X550T 1028 1fa8 Ethernet 10G 4P X550/I350 rNDC 1028 1fa9 Ethernet 10G 4P X550 rNDC + 1137 02b2 X550-TX 10 Gig LOM + 1137 02b3 X550-TX 10 Gig LOM 1170 0001 Intel Ethernet Controller X550-T2 OCP card 14c0 1201 X550 10Gb 2P RJ45 OCP Mezz 1590 00d1 Ethernet 10Gb 2-port 562T Adapter @@ -24427,6 +25462,7 @@ 156d DSL5520 Thunderbolt 2 Bridge [Falcon Ridge 4C 2013] 156f Ethernet Connection I219-LM 1028 06dc Latitude E7470 + 103c 8079 EliteBook 840 G3 1570 Ethernet Connection I219-V 1571 Ethernet Virtual Function 700 Series 1572 Ethernet Controller X710 for 10GbE SFP+ @@ -24461,9 +25497,17 @@ 8086 000e Ethernet Server Adapter OCP X710-2 8086 000f Ethernet Server Adapter OCP X710-2 8086 0010 Ethernet Converged Network Adapter X710 + 8086 0011 Ethernet Network Adapter X710-2 for OCP NIC 3.0 + 8086 0012 Ethernet Network Adapter X710-4 for OCP NIC 3.0 + 8086 0013 Ethernet 10G 2P X710 OCP + 8086 0014 Ethernet 10G 4P X710 OCP + 8086 0015 Ethernet Server Adapter X710-DA2 for OCP + 8086 00a1 Ethernet Network Adapter X710-2 for OCP NIC 3.0 + 8086 00a2 Ethernet Network Adapter X710-4 for OCP NIC 3.0 8086 4005 Ethernet Controller X710 for 10GbE SFP+ 8086 4006 Ethernet Controller X710 for 10GbE SFP+ 8086 4007 Ethernet Controller X710 for 10GbE SFP+ + 1574 Ethernet Controller XL710 Emulation 1575 DSL6340 Thunderbolt 3 NHI [Alpine Ridge 2C 2015] 1576 DSL6340 Thunderbolt 3 Bridge [Alpine Ridge 2C 2015] 1577 DSL6540 Thunderbolt 3 NHI [Alpine Ridge 4C 2015] @@ -24487,6 +25531,7 @@ 1028 1f9f Ethernet 40G 2P XL710 QSFP+ rNDC 108e 0000 10 Gb/40 Gb Ethernet Adapter 108e 7b1b 10 Gb/40 Gb Ethernet Adapter + 108e 7b1d 10Gb/40Gb Ethernet Adapter 1137 0000 Ethernet Converged NIC XL710-QDA2 1137 013c Ethernet Converged NIC XL710-QDA2 8086 0000 Ethernet Converged Network Adapter XL710-Q2 @@ -24511,6 +25556,8 @@ 1588 Ethernet Controller XL710 for 20GbE backplane 103c 0000 Ethernet 10/20Gb 2-port 660M Adapter 103c 22ff Ethernet 10/20Gb 2-port 660M Adapter + 1137 0000 Ethernet Network Adapter XXV710 + 1137 02b4 Ethernet Network Adapter XXV710 OCP 2.0 1589 Ethernet Controller X710/X557-AT 10GBASE-T 108e 0000 Quad Port 10GBase-T Adapter 108e 7b1c Quad Port 10GBase-T Adapter @@ -24523,8 +25570,14 @@ 158a Ethernet Controller XXV710 for 25GbE backplane 1590 0000 10/25Gb Ethernet Adapter 1590 0286 Synergy 4610C 10/25Gb Ethernet Adapter + 8086 0000 Ethernet Controller XXV710 for 25GbE backplane 8086 000a Ethernet 25G 2P XXV710 Mezz 158b Ethernet Controller XXV710 for 25GbE SFP28 + 1137 0000 Ethernet Network Adapter XXV710 + 1137 0225 Ethernet Network Adapter XXV710 + 1137 02b4 Ethernet Network Adapter XXV710 OCP 2.0 + 1590 0000 Ethernet Network Adapter XXV710-2 + 1590 0253 Ethernet 10/25/Gb 2-port 661SFP28 Adapter 8086 0000 Ethernet Network Adapter XXV710 8086 0001 Ethernet Network Adapter XXV710-2 8086 0002 Ethernet Network Adapter XXV710-2 @@ -24535,10 +25588,22 @@ 8086 0007 Ethernet Network Adapter OCP XXV710-1 8086 0008 Ethernet Network Adapter OCP XXV710-1 8086 0009 Ethernet 25G 2P XXV710 Adapter + 8086 000a Ethernet 25G 2P XXV710 OCP 8086 4001 Ethernet Network Adapter XXV710-2 1591 Ethernet Controller E810-C for backplane 1592 Ethernet Controller E810-C for QSFP + 8086 0002 Ethernet Network Adapter E810-C-Q2 + 8086 0004 Ethernet Network Adapter E810-C-Q2 + 8086 0005 Ethernet Network Adapter E810-C-Q1 for OCP3.0 + 8086 0006 Ethernet Network Adapter E810-C-Q2 for OCP3.0 + 8086 0009 Ethernet Network Adapter E810-C-Q1 1593 Ethernet Controller E810-C for SFP + 8086 0002 Ethernet Network Adapter E810-L-2 + 8086 0005 Ethernet Network Adapter E810-XXV-4 + 8086 0006 Ethernet Network Adapter E810-XXV-4 + 8086 0007 Ethernet Network Adapter E810-XXV-4 + 8086 0008 Ethernet Network Adapter E810-XXV-2 + 8086 0009 Ethernet Network Adapter E810-XXV-2 for OCP 2.0 15a0 Ethernet Connection (2) I218-LM 15a1 Ethernet Connection (2) I218-V 15a2 Ethernet Connection (3) I218-LM @@ -24569,6 +25634,7 @@ 15be Ethernet Connection (6) I219-V 15bf JHL6240 Thunderbolt 3 NHI (Low Power) [Alpine Ridge LP 2016] 15c0 JHL6240 Thunderbolt 3 Bridge (Low Power) [Alpine Ridge LP 2016] + 15c1 JHL6240 Thunderbolt 3 USB 3.1 Controller (Low Power) [Alpine Ridge LP 2016] 15c2 Ethernet Connection X553 Backplane 15c3 Ethernet Connection X553 Backplane 15c4 Ethernet Connection X553 10 GbE SFP+ @@ -24598,6 +25664,7 @@ 17aa 225d ThinkPad T480 15d9 JHL6340 Thunderbolt 3 NHI (C step) [Alpine Ridge 2C 2016] 15da JHL6340 Thunderbolt 3 Bridge (C step) [Alpine Ridge 2C 2016] + 15db JHL6340 Thunderbolt 3 USB 3.1 Controller (C step) [Alpine Ridge 2C 2016] 15df Ethernet Connection (8) I219-LM 15e0 Ethernet Connection (8) I219-V 15e1 Ethernet Connection (9) I219-LM @@ -24613,6 +25680,25 @@ 15ec JHL7540 Thunderbolt 3 USB Controller [Titan Ridge 4C 2018] 15ef JHL7540 Thunderbolt 3 Bridge [Titan Ridge DD 2018] 15f0 JHL7540 Thunderbolt 3 USB Controller [Titan Ridge DD 2018] + 15f6 I210 Gigabit Ethernet Connection + 15ff Ethernet Controller X710 for 10GBASE-T + 1137 0000 X710TLG GbE RJ45 PCIe NIC + 1137 02c1 X710T2LG 2x10 GbE RJ45 PCIe NIC + 1137 02c2 X710T4LG 4x10 GbE RJ45 PCIe NIC + 8086 0000 Ethernet Network Adapter X710-TL + 8086 0001 Ethernet Network Adapter X710-T4L + 8086 0002 Ethernet Network Adapter X710-T4L + 8086 0003 Ethernet Network Adapter X710-T2L + 8086 0004 Ethernet Network Adapter X710-T2L + 8086 0005 Ethernet 10G 2P X710-T2L-t Adapter + 8086 0006 Ethernet 10G 4P X710-T4L-t Adapter + 8086 0007 Ethernet 10G 2P X710-T2L-t OCP + 8086 0008 Ethernet 10G 4P X710-T4L-t OCP + 8086 0009 Ethernet Network Adapter X710-T4L for OCP 3.0 + 8086 000a Ethernet Network Adapter X710-T4L for OCP 3.0 + 8086 000b Ethernet Network Adapter X710-T2L for OCP 3.0 + 8086 000c Ethernet Network Adapter X710-T2L for OCP 3.0 + 8086 000f Ethernet Network Adapter X710-T2L for OCP 3.0 1600 Broadwell-U Host Bridge -OPI 1601 Broadwell-U PCI Express x16 Controller 1602 Broadwell-U Integrated Graphics @@ -24652,6 +25738,8 @@ 163d Broadwell-U Integrated Graphics 163e Broadwell-U Integrated Graphics 1889 Ethernet Adaptive Virtual Function + 18a0 C4xxx Series QAT + 18a1 C4XXX Series QAT Virtual Function 1900 Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Host Bridge/DRAM Registers 1901 Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor PCIe Controller (x16) 1902 HD Graphics 510 @@ -24662,6 +25750,7 @@ 1904 Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Host Bridge/DRAM Registers 1028 06dc Latitude E7470 1028 06f3 Latitude 3570 + 103c 8079 EliteBook 840 G3 17aa 382a B51-80 Laptop 1905 Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor PCIe Controller (x8) 1906 HD Graphics 510 @@ -24672,7 +25761,7 @@ 190f Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Host Bridge/DRAM Registers 1910 Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Host Bridge/DRAM Registers 1028 06e4 XPS 15 9550 - 1911 Xeon E3-1200 v5/v6 / E3-1500 v5 / 6th/7th Gen Core Processor Gaussian Mixture Model + 1911 Xeon E3-1200 v5/v6 / E3-1500 v5 / 6th/7th/8th Gen Core Processor Gaussian Mixture Model 17aa 2247 ThinkPad T570 17aa 224f ThinkPad X1 Carbon 5th Gen 17aa 225d ThinkPad T480 @@ -24680,6 +25769,7 @@ 1916 Skylake GT2 [HD Graphics 520] 1028 06dc Latitude E7470 1028 06f3 Latitude 3570 + 103c 8079 EliteBook 840 G3 1918 Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Host Bridge/DRAM Registers 1919 Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Imaging Unit 191b HD Graphics 530 @@ -24724,6 +25814,18 @@ 1962 80960RM (i960RM) Microprocessor 105a 0000 SuperTrak SX6000 I2O CPU 1964 80960RN (i960RN) Microprocessor + 1980 Atom Processor C3000 Series System Agent + 19a1 Atom Processor C3000 Series Error Registers + 19a2 Atom Processor C3000 Series Root Complex Event Collector + 19a3 Atom Processor C3000 Series Integrated QAT Root Port + 19a4 Atom Processor C3000 Series PCI Express Root Port #0 + 19a5 Atom Processor C3000 Series PCI Express Root Port #1 + 19a6 Atom Processor C3000 Series PCI Express Root Port #2 + 19a7 Atom Processor C3000 Series PCI Express Root Port #3 + 19a8 Atom Processor C3000 Series PCI Express Root Port #4 + 19a9 Atom Processor C3000 Series PCI Express Root Port #5 + 19aa Atom Processor C3000 Series PCI Express Root Port #6 + 19ab Atom Processor C3000 Series PCI Express Root Port #7 19ac Atom Processor C3000 Series SMBus Contoller - Host 19b0 Atom Processor C3000 Series SATA Controller 0 19b1 Atom Processor C3000 Series SATA Controller 0 @@ -24746,7 +25848,16 @@ 19ce Atom Processor C3000 Series SATA Controller 1 19cf Atom Processor C3000 Series SATA Controller 1 19d0 Atom Processor C3000 Series USB 3.0 xHCI Controller + 19d1 Atom Processor C3000 Series Integrated LAN Root Port #0 + 19d2 Atom Processor C3000 Series Integrated LAN Root Port #1 + 19d3 Atom Processor C3000 Series ME HECI 1 + 19d4 Atom Processor C3000 Series ME HECI 2 + 19d5 Atom Processor C3000 Series ME KT Controller + 19d6 Atom Processor C3000 Series ME HECI 3 + 19d8 Atom Processor C3000 Series HSUART Controller 19dc Atom Processor C3000 Series LPC or eSPI + 19dd Atom Processor C3000 Series Primary to Side Band (P2SB) Bridge + 19de Atom Processor C3000 Series Power Management Controller 19df Atom Processor C3000 Series SMBus controller 19e0 Atom Processor C3000 Series SPI Controller 19e2 Atom Processor C3000 Series QuickAssist Technology @@ -25189,15 +26300,32 @@ 2018 Sky Lake-E M2PCI Registers 201a Sky Lake-E Non-Transparent Bridge Registers 201c Sky Lake-E Non-Transparent Bridge Registers + 201d Volume Management Device NVMe RAID Controller 2020 Sky Lake-E DMI3 Registers 15d9 095d X11SPM-TF 2021 Sky Lake-E CBDMA Registers 2024 Sky Lake-E MM/Vt-d Configuration Registers + 2025 Sky Lake-E RAS + 2026 Sky Lake-E IOAPIC 2030 Sky Lake-E PCI Express Root Port A 2031 Sky Lake-E PCI Express Root Port B 2032 Sky Lake-E PCI Express Root Port C 2033 Sky Lake-E PCI Express Root Port D + 2034 Sky Lake-E VT-d 2035 Sky Lake-E RAS Configuration Registers + 2036 Sky Lake-E IOxAPIC Configuration Registers + 2040 Sky Lake-E Integrated Memory Controller + 2041 Sky Lake-E Integrated Memory Controller + 2042 Sky Lake-E Integrated Memory Controller + 2043 Sky Lake-E Integrated Memory Controller + 2044 Sky Lake-E Integrated Memory Controller + 2045 Sky Lake-E LM Channel 1 + 2046 Sky Lake-E LMS Channel 1 + 2047 Sky Lake-E LMDP Channel 1 + 2048 Sky Lake-E DECS Channel 2 + 2049 Sky Lake-E LM Channel 2 + 204a Sky Lake-E LMS Channel 2 + 204b Sky Lake-E LMDP Channel 2 204c Sky Lake-E M3KTI Registers 204d Sky Lake-E M3KTI Registers 204e Sky Lake-E M3KTI Registers @@ -25205,6 +26333,9 @@ 2055 Sky Lake-E CHA Registers 2056 Sky Lake-E CHA Registers 2057 Sky Lake-E CHA Registers + 2058 Sky Lake-E KTI 0 + 2059 Sky Lake-E UPI Registers + 2066 Sky Lake-E Integrated Memory Controller 2068 Sky Lake-E DDRIO Registers 2069 Sky Lake-E DDRIO Registers 206a Sky Lake-E IOxAPIC Configuration Registers @@ -25219,12 +26350,15 @@ 2084 Sky Lake-E PCU Registers 2085 Sky Lake-E PCU Registers 2086 Sky Lake-E PCU Registers + 2088 Sky Lake-E DDRIO Registers 208d Sky Lake-E CHA Registers 208e Sky Lake-E CHA Registers + 2241 Larrabee 2250 Xeon Phi coprocessor 5100 series 225c Xeon Phi coprocessor SE10/7120 series - 225d Xeon Phi coprocessor 3120 series + 225d Xeon Phi coprocessor 3120 series 225e Xeon Phi coprocessor 31S1 + 2262 Xeon Phi coprocessor 7220 2280 Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series SoC Transaction Register 2284 Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series High Definition Audio Controller 2286 Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series LPIO1 DMA Controller @@ -25239,7 +26373,7 @@ 22a3 Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series SATA Controller 22a4 Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series SATA AHCI Controller 22a8 Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series Low Power Engine Audio - 22b0 Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series PCI Configuration Registers + 22b0 Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Integrated Graphics Controller 22b1 Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Integrated Graphics Controller 22b5 Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series USB xHCI Controller 22b8 Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series Imaging Unit @@ -25462,6 +26596,7 @@ # same ID possibly also on other ASUS boards 1043 8277 P5K PRO Motherboard 1043 844d P8 series motherboard + 1043 8534 ASUS B85-PLUS 1458 5000 Motherboard 1462 7345 MS-7345 Motherboard: Intel 82801I/IR [ICH9/ICH9R] 1462 7418 Wind PC MS-7418 @@ -25759,6 +26894,7 @@ 8086 4c43 Desktop Board D865GLC 8086 524c D865PERL mainboard 24d2 82801EB/ER (ICH5/ICH5R) USB UHCI Controller #1 + 1014 0287 ThinkCentre S50 1014 02dd eServer xSeries server mainboard 1014 02ed eServer xSeries server mainboard 1028 0168 Precision Workstation 670 Mainboard @@ -25782,6 +26918,7 @@ 8086 4c43 Desktop Board D865GLC 8086 524c D865PERL mainboard 24d3 82801EB/ER (ICH5/ICH5R) SMBus Controller + 1014 0287 ThinkCentre S50 1014 02dd eServer xSeries server mainboard 1014 02ed eServer xSeries server mainboard 1028 0156 Precision 360 @@ -25801,6 +26938,7 @@ 8086 4c43 Desktop Board D865GLC 8086 524c D865PERL mainboard 24d4 82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2 + 1014 0287 ThinkCentre S50 1014 02dd eServer xSeries server mainboard 1014 02ed eServer xSeries server mainboard 1028 0168 Precision Workstation 670 Mainboard @@ -25826,6 +26964,7 @@ 8086 524c D865PERL mainboard 24d5 82801EB/ER (ICH5/ICH5R) AC'97 Audio Controller 100a 147b Abit IS7-E motherboard + 1014 0287 ThinkCentre S50 1028 0168 Precision Workstation 670 Mainboard 1028 0169 Precision 470 103c 006a NX9500 @@ -25843,6 +26982,7 @@ 24d6 82801EB/ER (ICH5/ICH5R) AC'97 Modem Controller 103c 006a NX9500 24d7 82801EB/ER (ICH5/ICH5R) USB UHCI Controller #3 + 1014 0287 ThinkCentre S50 1014 02ed xSeries server mainboard 1028 0168 Precision Workstation 670 Mainboard 1028 0169 Precision 470 @@ -25864,6 +27004,7 @@ 8086 4c43 Desktop Board D865GLC 8086 524c D865PERL mainboard 24db 82801EB/ER (ICH5/ICH5R) IDE Controller + 1014 0287 ThinkCentre S50 1014 02dd eServer xSeries server mainboard 1014 02ed eServer xSeries server mainboard 1028 0168 Precision Workstation 670 Mainboard @@ -25889,6 +27030,7 @@ 8086 524c D865PERL mainboard 24dc 82801EB (ICH5) LPC Interface Bridge 24dd 82801EB/ER (ICH5/ICH5R) USB2 EHCI Controller + 1014 0287 ThinkCentre S50 1014 02dd eServer xSeries server mainboard 1014 02ed eServer xSeries server mainboard 1028 0168 Precision Workstation 670 Mainboard @@ -25910,6 +27052,7 @@ 8086 4c43 Desktop Board D865GLC 8086 524c D865PERL mainboard 24de 82801EB/ER (ICH5/ICH5R) USB UHCI Controller #4 + 1014 0287 ThinkCentre S50 1014 02ed xSeries server mainboard 1028 0168 Precision Workstation 670 Mainboard 1028 0169 Precision 470 @@ -26017,6 +27160,7 @@ 1458 2570 GA-8IPE1000 Pro2 motherboard (865PE) 2571 82865G/PE/P AGP Bridge 2572 82865G Integrated Graphics Controller + 1014 0287 ThinkCentre S50 1028 019d Dimension 3000 103c 12bc D530 sff(dc578av) 1043 80a5 P5P800-MX Mainboard @@ -26468,8 +27612,11 @@ 1028 2000 Express Flash NVMe [Optane] 375GB 2.5" U.2 (P4800X) 1028 2001 Express Flash NVMe [Optane] 750GB 2.5" U.2 (P4800X) 1028 2002 Express Flash NVMe [Optane] 750GB AIC (P4800X) + 1028 200a Express Flash NVMe [Optane] 375GB AIC (P4800X) 8086 3904 NVMe Datacenter SSD [Optane] x4 AIC (P4800X) 8086 3905 NVMe Datacenter SSD [Optane] 15mm 2.5" U.2 (P4800X) + 2723 Wi-Fi 6 AX200 + 8086 2723 Wireless AX200 2770 82945G/GZ/P/PL Memory Controller Hub 1028 01ad OptiPlex GX620 103c 2a3b Pavilion A1512X @@ -26543,7 +27690,7 @@ 27b8 82801GB/GR (ICH7 Family) LPC Interface Bridge 1028 01e6 PowerEdge 860 103c 2a8c Compaq 500B Microtower - 1043 8179 P5KPL-VM Motherboard + 1043 8179 P5B-MX/WiFi-AP, P5KPL-VM Motherboard 107b 5048 E4500 1462 7418 Wind PC MS-7418 1775 11cc CC11/CL11 @@ -26571,7 +27718,7 @@ 1028 01df PowerEdge SC440 1028 01e6 PowerEdge 860 103c 2a8c Compaq 500B Microtower - 1043 8179 P5KPL-VM Motherboard + 1043 8179 P5B-MX/WiFi-AP, P5KPL-VM Motherboard 107b 5048 E4500 1462 2310 MSI Hetis 945 1462 7236 945P Neo3-F Rev. 2.2 motherboard @@ -26802,7 +27949,7 @@ 1028 01e6 PowerEdge 860 103c 2a3b Pavilion A1512X 103c 2a8c Compaq 500B Microtower - 1043 8179 P5KPL-VM Motherboard + 1043 8179 P5B-MX/WiFi-AP, P5KPL-VM Motherboard 105b 0d7c D270S/D250S Motherboard 1071 8209 Medion MIM 2240 Notebook PC [MD98100] 10f7 8338 Panasonic CF-Y5 laptop @@ -26833,7 +27980,7 @@ 103c 30a3 Compaq nw8440 103c 30d5 530 Laptop 1043 1237 A6J-Q008 - 1043 8179 P5KPL-VM Motherboard + 1043 8179 P5B-MX/WiFi-AP, P5KPL-VM Motherboard 107b 5048 E4500 10f7 8338 Panasonic CF-Y5 laptop 1462 7418 Wind PC MS-7418 @@ -26844,6 +27991,7 @@ 1775 11cc CC11/CL11 27e2 82801GR/GH/GHM (ICH7 Family) PCI Express Port 6 1775 11cc CC11/CL11 + 280b Intel(R) Display Audio 2810 82801HB/HR (ICH8/R) LPC Interface Controller 1043 81ec P5B 2811 82801HEM (ICH8M-E) LPC Interface Controller @@ -27903,9 +29051,13 @@ 8086 4210 Dual Band Wireless AC 3165 3166 Dual Band Wireless-AC 3165 Plus Bluetooth 3184 UHD Graphics 605 + 3185 UHD Graphics 605 318c Celeron/Pentium Silver Processor Dynamic Platform and Thermal Framework Processor Participant 318e Celeron/Pentium Silver Processor NorthPeak + 3192 Gemini Lake P2SB + 3197 Celeron/Pentium Silver Processor PCI-default ISA-bridge 319a Celeron/Pentium Silver Processor Trusted Execution Engine Interface + 31a2 Celeron/Pentium Silver Processor Integrated Sensor Solution 31ac Celeron/Pentium Silver Processor Serial IO I2C Host Controller 31ae Celeron/Pentium Silver Processor Serial IO I2C Host Controller 31bc Celeron/Pentium Silver Processor Serial IO UART Host Controller @@ -27914,8 +29066,16 @@ 31c2 Celeron/Pentium Silver Processor Serial IO SPI Host Controller 31c4 Celeron/Pentium Silver Processor Serial IO SPI Host Controller 31c6 Celeron/Pentium Silver Processor Serial IO SPI Host Controller + 31cc Celeron/Pentium Silver Processor SDA Standard Compliant SD Host Controller 31d4 Celeron/Pentium Silver Processor Gaussian Mixture Model + 31d6 Gemini Lake PCI Express Root Port + 31d7 Gemini Lake PCI Express Root Port + 31d8 Gemini Lake PCI Express Root Port + 31d9 Gemini Lake PCI Express Root Port + 31da Gemini Lake PCI Express Root Port + 31db Gemini Lake PCI Express Root Port 31ee Celeron/Pentium Silver Processor Serial IO UART Host Controller + 31f0 Gemini Lake Host Bridge 3200 GD31244 PCI-X SATA HBA 1775 c200 C2K onboard SATA host bus adapter 3310 IOP348 I/O Processor @@ -28002,12 +29162,15 @@ 34bc Ice Lake-LP PCI Express Root Port #5 34c5 Ice Lake-LP Serial IO I2c Controller #4 34c6 Ice Lake-LP Serial IO I2c Controller #5 + 34c8 Smart Sound Technology Audio Controller 34d3 Ice Lake-LP SATA Controller [AHCI mode] + 34e0 Management Engine Interface 34e8 Ice Lake-LP Serial IO I2C Controller #0 34e9 Ice Lake-LP Serial IO I2C Controller #1 34ea Ice Lake-LP Serial IO I2C Controller #2 34eb Ice Lake-LP Serial IO I2C Controller #3 34ed Ice Lake-LP USB 3.1 xHCI Host Controller + 34f0 Killer Wi-Fi 6 AX1650i 160MHz Wireless Network Adapter (201NGW) 34f8 Ice Lake-LP SD Controller 3500 6311ESB/6321ESB PCI Express Upstream Port 103c 31fe ProLiant DL140 G3 @@ -28202,10 +29365,12 @@ 372c Xeon C5500/C3500 Reserved 373f Xeon C5500/C3500 IOxAPIC 37c8 C62x Chipset QuickAssist Technology + 37cc Ethernet Connection X722 37cd Ethernet Virtual Function 700 Series 37ce Ethernet Connection X722 for 10GbE backplane 1590 0215 Ethernet 10Gb 2-port 568i Adapter 17aa 4023 Intel Ethernet Connection X722 for 10GbE backplane + 17aa 4025 Ethernet Connection X722 for 10GbE backplane 37cf Ethernet Connection X722 for 10GbE QSFP+ 37d0 Ethernet Connection X722 for 10GbE SFP+ 17aa 4020 Intel Ethernet Connection X722 for 10G SFP+ @@ -28223,17 +29388,22 @@ 17aa 4020 Ethernet Connection X722 for 1GbE 17aa 4021 Ethernet Connection X722 for 1GbE 17aa 4022 Ethernet Connection X722 for 1GbE + 17aa 4024 Ethernet Connection X722 for 1GbE 37d2 Ethernet Connection X722 for 10GBASE-T + 1059 0180 RD10019 10GbE interface 1170 37d2 Ethernet Connection X722 for 10GBASE-T 14cd 0030 Ethernet OCP 2x10G RJ45 Phy Card [USI-X557-10GbaseT] 1590 0218 Ethernet 10Gb 2-port 568FLR-MMT Adapter 17aa 4020 Ethernet Connection X722 for 10GBASE-T 17aa 4021 Ethernet Connection X722 for 10GBASE-T 17aa 4022 Ethernet Connection X722 for 10GBASE-T + 17aa 4024 Ethernet Connection X722 for 10GBASE-T + 17aa 4025 Ethernet Connection X722 for 10GBASE-T 37d3 Ethernet Connection X722 for 10GbE SFP+ 1590 0219 Ethernet 10Gb 2-port 568FLR-MMSFP+ Adapter 17aa 4020 Ethernet Connection X722 for 10GbE SFP+ 17aa 4021 Ethernet Connection X722 for 10GbE SFP+ + 17aa 4025 Ethernet Connection X722 for 10GbE SFP+ 37d4 Ethernet Connection X722 for 10GbE QSFP+ 37d9 X722 Hyper-V Virtual Function 3a00 82801JD/DO (ICH10 Family) 4-port SATA IDE Controller @@ -28601,17 +29771,27 @@ 3cf4 Xeon E5/Core i7 Integrated Memory Controller System Address Decoder 0 3cf5 Xeon E5/Core i7 Integrated Memory Controller System Address Decoder 1 3cf6 Xeon E5/Core i7 System Address Decoder - 3e18 8th Gen Core Processor Host Bridge/DRAM Registers - 3e1f 8th Gen Core Processor Host Bridge/DRAM Registers + 3e10 8th Gen Core 4-core Processor Host Bridge/DRAM Registers [Coffee Lake H] + 3e18 8th Gen Core 4-core Workstation Processor Host Bridge/DRAM Registers [Coffee Lake S] + 3e1f 8th Gen Core 4-core Desktop Processor Host Bridge/DRAM Registers [Coffee Lake S] + 1458 5000 Z370 AORUS Gaming K3-CF + 3e30 8th Gen Core 8-core Desktop Processor Host Bridge/DRAM Registers [Coffee Lake S] + 3e33 8th/9th Gen Core Processor Host Bridge/DRAM Registers [Coffee Lake] + 3e34 Coffee Lake HOST and DRAM Controller 3e81 8th Gen Core Processor PCIe Controller (x16) 3e85 8th Gen Core Processor PCIe Controller (x8) 3e89 8th Gen Core Processor PCIe Controller (x4) 3e91 8th Gen Core Processor Gaussian Mixture Model 3e92 UHD Graphics 630 (Desktop) + 3e93 UHD Graphics 610 + 3e96 HD Graphics P630 + 3e98 UHD Graphics 630 (Desktop 9 Series) 3e9b UHD Graphics 630 (Mobile) 3ea0 UHD Graphics 620 (Whiskey Lake) + 1028 089e Inspiron 5482 3ea5 Iris Plus Graphics 655 3ec2 8th Gen Core Processor Host Bridge/DRAM Registers + 1043 8694 PRIME H310M-D 3ec4 8th Gen Core Processor Host Bridge/DRAM Registers 3ec6 8th Gen Core Processor Host Bridge/DRAM Registers 3eca 8th Gen Core Processor Host Bridge/DRAM Registers @@ -28802,6 +29982,7 @@ 5909 Xeon E3-1200 v6/7th Gen Core Processor PCIe Controller (x4) 590c Xeon E3-1200 v6/7th Gen Core Processor Host Bridge/DRAM Registers 590f Xeon E3-1200 v6/7th Gen Core Processor Host Bridge/DRAM Registers + 1462 7a68 B250 KRAIT GAMING (MS-7A68) 5910 Xeon E3-1200 v6/7th Gen Core Processor Host Bridge/DRAM Registers 5911 Xeon E3-1200 v6/7th Gen Core Processor Gaussian Mixture Model 5912 HD Graphics 630 @@ -28822,6 +30003,7 @@ 5926 Iris Plus Graphics 640 5927 Iris Plus Graphics 650 5a84 Celeron N3350/Pentium N4200/Atom E3900 Series Integrated Graphics Controller + 5a85 HD Graphics 500 5a88 Celeron N3350/Pentium N4200/Atom E3900 Series Imaging Unit 5a98 Celeron N3350/Pentium N4200/Atom E3900 Series Audio Cluster 5a9a Celeron N3350/Pentium N4200/Atom E3900 Series Trusted Execution Engine @@ -28951,6 +30133,7 @@ 6f52 Xeon Processor D Family QuickData Technology Register DMA Channel 2 6f53 Xeon Processor D Family QuickData Technology Register DMA Channel 3 6f54 Xeon Processor D Family QuickAssist Technology + 6f55 Xeon Processor D Family QuickAssist Technology Virtual Fuction 6f60 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Home Agent 1 6f68 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Target Address/Thermal/RAS 6f6a Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Channel Target Address Decoder @@ -29128,6 +30311,7 @@ 71a1 440GX - 82443GX AGP bridge 71a2 440GX - 82443GX Host bridge (AGP disabled) 4c53 1000 CC7/CR7/CP7/VC7/VP7/VR7 mainboard + 7360 XMM7360 LTE Advanced Modem 7600 82372FB PIIX5 ISA 7601 82372FB PIIX5 IDE 7602 82372FB PIIX5 USB @@ -29208,6 +30392,14 @@ 8817 Platform Controller Hub EG20T I2C Controller 8818 Platform Controller Hub EG20T Controller Area Network (CAN) Controller 8819 Platform Controller Hub EG20T IEEE 1588 Hardware Assist + 8a0d Ice Lake Thunderbolt 3 NHI #1 + 8a13 Ice Lake Thunderbolt 3 USB Controller + 8a17 Ice Lake Thunderbolt 3 NHI #0 + 8a1d Ice Lake Thunderbolt 3 PCI Express Root Port #0 + 8a1f Ice Lake Thunderbolt 3 PCI Express Root Port #1 + 8a21 Ice Lake Thunderbolt 3 PCI Express Root Port #2 + 8a23 Ice Lake Thunderbolt 3 PCI Express Root Port #3 + 8a52 Iris Plus Graphics G7 8c00 8 Series/C220 Series Chipset Family 4-port SATA Controller 1 [IDE mode] 8c01 8 Series Chipset Family 4-port SATA Controller 1 [IDE mode] - Mobile 8c02 8 Series/C220 Series Chipset Family 6-port SATA Controller 1 [AHCI mode] @@ -29425,6 +30617,7 @@ 9622 Integrated RAID 9641 Integrated RAID 96a1 Integrated RAID + 9b41 UHD Graphics 9c00 8 Series SATA Controller 1 [IDE mode] 9c01 8 Series SATA Controller 1 [IDE mode] 9c02 8 Series SATA Controller 1 [AHCI mode] @@ -29533,10 +30726,13 @@ 9d03 Sunrise Point-LP SATA Controller [AHCI mode] 1028 06dc Latitude E7470 1028 06f3 Latitude 3570 + 103c 8079 EliteBook 840 G3 17aa 225d ThinkPad T480 17aa 382a B51-80 Laptop 9d10 Sunrise Point-LP PCI Express Root Port #1 + 9d11 Sunrise Point-LP PCI Express Root Port #2 9d12 Sunrise Point-LP PCI Express Root Port #3 + 9d13 Sunrise Point-LP PCI Express Root Port #4 9d14 Sunrise Point-LP PCI Express Root Port #5 17aa 382a B51-80 Laptop 9d15 Sunrise Point-LP PCI Express Root Port #6 @@ -29546,15 +30742,18 @@ 9d18 Sunrise Point-LP PCI Express Root Port #9 17aa 382a B51-80 Laptop 9d19 Sunrise Point-LP PCI Express Root Port #10 + 9d1a Sunrise Point-LP PCI Express Root Port #11 9d21 Sunrise Point-LP PMC 1028 06dc Latitude E7470 1028 06f3 Latitude 3570 + 103c 8079 EliteBook 840 G3 17aa 224f ThinkPad X1 Carbon 5th Gen 17aa 225d ThinkPad T480 17aa 382a B51-80 Laptop 9d23 Sunrise Point-LP SMBus 1028 06dc Latitude E7470 1028 06f3 Latitude 3570 + 103c 8079 EliteBook 840 G3 17aa 2247 ThinkPad T570 17aa 224f ThinkPad X1 Carbon 5th Gen 17aa 225d ThinkPad T480 @@ -29567,12 +30766,14 @@ 9d2f Sunrise Point-LP USB 3.0 xHCI Controller 1028 06dc Latitude E7470 1028 06f3 Latitude 3570 + 103c 8079 EliteBook 840 G3 17aa 2247 ThinkPad T570 17aa 225d ThinkPad T480 17aa 382a B51-80 Laptop 9d31 Sunrise Point-LP Thermal subsystem 1028 06dc Latitude E7470 1028 06f3 Latitude 3570 + 103c 8079 EliteBook 840 G3 17aa 2247 ThinkPad T570 17aa 224f ThinkPad X1 Carbon 5th Gen 17aa 225d ThinkPad T480 @@ -29581,23 +30782,29 @@ 9d3a Sunrise Point-LP CSME HECI #1 1028 06dc Latitude E7470 1028 06f3 Latitude 3570 + 103c 8079 EliteBook 840 G3 17aa 2247 ThinkPad T570 17aa 224f ThinkPad X1 Carbon 5th Gen 17aa 225d ThinkPad T480 17aa 382a B51-80 Laptop + 9d3d Sunrise Point-LP Active Management Technology - SOL + 103c 8079 EliteBook 840 G3 9d43 Sunrise Point-LP LPC Controller 17aa 382a B51-80 Laptop 9d48 Sunrise Point-LP LPC Controller 1028 06dc Latitude E7470 1028 06f3 Latitude 3570 - 9d4e Intel(R) 100 Series Chipset Family LPC Controller/eSPI Controller - 9D4E + 103c 8079 EliteBook 840 G3 + 9d4e Sunrise Point LPC Controller/eSPI Controller 17aa 225d ThinkPad T480 + 9d50 Sunrise Point LPC Controller 9d56 Sunrise Point-LP LPC Controller 9d58 Sunrise Point-LP LPC Controller 17aa 2247 ThinkPad T570 17aa 224f ThinkPad X1 Carbon 5th Gen 9d60 Sunrise Point-LP Serial IO I2C Controller #0 1028 06f3 Latitude 3570 + 103c 8079 EliteBook 840 G3 17aa 225d ThinkPad T480 8086 9d60 100 Series PCH/Sunrise Point PCH I2C0 [Skylake/Kaby Lake LPSS I2C] 9d61 Sunrise Point-LP Serial IO I2C Controller #1 @@ -29609,9 +30816,41 @@ 9d70 Sunrise Point-LP HD Audio 1028 06dc Latitude E7470 1028 06f3 Latitude 3570 + 103c 8079 EliteBook 840 G3 17aa 382a B51-80 Laptop 9d71 Sunrise Point-LP HD Audio + 17aa 224f ThinkPad X1 Carbon 5th Gen 17aa 225d ThinkPad T480 + 9d84 Cannon Point-LP LPC Controller + 1028 089e Inspiron 5482 + 9da3 Cannon Point-LP SMBus Controller + 9da4 Cannon Point-LP SPI Controller + 9db0 Cannon Point-LP PCI Express Root Port #9 + 9db1 Cannon Point-LP PCI Express Root Port #10 + 9db2 Cannon Point-LP PCI Express Root Port #1 + 9db4 Cannon Point-LP PCI Express Root Port #13 + 1028 089e Inspiron 5482 + 9db6 Cannon Point-LP PCI Express Root Port #15 + 9db8 Cannon Point-LP PCI Express Root Port #1 + 9dbc Cannon Point-LP PCI Express Root Port #5 + 9dbe Cannon Point-LP PCI Express Root Port #7 + 9dbf Cannon Point PCI Express Root Port #8 + 9dc5 Cannon Point-LP Serial IO I2C Host Controller + 9dc8 Cannon Point-LP High Definition Audio Controller + 1028 089e Inspiron 5482 + 9dd3 Cannon Point-LP SATA Controller [AHCI Mode] + 9de0 Cannon Point-LP MEI Controller #1 + 9de3 Cannon Point-LP Keyboard and Text (KT) Redirection + 9de8 Cannon Point-LP Serial IO I2C Controller #0 + 1028 089e Inspiron 5482 + 9de9 Cannon Point-LP Serial IO I2C Controller #1 + 1028 089e Inspiron 5482 + 9ded Cannon Point-LP USB 3.1 xHCI Controller + 9def Cannon Point-LP Shared SRAM + 9df0 Cannon Point-LP CNVi [Wireless-AC] + 9df5 BayHubTech Integrated SD controller + 9df9 Cannon Point-LP Thermal Controller + 9dfc Cannon Point-LP Integrated Sensor Hub a000 Atom Processor D4xx/D5xx/N4xx/N5xx DMI Bridge 1458 5000 GA-D525TUD 8086 4f4d DeskTop Board D510MO @@ -29726,6 +30965,7 @@ a169 100 Series/C230 Series Chipset Family PCI Express Root Port #19 a16a 100 Series/C230 Series Chipset Family PCI Express Root Port #20 a170 100 Series/C230 Series Chipset Family HD Audio Controller + 1028 06e4 XPS 15 9550 a171 CM238 HD Audio Controller a182 C620 Series Chipset Family SATA Controller [AHCI mode] a186 C620 Series Chipset Family SATA Controller [RAID mode] @@ -29850,8 +31090,13 @@ a2ee 200 Series PCH PCI Express Root Port #24 a2f0 200 Series PCH HD Audio a304 H370 Chipset LPC/eSPI Controller + a305 Z390 Chipset LPC/eSPI Controller + a306 Q370 Chipset LPC/eSPI Controller + a309 Cannon Point-LP LPC Controller + a30c QM370 Chipset LPC/eSPI Controller a323 Cannon Lake PCH SMBus Controller a324 Cannon Lake PCH SPI Controller + a328 Cannon Lake PCH Serial IO UART Host Controller a32c Cannon Lake PCH PCI Express Root Port #21 a32d Cannon Lake PCH PCI Express Root Port #22 a32e Cannon Lake PCH PCI Express Root Port #23 @@ -29878,7 +31123,14 @@ a343 Cannon Lake PCH PCI Express Root Port #20 a348 Cannon Lake PCH cAVS a352 Cannon Lake PCH SATA AHCI Controller + a353 Cannon Lake Mobile PCH SATA AHCI Controller a360 Cannon Lake PCH HECI Controller + a363 Cannon Lake PCH Active Management Technology - SOL + a364 Cannon Lake PCH HECI Controller #2 + a368 Cannon Lake PCH Serial IO I2C Controller #0 + a369 Cannon Lake PCH Serial IO I2C Controller #1 + a36a Cannon Lake PCH Serial IO I2C Controller #2 + a36b Cannon Lake PCH Serial IO I2C Controller #3 a36d Cannon Lake PCH USB 3.1 xHCI Host Controller a36f Cannon Lake PCH Shared SRAM a370 Wireless-AC 9560 [Jefferson Peak] @@ -29923,6 +31175,29 @@ d158 Core Processor Miscellaneous Registers f1a5 SSD 600P Series f1a6 SSD Pro 7600p/760p/E 6100p Series + f1a8 SSD 660P Series +8088 Beijing Wangxun Technology Co., Ltd. + 0101 WX1860A2 Gigabit Ethernet Controller + 8088 0201 Dual-Port Ethernet Network Adaptor SF200T + 0102 WX1860A2S Gigabit Ethernet Controller + 8088 0210 Dual-Port Ethernet Network Adaptor SF200T-S + 0103 WX1860A4 Gigabit Ethernet Controller + 8088 0401 Qual-Port Ethernet Network Adaptor SF400T + 8088 0440 Qual-Port Ethernet Network Adaptor SF400-OCP + 0104 WX1860A4S Gigabit Ethernet Controller + 8088 0410 Qual-Port Ethernet Network Adaptor SF400T-S + 0105 WX1860AL2 Gigabit Ethernet Controller + 8088 0202 Dual-Port Ethernet Network Adaptor SF200HT + 0106 WX1860AL2S Gigabit Ethernet Controller + 8088 0220 Dual-Port Ethernet Network Adaptor SF200HT-S + 0107 WX1860AL4 Gigabit Ethernet Controller + 8088 0402 Qual-Port Ethernet Network Adaptor SF400HT + 0108 WX1860AL4S Gigabit Ethernet Controller + 8088 0420 Qual-Port Ethernet Network Adaptor SF400HT-S + 1001 Ethernet Controller RP1000 for 10GbE SFP+ + 8088 0000 Ethernet Network Adaptor RP1000 for 10GbE SFP+ + 2001 Ethernet Controller RP2000 for 10GbE SFP+ + 8088 2000 Ethernet Network Adaptor RP2000 for 10GbE SFP+ 80ee InnoTek Systemberatung GmbH beef VirtualBox Graphics Adapter cafe VirtualBox Guest Service @@ -30053,7 +31328,7 @@ 9004 7888 AHA-2930UW SCSI Controller 8b78 ABA-1030 ec78 AHA-4944W/UW -# Acquired by Microsemi +# Acquired by Microchip Technology 9005 Adaptec 0010 AHA-2940U2/U2W 9005 2180 AHA-2940U2 SCSI Controller @@ -30265,11 +31540,34 @@ 103c 0701 Smart Array P204i-b SR Gen10 103c 1100 Smart Array P816i-a SR Gen10 103c 1101 Smart Array P416ie-m SR G10 + 105b 1211 HBA 8238-16i + 105b 1321 HBA 8242-24i + 13fe 8312 SKY-9200 MIC-8312BridgeB 152d 8a22 QS-8204-8i 152d 8a23 QS-8238-16i 152d 8a24 QS-8236-16i 152d 8a36 QS-8240-24i 152d 8a37 QS-8242-24i + 193d 8460 HBA H460-M1 + 193d 8461 HBA H460-B1 + 193d c460 RAID P460-M2 + 193d c461 RAID P460-B2 + 193d f460 RAID P460-M4 + 193d f461 RAID P460-B4 + 19e5 d227 SmartROC-HD SR465C-M 4G + 19e5 d228 SmartROC SR455C-M 2G + 19e5 d229 SmartIOC SR155-M + 19e5 d22a SmartIOC-HD SR765-M + 19e5 d22b SmartROC-e SR455C-ME 4G + 19e5 d22c SmartROC SR455C-M 4G + 1bd4 0045 SMART-HBA 8242-24i + 1bd4 0046 RAID 8236-16i + 1bd4 0047 RAID 8240-24i + 1bd4 0048 SMART-HBA 8238-16i + 1bd4 004a PM8222-SHBA + 1bd4 004b RAID PM8204-2GB + 1bd4 004c RAID PM8204-4GB + 1bd4 004f PM8222-HBA 9005 0608 SmartRAID 3162-8i /e 9005 0800 SmartRAID 3154-8i 9005 0801 SmartRAID 3152-8i @@ -30496,11 +31794,14 @@ bdbd Blackmagic Design a144 DeckLink Mini Monitor 4K a148 DeckLink SDI Micro a14b DeckLink 8K Pro + a14e DeckLink Quad HDMI Recorder a1ff eGPU RX580 c001 TSI Telsys c0a9 Micron/Crucial Technology + 2263 P1 NVMe PCIe SSD c0de Motorola c0fe Motion Engineering, Inc. +ca3b Cambrionix Ltd. ca50 Varian Australia Pty Ltd cace CACE Technologies, Inc. 0001 TurboCap Port A @@ -30510,6 +31811,8 @@ caed Canny Edge cafe Chrysalis-ITS 0003 Luna K3 Hardware Security Module 0006 Luna PCI-e 3000 Hardware Security Module + 0007 Luna K6 Hardware Security Module + 0008 Luna K7 Hardware Security Module cc53 ScaleFlux Inc. cccc Catapult Communications ccec Curtiss-Wright Controls Embedded Computing @@ -30721,17 +32024,44 @@ edd8 ARK Logic Inc # Found on M2N68-AM Motherboard f043 ASUSTeK Computer Inc. (Wrong ID) f05b Foxconn International, Inc. (Wrong ID) +f15e SiFive, Inc. f1d0 AJA Video c0fe Xena HS/HD-R c0ff Kona/Xena 2 cafe Kona SD cfee Xena LS/SD-22-DA/SD-DA + dafe Corvid 1 daff KONA LHi + db00 IoExpress db01 Corvid22 + db02 Kona 3G + db03 Corvid 3G + db04 Kona 3G QUAD + db05 Kona LHe+ + db06 IoXT + db07 Kona 3G P2P + db08 Kona 3G QUAD P2P db09 Corvid 24 + db11 T-Tap dcaf Kona HD dfee Xena HD-DA + eb07 Io4K + eb0a Io4K UFC + eb0b Kona 4 + eb0c Kona 4 UFC + eb0d Corvid 88 eb0e Corvid 44 + eb16 Corvid HEVC + 10cf 1049 Corvid HEVC M31 + eb18 Corvid HB-R + eb1a Kona IP 1SFP + eb1c Kona IP 2SFP + eb1d Io4KPlus + eb1e IoIP + eb1f Kona 5 + eb23 Kona 1 + eb24 Kona HDMI + eb25 Corvid 44 12g efac Xena SD-MM/SD-22-MM facd Xena HD-MM f5f5 F5 Networks, Inc. @@ -30957,6 +32287,8 @@ C 11 Signal processing controller 80 Signal processing controller C 12 Processing accelerators 00 Processing accelerators +# For the class of PCI attached devices which perform a function of Deep Learning Neural Network inference acceleration + 01 AI Inference Accelerator C 13 Non-Essential Instrumentation C 40 Coprocessor C ff Unassigned class diff --git a/system/base/pciutils/pspec.xml b/system/base/pciutils/pspec.xml index 4d7a2211..c30749ec 100644 --- a/system/base/pciutils/pspec.xml +++ b/system/base/pciutils/pspec.xml @@ -62,6 +62,13 @@ + + 2019-12-26 + 3.6.2 + Rebuild + Idris Kalp + idriskalp@gmail.com + 2018-11-21 3.6.2 From 6f2bf6062178bae4220e9003a4edb5fa2497a14a Mon Sep 17 00:00:00 2001 From: idriskalp Date: Thu, 26 Dec 2019 19:16:24 +0300 Subject: [PATCH 082/160] biosdevname rebuild --- system/base/biosdevname/pspec.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/system/base/biosdevname/pspec.xml b/system/base/biosdevname/pspec.xml index 44f82db6..9d700a28 100644 --- a/system/base/biosdevname/pspec.xml +++ b/system/base/biosdevname/pspec.xml @@ -15,7 +15,7 @@ Biosdevname is a udev helper utility developed by Dell and released under the GNU General Public License (GPL). It provides a consistent naming mechanism for network devices based on their physical location as suggested by the system BIOS. http://linux.dell.com/biosdevname/biosdevname-0.7.2/biosdevname-0.7.2.tar.gz - pciutils-devel + pciutils-devel glibc-devel zlib-devel @@ -36,6 +36,13 @@ + + 2019-12-26 + 0.7.2 + Rebuild + Idris Kalp + idriskalp@gmail.com + 2018-07-15 0.7.2 From 2fe12213f27a18fec39a18c1f6f776e3327d2b23 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Thu, 26 Dec 2019 19:16:45 +0300 Subject: [PATCH 083/160] asciidoc rebuild --- office/docbook/asciidoc/pspec.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/office/docbook/asciidoc/pspec.xml b/office/docbook/asciidoc/pspec.xml index 0082d1a1..6d63449a 100644 --- a/office/docbook/asciidoc/pspec.xml +++ b/office/docbook/asciidoc/pspec.xml @@ -36,6 +36,13 @@ + + 2019-12-25 + 8.6.9 + Rebuild + Pisi Linux Community + admin@pisilinux.org + 2018-07-25 8.6.9 From 2ecd731710ec042e76d7ee29dda8e4c96066f8c8 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Thu, 26 Dec 2019 19:17:10 +0300 Subject: [PATCH 084/160] lvm2 --- hardware/disk/lvm2/actions.py | 0 hardware/disk/lvm2/comar/package.py | 0 hardware/disk/lvm2/files/lvm2-2.02.105-pthread-pkgconfig.patch | 0 .../disk/lvm2/files/lvm2-2.02.106-static-pkgconfig-libs.patch | 0 .../disk/lvm2/files/lvm2-2.02.63-always-make-static-libdm.patch | 0 .../disk/lvm2/files/lvm2-2.02.92-dynamic-static-ldflags.patch | 0 hardware/disk/lvm2/files/tmpfiles.conf | 0 hardware/disk/lvm2/pspec.xml | 0 hardware/disk/lvm2/translations.xml | 0 9 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 hardware/disk/lvm2/actions.py mode change 100644 => 100755 hardware/disk/lvm2/comar/package.py mode change 100644 => 100755 hardware/disk/lvm2/files/lvm2-2.02.105-pthread-pkgconfig.patch mode change 100644 => 100755 hardware/disk/lvm2/files/lvm2-2.02.106-static-pkgconfig-libs.patch mode change 100644 => 100755 hardware/disk/lvm2/files/lvm2-2.02.63-always-make-static-libdm.patch mode change 100644 => 100755 hardware/disk/lvm2/files/lvm2-2.02.92-dynamic-static-ldflags.patch mode change 100644 => 100755 hardware/disk/lvm2/files/tmpfiles.conf mode change 100644 => 100755 hardware/disk/lvm2/pspec.xml mode change 100644 => 100755 hardware/disk/lvm2/translations.xml diff --git a/hardware/disk/lvm2/actions.py b/hardware/disk/lvm2/actions.py old mode 100644 new mode 100755 diff --git a/hardware/disk/lvm2/comar/package.py b/hardware/disk/lvm2/comar/package.py old mode 100644 new mode 100755 diff --git a/hardware/disk/lvm2/files/lvm2-2.02.105-pthread-pkgconfig.patch b/hardware/disk/lvm2/files/lvm2-2.02.105-pthread-pkgconfig.patch old mode 100644 new mode 100755 diff --git a/hardware/disk/lvm2/files/lvm2-2.02.106-static-pkgconfig-libs.patch b/hardware/disk/lvm2/files/lvm2-2.02.106-static-pkgconfig-libs.patch old mode 100644 new mode 100755 diff --git a/hardware/disk/lvm2/files/lvm2-2.02.63-always-make-static-libdm.patch b/hardware/disk/lvm2/files/lvm2-2.02.63-always-make-static-libdm.patch old mode 100644 new mode 100755 diff --git a/hardware/disk/lvm2/files/lvm2-2.02.92-dynamic-static-ldflags.patch b/hardware/disk/lvm2/files/lvm2-2.02.92-dynamic-static-ldflags.patch old mode 100644 new mode 100755 diff --git a/hardware/disk/lvm2/files/tmpfiles.conf b/hardware/disk/lvm2/files/tmpfiles.conf old mode 100644 new mode 100755 diff --git a/hardware/disk/lvm2/pspec.xml b/hardware/disk/lvm2/pspec.xml old mode 100644 new mode 100755 diff --git a/hardware/disk/lvm2/translations.xml b/hardware/disk/lvm2/translations.xml old mode 100644 new mode 100755 From 45d029a702d634ed470b06d4eb7bc0de7a4f4127 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Thu, 26 Dec 2019 19:45:54 +0300 Subject: [PATCH 085/160] spidermonkey 60.9.0 --- system/base/spidermonkey/actions.py | 42 ++++-- .../base/spidermonkey/files/bug1415202.patch | 127 ++++++++++++++++++ .../files/mozjs60-fix-soname.patch | 25 ++++ system/base/spidermonkey/pspec.xml | 11 +- 4 files changed, 196 insertions(+), 9 deletions(-) create mode 100644 system/base/spidermonkey/files/bug1415202.patch create mode 100644 system/base/spidermonkey/files/mozjs60-fix-soname.patch diff --git a/system/base/spidermonkey/actions.py b/system/base/spidermonkey/actions.py index ef420a00..501446b4 100644 --- a/system/base/spidermonkey/actions.py +++ b/system/base/spidermonkey/actions.py @@ -11,29 +11,55 @@ from pisi.actionsapi import shelltools #WorkDir = "mozjs%s/js/src" % get.srcVERSION() shelltools.export("SHELL","/bin/sh") +WorkDir = "firefox-%s" %get.srcVERSION() def setup(): - shelltools.cd("js/src") + #shelltools.cd("js/src") #shelltools.system("sed -i 's/(defined\((@TEMPLATE_FILE)\))/\1/' config/milestone.pl ") + shelltools.system("mkdir -p build-js") + shelltools.cd("build-js") - - autotools.configure("--prefix=/usr \ - --enable-readline \ - --enable-threadsafe \ - --with-system-nspr") + shelltools.system("../js/src/configure \ + --prefix=/usr \ + --libdir=/usr/lib \ + --enable-readline \ + --enable-posix-nspr-emulation \ + --with-intl-api \ + --disable-debug \ + --disable-debug-symbols \ + --disable-jemalloc \ + --disable-strip \ + --enable-hardening \ + --enable-linker=gold \ + --enable-optimize \ + --enable-readline \ + --enable-release \ + --enable-shared-js \ + --enable-tests \ + --with-intl-api \ + --with-system-zlib \ + --without-system-icu") def build(): - shelltools.cd("js/src") + shelltools.cd("build-js") autotools.make() + +def check(): + shelltools.cd("build-js") + + autotools.make("-C js/src check-jstests check-jit-test") + def install(): - shelltools.cd("js/src") + shelltools.cd("build-js") autotools.rawInstall("DESTDIR=%s" % get.installDIR()) + pisitools.remove("/usr/lib/*.ajs") #for polkit #pisitools.rename("/usr/lib/pkgconfig/mozjs-..pc", "mozjs-17.0.pc") #pisitools.remove("usr/lib/libmozjs-..a") + shelltools.cd("..") pisitools.dodoc("README*") # add link for polkit diff --git a/system/base/spidermonkey/files/bug1415202.patch b/system/base/spidermonkey/files/bug1415202.patch new file mode 100644 index 00000000..e23fa856 --- /dev/null +++ b/system/base/spidermonkey/files/bug1415202.patch @@ -0,0 +1,127 @@ +# HG changeset patch +# User André Bargull +# Date 1510140221 28800 +# Wed Nov 08 03:23:41 2017 -0800 +# Node ID 8bf5e7460a7c5ba3430b501d1659c469a862a929 +# Parent 60fd4a5b01ec70ded9ddfd560fd5be191b1c74b9 +Bug 1415202: Always use the equivalent year to determine the time zone offset and name. r=Waldo + +diff --git a/js/src/jsdate.cpp b/js/src/jsdate.cpp +--- a/js/src/jsdate.cpp ++++ b/js/src/jsdate.cpp +@@ -2348,22 +2348,26 @@ static PRMJTime ToPRMJTime(double localT + prtm.tm_isdst = (DaylightSavingTA(utcTime) != 0); + + return prtm; + } + + static size_t FormatTime(char* buf, int buflen, const char* fmt, double utcTime, + double localTime) { + PRMJTime prtm = ToPRMJTime(localTime, utcTime); +- int eqivalentYear = IsRepresentableAsTime32(utcTime) ++ ++ // If an equivalent year was used to compute the date/time components, use ++ // the same equivalent year to determine the time zone name and offset in ++ // PRMJ_FormatTime(...). ++ int timeZoneYear = IsRepresentableAsTime32(utcTime) + ? prtm.tm_year + : EquivalentYearForDST(prtm.tm_year); + int offsetInSeconds = (int)floor((localTime - utcTime) / msPerSecond); + +- return PRMJ_FormatTime(buf, buflen, fmt, &prtm, eqivalentYear, ++ return PRMJ_FormatTime(buf, buflen, fmt, &prtm, timeZoneYear, + offsetInSeconds); + } + + enum class FormatSpec { DateTime, Date, Time }; + + static bool FormatDate(JSContext* cx, double utcTime, FormatSpec format, + MutableHandleValue rval) { + JSString* str; +diff --git a/js/src/vm/Time.cpp b/js/src/vm/Time.cpp +--- a/js/src/vm/Time.cpp ++++ b/js/src/vm/Time.cpp +@@ -242,17 +242,17 @@ static void PRMJ_InvalidParameterHandler + const wchar_t* file, unsigned int line, + uintptr_t pReserved) { + /* empty */ + } + #endif + + /* Format a time value into a buffer. Same semantics as strftime() */ + size_t PRMJ_FormatTime(char* buf, int buflen, const char* fmt, +- const PRMJTime* prtm, int equivalentYear, ++ const PRMJTime* prtm, int timeZoneYear, + int offsetInSeconds) { + size_t result = 0; + #if defined(XP_UNIX) || defined(XP_WIN) + struct tm a; + #ifdef XP_WIN + _invalid_parameter_handler oldHandler; + #ifndef __MINGW32__ + int oldReportMode; +@@ -275,39 +275,33 @@ size_t PRMJ_FormatTime(char* buf, int bu + */ + #if defined(HAVE_LOCALTIME_R) && defined(HAVE_TM_ZONE_TM_GMTOFF) + char emptyTimeZoneId[] = ""; + { + /* + * Fill out |td| to the time represented by |prtm|, leaving the + * timezone fields zeroed out. localtime_r will then fill in the + * timezone fields for that local time according to the system's +- * timezone parameters. ++ * timezone parameters. Use |timeZoneYear| for the year to ensure the ++ * time zone name matches the time zone offset used by the caller. + */ + struct tm td; + memset(&td, 0, sizeof(td)); + td.tm_sec = prtm->tm_sec; + td.tm_min = prtm->tm_min; + td.tm_hour = prtm->tm_hour; + td.tm_mday = prtm->tm_mday; + td.tm_mon = prtm->tm_mon; + td.tm_wday = prtm->tm_wday; +- td.tm_year = prtm->tm_year - 1900; ++ td.tm_year = timeZoneYear - 1900; + td.tm_yday = prtm->tm_yday; + td.tm_isdst = prtm->tm_isdst; + + time_t t = mktime(&td); + +- // If |prtm| cannot be represented in |time_t| the year is probably +- // out of range, try again with the DST equivalent year. +- if (t == static_cast(-1)) { +- td.tm_year = equivalentYear - 1900; +- t = mktime(&td); +- } +- + // If either mktime or localtime_r failed, fill in the fallback time + // zone offset |offsetInSeconds| and set the time zone identifier to + // the empty string. + if (t != static_cast(-1) && localtime_r(&t, &td)) { + a.tm_gmtoff = td.tm_gmtoff; + a.tm_zone = td.tm_zone; + } else { + a.tm_gmtoff = offsetInSeconds; +diff --git a/js/src/vm/Time.h b/js/src/vm/Time.h +--- a/js/src/vm/Time.h ++++ b/js/src/vm/Time.h +@@ -44,17 +44,17 @@ inline void PRMJ_NowInit() {} + #ifdef XP_WIN + extern void PRMJ_NowShutdown(); + #else + inline void PRMJ_NowShutdown() {} + #endif + + /* Format a time value into a buffer. Same semantics as strftime() */ + extern size_t PRMJ_FormatTime(char* buf, int buflen, const char* fmt, +- const PRMJTime* tm, int equivalentYear, ++ const PRMJTime* tm, int timeZoneYear, + int offsetInSeconds); + + /** + * Requesting the number of cycles from the CPU. + * + * `rdtsc`, or Read TimeStamp Cycle, is an instruction provided by + * x86-compatible CPUs that lets processes request the number of + * cycles spent by the CPU executing instructions since the CPU was diff --git a/system/base/spidermonkey/files/mozjs60-fix-soname.patch b/system/base/spidermonkey/files/mozjs60-fix-soname.patch new file mode 100644 index 00000000..cd661c35 --- /dev/null +++ b/system/base/spidermonkey/files/mozjs60-fix-soname.patch @@ -0,0 +1,25 @@ +diff --git i/js/src/build/Makefile.in w/js/src/build/Makefile.in +index ee19104e0ef5..a0f06fd35a18 100644 +--- i/js/src/build/Makefile.in ++++ w/js/src/build/Makefile.in +@@ -89,6 +89,8 @@ ifneq (,$(REAL_LIBRARY)) + endif + ifneq (,$(SHARED_LIBRARY)) + $(SYSINSTALL) $(SHARED_LIBRARY) $(DESTDIR)$(libdir) ++ mv -f $(DESTDIR)$(libdir)/$(SHARED_LIBRARY) $(DESTDIR)$(libdir)/$(SHARED_LIBRARY).0 ++ ln -s $(SHARED_LIBRARY).0 $(DESTDIR)$(libdir)/$(SHARED_LIBRARY) + ifeq ($(OS_ARCH),Darwin) + install_name_tool -id $(abspath $(libdir)/$(SHARED_LIBRARY)) $(DESTDIR)$(libdir)/$(SHARED_LIBRARY) + endif +diff --git i/js/src/build/moz.build w/js/src/build/moz.build +index a7f5fa4ce8eb..726687c13fb0 100644 +--- i/js/src/build/moz.build ++++ w/js/src/build/moz.build +@@ -23,6 +23,7 @@ if not CONFIG['JS_STANDALONE']: + if CONFIG['JS_SHARED_LIBRARY']: + GeckoSharedLibrary('js', linkage=None) + SHARED_LIBRARY_NAME = CONFIG['JS_LIBRARY_NAME'] ++ LDFLAGS += ['-Wl,-soname,lib{}.so.0'.format(SHARED_LIBRARY_NAME)] + else: + Library('js') + diff --git a/system/base/spidermonkey/pspec.xml b/system/base/spidermonkey/pspec.xml index a198ccc0..601ff194 100644 --- a/system/base/spidermonkey/pspec.xml +++ b/system/base/spidermonkey/pspec.xml @@ -12,7 +12,7 @@ library Stand-alone JavaScript C Library Spidermonkey is Mozilla's C implementation of JavaScript. - http://ftp.gnome.org/pub/gnome/teams/releng/tarballs-needing-help/mozjs/mozjs-52.2.1gnome1.tar.gz + https://ftp.mozilla.org/pub/firefox/releases/60.9.0esr/source/firefox-60.9.0esr.source.tar.xz zlib-devel nspr-devel @@ -21,6 +21,8 @@ autoconf213 + bug1415202.patch + mozjs60-fix-soname.patch @@ -55,6 +57,13 @@ + + 2019-10-03 + 60.9.0 + Version bump. + Idris Kalp + idriskalp@gmail.com + 2018-07-23 52.2.1 From 9b806772a08e5b21f8e74292bc8a7224ad04cac5 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Thu, 26 Dec 2019 22:45:43 +0300 Subject: [PATCH 086/160] polkit 0.116 --- system/base/polkit/pspec.xml | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/system/base/polkit/pspec.xml b/system/base/polkit/pspec.xml index 79d96a7c..58f2eae2 100644 --- a/system/base/polkit/pspec.xml +++ b/system/base/polkit/pspec.xml @@ -14,13 +14,13 @@ app:console PolicyKit Authorization Framework polkit is a toolkit for defining and handling authorizations. It is used for allowing unprivileged processes to speak to privileged processes. - http://www.freedesktop.org/software/polkit/releases/polkit-0.115.tar.gz + http://www.freedesktop.org/software/polkit/releases/polkit-0.116.tar.gz dbus-devel pam-devel glib2-devel expat-devel - spidermonkey-devel + spidermonkey-devel gobject-introspection-devel intltool @@ -51,7 +51,7 @@ glib2 libgcc expat - spidermonkey + spidermonkey /etc @@ -85,6 +85,13 @@ + + 2019-12-26 + 0.116 + Version bump + idris Kalp + idriskalp@gmail.com + 2018-10-31 0.115 From c0c6ac9aa40698430cabd71ffa898e407950efb9 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Thu, 26 Dec 2019 22:46:02 +0300 Subject: [PATCH 087/160] pypolkit rebuild --- system/base/pypolkit/pspec.xml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/system/base/pypolkit/pspec.xml b/system/base/pypolkit/pspec.xml index f37ba1ca..64ff2834 100644 --- a/system/base/pypolkit/pspec.xml +++ b/system/base/pypolkit/pspec.xml @@ -12,11 +12,11 @@ library Python binding of PolicyKit pypolkit is a Python binding for the PolicyKit library. - http://source.pisilinux.org/1.0/pypolkit-1.0.2.tar.gz + https://sourceforge.net/projects/pisilinux/files/source/pypolkit-1.0.2.tar.gz glib2-devel python-devel - polkit-devel + polkit-devel @@ -34,6 +34,13 @@ + + 2019-12-26 + 1.0.2 + Rebuild + Idris Kalp + idriskalp@gmail.com + 2018-07-22 1.0.2 From 1899dc49fa6399cd1c71c65261f87ce8242ce385 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Thu, 26 Dec 2019 22:47:36 +0300 Subject: [PATCH 088/160] comar rebuild --- system/base/comar/pspec.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/system/base/comar/pspec.xml b/system/base/comar/pspec.xml index 62ae3dac..03ccb804 100644 --- a/system/base/comar/pspec.xml +++ b/system/base/comar/pspec.xml @@ -48,6 +48,13 @@ + + 2019-12-26 + 3.0.3 + Rebuild + Idris Kalp + idriskalp@gmail.com + 2018-07-20 3.0.3 From fec5713bf200bf0b62bed47b8eb2a1331ebe6470 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 12:41:46 +0300 Subject: [PATCH 089/160] libaio 0.3.112 and move to core --- system/base/libaio/actions.py | 37 ++++++++ .../libaio/files/92_unused_warnings.patch | 44 +++++++++ .../libaio/files/libaio-0.3.106-build.patch | 26 ++++++ .../files/libaio-0.3.107-ar-ranlib.patch | 17 ++++ .../files/libaio-0.3.109-generic-arch.patch | 62 +++++++++++++ .../files/libaio-0.3.109-testcase-8.patch | 19 ++++ .../libaio-0.3.109-unify-bits-endian.patch | 60 +++++++++++++ .../libaio/files/libaio-0.3.109-x32.patch | 63 +++++++++++++ .../files/libaio-install-to-slash.patch | 30 +++++++ system/base/libaio/pspec.xml | 90 +++++++++++++++++++ system/base/libaio/translations.xml | 14 +++ 11 files changed, 462 insertions(+) create mode 100755 system/base/libaio/actions.py create mode 100755 system/base/libaio/files/92_unused_warnings.patch create mode 100755 system/base/libaio/files/libaio-0.3.106-build.patch create mode 100755 system/base/libaio/files/libaio-0.3.107-ar-ranlib.patch create mode 100755 system/base/libaio/files/libaio-0.3.109-generic-arch.patch create mode 100755 system/base/libaio/files/libaio-0.3.109-testcase-8.patch create mode 100755 system/base/libaio/files/libaio-0.3.109-unify-bits-endian.patch create mode 100755 system/base/libaio/files/libaio-0.3.109-x32.patch create mode 100755 system/base/libaio/files/libaio-install-to-slash.patch create mode 100755 system/base/libaio/pspec.xml create mode 100755 system/base/libaio/translations.xml diff --git a/system/base/libaio/actions.py b/system/base/libaio/actions.py new file mode 100755 index 00000000..ff4b83d7 --- /dev/null +++ b/system/base/libaio/actions.py @@ -0,0 +1,37 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# +# Licensed under the GNU General Public License, version 3. +# See the file http://www.gnu.org/licenses/gpl.txt + +from pisi.actionsapi import get +from pisi.actionsapi import autotools +from pisi.actionsapi import pisitools + +def build(): + pisitools.dosed("src/Makefile", "=-shared", r"= -Wl,-O1,--as-needed -shared") + if get.buildTYPE() == "emul32": + pisitools.dosed(".", "\/lib$", r"/lib%s\n" % "32" if get.buildTYPE() == "emul32" else "", filePattern="Makefile") + autotools.make() + +#def check(): + #shelltools.cd("harness") + #pisitools.dodir("testdir") + + #autotools.make("check prefix=../src libdir=../src") + + +def install(): + + if get.buildTYPE() == "emul32": + autotools.rawInstall("prefix=%s/usr \ + includedir=%s/usr/include \ + libdir%s/=usr/lib32 " % ((get.installDIR(), ) * 3)) + pisitools.remove("/usr/lib32/libaio.a") + else: + autotools.rawInstall("prefix=%s/usr \ + includedir=%s/usr/include \ + libdir%s/=usr/lib " % ((get.installDIR(), ) * 3)) + #pisitools.remove("/usr/lib/libaio.a") + + pisitools.dodoc("ChangeLog", "COPYING", "TODO") diff --git a/system/base/libaio/files/92_unused_warnings.patch b/system/base/libaio/files/92_unused_warnings.patch new file mode 100755 index 00000000..d3b22ab9 --- /dev/null +++ b/system/base/libaio/files/92_unused_warnings.patch @@ -0,0 +1,44 @@ +Index: b/harness/cases/12.t +=================================================================== +--- a/harness/cases/12.t ++++ b/harness/cases/12.t +@@ -18,7 +18,7 @@ + + int test_main(void) + { +- int res, status; ++ int status; + pid_t pid; + sigset_t set; + +@@ -35,7 +35,7 @@ + if (pid == 0) + test_child(); + +- res = waitpid(pid, &status, 0); ++ waitpid(pid, &status, 0); + + if (WIFEXITED(status)) { + int failed = (WEXITSTATUS(status) != 0); +Index: b/harness/cases/14.t +=================================================================== +--- a/harness/cases/14.t ++++ b/harness/cases/14.t +@@ -59,7 +59,7 @@ + /* from 12.t */ + int test_main(void) + { +- int res, status; ++ int status; + pid_t pid; + sigset_t set; + +@@ -75,7 +75,7 @@ + if (pid == 0) + test_child(); + +- res = waitpid(pid, &status, 0); ++ waitpid(pid, &status, 0); + + if (WIFEXITED(status)) { + int failed = (WEXITSTATUS(status) != 0); \ No newline at end of file diff --git a/system/base/libaio/files/libaio-0.3.106-build.patch b/system/base/libaio/files/libaio-0.3.106-build.patch new file mode 100755 index 00000000..4a8434bb --- /dev/null +++ b/system/base/libaio/files/libaio-0.3.106-build.patch @@ -0,0 +1,26 @@ +--- src/Makefile.orig 2006-07-09 19:46:41.000000000 -0700 ++++ src/Makefile 2006-07-09 19:51:00.000000000 -0700 +@@ -2,11 +2,10 @@ + includedir=$(prefix)/include + libdir=$(prefix)/lib + +-ARCH := $(shell uname -m | sed -e s/i.86/i386/) +-CFLAGS := -nostdlib -nostartfiles -Wall -I. -g -fomit-frame-pointer -O2 -fPIC +-SO_CFLAGS=-shared $(CFLAGS) ++CFLAGS += -nostdlib -nostartfiles -Wall -I. -fPIC ++SO_CFLAGS=-shared $(CFLAGS) + L_CFLAGS=$(CFLAGS) +-LINK_FLAGS= ++LINK_FLAGS=-lgcc -lrt $(LDFLAGS) + + soname=libaio.so.1 + minor=0 +@@ -48,7 +47,7 @@ + ranlib libaio.a + + $(libname): $(libaio_sobjs) libaio.map +- $(CC) $(SO_CFLAGS) -Wl,--version-script=libaio.map -Wl,-soname=$(soname) -o $@ $(libaio_sobjs) $(LINK_FLAGS) ++ $(CC) $(SO_CFLAGS) -Wl,--version-script=libaio.map -Wl,-soname,$(soname) -o $@ $(libaio_sobjs) $(LINK_FLAGS) + + install: $(all_targets) + install -D -m 644 libaio.h $(includedir)/libaio.h diff --git a/system/base/libaio/files/libaio-0.3.107-ar-ranlib.patch b/system/base/libaio/files/libaio-0.3.107-ar-ranlib.patch new file mode 100755 index 00000000..d1ec1403 --- /dev/null +++ b/system/base/libaio/files/libaio-0.3.107-ar-ranlib.patch @@ -0,0 +1,17 @@ +--- a/src/Makefile ++++ b/src/Makefile +@@ -42,10 +42,12 @@ + $(CC) $(L_CFLAGS) -c -o $@ $< + + ++AR ?= ar ++RANLIB ?= ranlib + libaio.a: $(libaio_objs) + rm -f libaio.a +- ar r libaio.a $^ +- ranlib libaio.a ++ $(AR) r libaio.a $^ ++ $(RANLIB) libaio.a + + $(libname): $(libaio_sobjs) libaio.map + $(CC) $(SO_CFLAGS) -Wl,--version-script=libaio.map -Wl,-soname,$(soname) -o $@ $(libaio_sobjs) $(LINK_FLAGS) diff --git a/system/base/libaio/files/libaio-0.3.109-generic-arch.patch b/system/base/libaio/files/libaio-0.3.109-generic-arch.patch new file mode 100755 index 00000000..fea3aeee --- /dev/null +++ b/system/base/libaio/files/libaio-0.3.109-generic-arch.patch @@ -0,0 +1,62 @@ +From 5e96c73d5dfbdea8d0be82b7f3fc8d6735e5dfa7 Mon Sep 17 00:00:00 2001 +From: Mike Frysinger +Date: Sun, 17 Jan 2010 17:07:48 -0500 +Subject: [PATCH] add a generic syscall() fallback + +Signed-off-by: Mike Frysinger +--- + src/syscall-generic.h | 29 +++++++++++++++++++++++++++++ + src/syscall.h | 3 ++- + 2 files changed, 31 insertions(+), 1 deletions(-) + create mode 100644 src/syscall-generic.h + +diff --git a/src/syscall-generic.h b/src/syscall-generic.h +new file mode 100644 +index 0000000..24d7c7c +--- /dev/null ++++ b/src/syscall-generic.h +@@ -0,0 +1,29 @@ ++#include ++#include ++#include ++ ++#define _body_io_syscall(sname, args...) \ ++{ \ ++ int ret = syscall(__NR_##sname, ## args); \ ++ return ret < 0 ? -errno : ret; \ ++} ++ ++#define io_syscall1(type,fname,sname,type1,arg1) \ ++type fname(type1 arg1) \ ++_body_io_syscall(sname, (long)arg1) ++ ++#define io_syscall2(type,fname,sname,type1,arg1,type2,arg2) \ ++type fname(type1 arg1,type2 arg2) \ ++_body_io_syscall(sname, (long)arg1, (long)arg2) ++ ++#define io_syscall3(type,fname,sname,type1,arg1,type2,arg2,type3,arg3) \ ++type fname(type1 arg1,type2 arg2,type3 arg3) \ ++_body_io_syscall(sname, (long)arg1, (long)arg2, (long)arg3) ++ ++#define io_syscall4(type,fname,sname,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ ++type fname (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ ++_body_io_syscall(sname, (long)arg1, (long)arg2, (long)arg3, (long)arg4) ++ ++#define io_syscall5(type,fname,sname,type1,arg1,type2,arg2,type3,arg3,type4,arg4, type5,arg5) \ ++type fname (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \ ++_body_io_syscall(sname, (long)arg1, (long)arg2, (long)arg3, (long)arg4, (long)arg5) +diff --git a/src/syscall.h b/src/syscall.h +index 78becfe..d954af0 100644 +--- a/src/syscall.h ++++ b/src/syscall.h +@@ -25,5 +25,6 @@ + #elif defined(__arm__) + #include "syscall-arm.h" + #else +-#error "add syscall-arch.h" ++#warning "using generic syscall method" ++#include "syscall-generic.h" + #endif +-- +1.7.3.1 + diff --git a/system/base/libaio/files/libaio-0.3.109-testcase-8.patch b/system/base/libaio/files/libaio-0.3.109-testcase-8.patch new file mode 100755 index 00000000..de05421b --- /dev/null +++ b/system/base/libaio/files/libaio-0.3.109-testcase-8.patch @@ -0,0 +1,19 @@ +Do not ignore return value of ftruncate(): testcases are compiled with -Werror, +and ftruncate is declared with attribute warn_unused_result. +--- harness/cases/8.t.orig 2012-03-09 16:40:04.074168070 +0100 ++++ harness/cases/8.t 2012-03-09 16:40:57.777278646 +0100 +@@ -9,12 +9,13 @@ + { + long long min = 0, max = 9223372036854775807LL; + char c = 0; ++ int ret; + + while (max - min > 1) { + if (pwrite64(fd, &c, 1, (min + max) / 2) == -1) + max = (min + max) / 2; + else { +- ftruncate(fd, 0); ++ ret = ftruncate(fd, 0); assert(ret == 0); + min = (min + max) / 2; + } + } diff --git a/system/base/libaio/files/libaio-0.3.109-unify-bits-endian.patch b/system/base/libaio/files/libaio-0.3.109-unify-bits-endian.patch new file mode 100755 index 00000000..a94ea20b --- /dev/null +++ b/system/base/libaio/files/libaio-0.3.109-unify-bits-endian.patch @@ -0,0 +1,60 @@ +diff --git a/src/libaio.h b/src/libaio.h +index ffe8259..4a6c9fb 100644 +--- a/src/libaio.h ++++ b/src/libaio.h +@@ -49,40 +49,34 @@ typedef enum io_iocb_cmd { + IO_CMD_PWRITEV = 8, + } io_iocb_cmd_t; + +-#if defined(__i386__) /* little endian, 32 bits */ ++/* little endian, 32 bits */ ++#if defined(__i386__) || defined(__sh__) || defined(__bfin__) || \ ++ defined(__ARMEL__) || defined(__MIPSEL__) || defined(__cris__) + #define PADDED(x, y) x; unsigned y + #define PADDEDptr(x, y) x; unsigned y + #define PADDEDul(x, y) unsigned long x; unsigned y ++ ++/* little endian, 64 bits */ + #elif defined(__ia64__) || defined(__x86_64__) || defined(__alpha__) + #define PADDED(x, y) x, y + #define PADDEDptr(x, y) x + #define PADDEDul(x, y) unsigned long x +-#elif defined(__powerpc64__) /* big endian, 64 bits */ +-#define PADDED(x, y) unsigned y; x +-#define PADDEDptr(x,y) x +-#define PADDEDul(x, y) unsigned long x +-#elif defined(__PPC__) /* big endian, 32 bits */ +-#define PADDED(x, y) unsigned y; x +-#define PADDEDptr(x, y) unsigned y; x +-#define PADDEDul(x, y) unsigned y; unsigned long x +-#elif defined(__s390x__) /* big endian, 64 bits */ ++ ++/* big endian, 64 bits */ ++#elif defined(__powerpc64__) || defined(__s390x__) || \ ++ (defined(__sparc__) && defined(__arch64__)) + #define PADDED(x, y) unsigned y; x + #define PADDEDptr(x,y) x + #define PADDEDul(x, y) unsigned long x +-#elif defined(__s390__) /* big endian, 32 bits */ +-#define PADDED(x, y) unsigned y; x +-#define PADDEDptr(x, y) unsigned y; x +-#define PADDEDul(x, y) unsigned y; unsigned long x +-#elif defined(__arm__) +-# if defined (__ARMEB__) /* big endian, 32 bits */ ++ ++/* big endian, 32 bits */ ++#elif defined(__PPC__) || defined(__s390__) || defined(__ARMEB__) || \ ++ defined(__MIPSEB__) || defined(__sparc__) || defined(__m68k__) || \ ++ defined(__hppa__) || defined(__frv__) || defined(__avr32__) + #define PADDED(x, y) unsigned y; x + #define PADDEDptr(x, y) unsigned y; x + #define PADDEDul(x, y) unsigned y; unsigned long x +-# else /* little endian, 32 bits */ +-#define PADDED(x, y) x; unsigned y +-#define PADDEDptr(x, y) x; unsigned y +-#define PADDEDul(x, y) unsigned long x; unsigned y +-# endif ++ + #else + #error endian? + #endif \ No newline at end of file diff --git a/system/base/libaio/files/libaio-0.3.109-x32.patch b/system/base/libaio/files/libaio-0.3.109-x32.patch new file mode 100755 index 00000000..1d2c2a90 --- /dev/null +++ b/system/base/libaio/files/libaio-0.3.109-x32.patch @@ -0,0 +1,63 @@ +http://git.yoctoproject.org/cgit/cgit.cgi/poky/commit/?id=f5c071d93c9e6f57930bce56b1e4f009c160a826 + +Upstream-Status: Pending + +Properly load arguments 5 an 6 for x86-64 syscall +Use asm ("r10") and asm ("r8") to load arguments 5 an 6 for x86-64 +syscall so that it works with both x32 and x86-64. + +Received this patch from H.J. Lu + +Signed-Off-By: Nitin A Kamble +2011/12/02 + +--- libaio-0.3.109/src/syscall-x86_64.h.x32 2009-10-09 11:17:02.000000000 -0700 ++++ libaio-0.3.109/src/syscall-x86_64.h 2011-12-02 09:09:07.537603224 -0800 +@@ -1,8 +1,18 @@ ++#ifndef __NR_io_setup + #define __NR_io_setup 206 ++#endif ++#ifndef __NR_io_destroy + #define __NR_io_destroy 207 ++#endif ++#ifndef __NR_io_getevents + #define __NR_io_getevents 208 ++#endif ++#ifndef __NR_io_submit + #define __NR_io_submit 209 ++#endif ++#ifndef __NR_io_cancel + #define __NR_io_cancel 210 ++#endif + + #define __syscall_clobber "r11","rcx","memory" + #define __syscall "syscall" +@@ -42,10 +52,11 @@ return __res; \ + type fname (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ + { \ + long __res; \ +-__asm__ volatile ("movq %5,%%r10 ;" __syscall \ ++register long __a4 asm ("r10") = (long) arg4; \ ++__asm__ volatile (__syscall \ + : "=a" (__res) \ + : "0" (__NR_##sname),"D" ((long)(arg1)),"S" ((long)(arg2)), \ +- "d" ((long)(arg3)),"g" ((long)(arg4)) : __syscall_clobber,"r10" ); \ ++ "d" ((long)(arg3)),"r" (__a4)); \ + return __res; \ + } + +@@ -54,10 +65,11 @@ return __res; \ + type fname (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \ + { \ + long __res; \ +-__asm__ volatile ("movq %5,%%r10 ; movq %6,%%r8 ; " __syscall \ ++register long __a4 asm ("r10") = (long) arg4; \ ++register long __a5 asm ("r8") = (long) arg5; \ ++__asm__ volatile ( __syscall \ + : "=a" (__res) \ + : "0" (__NR_##sname),"D" ((long)(arg1)),"S" ((long)(arg2)), \ +- "d" ((long)(arg3)),"g" ((long)(arg4)),"g" ((long)(arg5)) : \ +- __syscall_clobber,"r8","r10" ); \ ++ "d" ((long)(arg3)),"r" (__a4),"r" (__a5)); \ + return __res; \ + } diff --git a/system/base/libaio/files/libaio-install-to-slash.patch b/system/base/libaio/files/libaio-install-to-slash.patch new file mode 100755 index 00000000..98fbfe0d --- /dev/null +++ b/system/base/libaio/files/libaio-install-to-slash.patch @@ -0,0 +1,30 @@ +diff -up libaio-0.3.107/src/Makefile.orig libaio-0.3.107/src/Makefile +--- libaio-0.3.107/src/Makefile.orig 2009-01-20 10:07:31.520105235 -0500 ++++ libaio-0.3.107/src/Makefile 2009-01-20 10:08:51.199104930 -0500 +@@ -1,6 +1,7 @@ + prefix=/usr +-includedir=$(prefix)/include +-libdir=$(prefix)/lib ++includedir=/usr/include ++libdir=/usr/lib ++usrlibdir=/usr/lib + + ARCH := $(shell uname -m | sed -e s/i.86/i386/) + CFLAGS := -nostdlib -nostartfiles -Wall -I. -g -fomit-frame-pointer -O2 -fPIC +@@ -51,11 +52,11 @@ $(libname): $(libaio_sobjs) libaio.map + $(CC) $(SO_CFLAGS) -Wl,--version-script=libaio.map -Wl,-soname=$(soname) -o $@ $(libaio_sobjs) $(LINK_FLAGS) + + install: $(all_targets) +- install -D -m 644 libaio.h $(includedir)/libaio.h +- install -D -m 644 libaio.a $(libdir)/libaio.a +- install -D -m 755 $(libname) $(libdir)/$(libname) +- ln -sf $(libname) $(libdir)/$(soname) +- ln -sf $(libname) $(libdir)/libaio.so ++ install -D -m 644 libaio.h $(destdir)$(includedir)/libaio.h ++ install -D -m 644 libaio.a $(destdir)$(usrlibdir)/libaio.a ++ install -D -m 755 $(libname) $(destdir)$(libdir)/$(libname) ++ ln -sf $(libdir)/$(libname) $(destdir)$(libdir)/$(soname) ++ ln -sf $(libdir)/$(libname) $(destdir)$(usrlibdir)/libaio.so + + $(libaio_objs): libaio.h + \ No newline at end of file diff --git a/system/base/libaio/pspec.xml b/system/base/libaio/pspec.xml new file mode 100755 index 00000000..7ea955b3 --- /dev/null +++ b/system/base/libaio/pspec.xml @@ -0,0 +1,90 @@ + + + + + libaio + http://lse.sourceforge.net/io/aio.html + + PisiLinux Community + admins@pisilinux.org + + LGPLv2.1 + library + Linux-native asynchronous I/O access library + libaio has a richer API and capability set than the simple POSIX async I/O facility. + http://ftp.de.debian.org/debian/pool/main/liba/libaio/libaio_0.3.112.orig.tar.xz + + + + libaio + + /lib + /usr/lib + /usr/share/doc + + + + + libaio-32bit + emul32 + 32-bit shared libraries for libaio + emul32 + + libaio + + + /usr/lib32 + + + + + libaio-devel + Development files for libaio + + libaio + + + /usr/include + + /usr/share/man/man3 + + + + + + 2019-12-26 + 0.3.112 + Version bump for new lvm2 + Kamil Atlı + suvari@pisilinux.org + + + 2018-08-06 + 0.3.110 + Rebuild. + Mustafa Cinasal + muscnsl@gmail.com + + + 2017-02-28 + 0.3.110 + Version Bump. + Ertuğrul Erata + ertugrulerata@gmail.com + + + 2016-06-09 + 0.3.109 + Release Bump + Pisi Linux Community + admin@pisilinux.org + + + 2014-05-19 + 0.3.109 + First release + Alihan Öztürk + alihan@pisilinux.org + + + \ No newline at end of file diff --git a/system/base/libaio/translations.xml b/system/base/libaio/translations.xml new file mode 100755 index 00000000..4b27c4a2 --- /dev/null +++ b/system/base/libaio/translations.xml @@ -0,0 +1,14 @@ + + + + libaio + Linux asenkron girdi/çıktı kütüphanesi + libaio, basit POSIX asenkron girdi/çıktı desteğinden daha iyi bir programlama arayüzü sunan bir kütüphanedir. + Librairie d'entrée/sortie asynchrone utilisant l'interface native du noyau. + + + + libaio-devel + libaio için geliştirme dosyaları + + From 4078ab723358e1e15d52b840a90fc71a5062dea3 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 12:42:41 +0300 Subject: [PATCH 090/160] lvm2 2.02.186 --- hardware/disk/lvm2/actions.py | 6 +- hardware/disk/lvm2/comar/package.py | 0 .../lvm2-2.02.105-pthread-pkgconfig.patch | 0 .../lvm2-2.02.106-static-pkgconfig-libs.patch | 0 .../lvm2-2.02.166-HPPA-no-O_DIRECT.patch | 12 +++ .../files/lvm2-2.02.171-static-libm.patch | 13 +++ .../lvm2-2.02.178-static-pkgconfig-libs.patch | 102 ++++++++++++++++++ ...-metadata-with-invalid-creation_time.patch | 72 +++++++++++++ .../lvm2/files/lvm2-2.02.184-mksh_build.patch | 13 +++ ...2.186-udev_remove_unsupported_option.patch | 34 ++++++ .../lvm2-2.02.56-lvm2create_initrd.patch | 72 +++++++++++++ ...vm2-2.02.63-always-make-static-libdm.patch | 0 .../files/lvm2-2.02.67-createinitrd.patch | 18 ++++ .../lvm2-2.02.92-dynamic-static-ldflags.patch | 0 .../lvm2/files/lvm2-2.02.99-locale-muck.patch | 11 ++ .../lvm2-2.03.05-dmeventd-no-idle-exit.patch | 81 ++++++++++++++ .../lvm2-2.03.05-dynamic-static-ldflags.patch | 75 +++++++++++++ .../lvm2-2.03.05-pthread-pkgconfig.patch | 48 +++++++++ hardware/disk/lvm2/files/tmpfiles.conf | 0 hardware/disk/lvm2/pspec.xml | 26 ++++- hardware/disk/lvm2/translations.xml | 0 21 files changed, 580 insertions(+), 3 deletions(-) mode change 100755 => 100644 hardware/disk/lvm2/actions.py mode change 100755 => 100644 hardware/disk/lvm2/comar/package.py mode change 100755 => 100644 hardware/disk/lvm2/files/lvm2-2.02.105-pthread-pkgconfig.patch mode change 100755 => 100644 hardware/disk/lvm2/files/lvm2-2.02.106-static-pkgconfig-libs.patch create mode 100644 hardware/disk/lvm2/files/lvm2-2.02.166-HPPA-no-O_DIRECT.patch create mode 100644 hardware/disk/lvm2/files/lvm2-2.02.171-static-libm.patch create mode 100644 hardware/disk/lvm2/files/lvm2-2.02.178-static-pkgconfig-libs.patch create mode 100644 hardware/disk/lvm2/files/lvm2-2.02.184-allow-reading-metadata-with-invalid-creation_time.patch create mode 100644 hardware/disk/lvm2/files/lvm2-2.02.184-mksh_build.patch create mode 100644 hardware/disk/lvm2/files/lvm2-2.02.186-udev_remove_unsupported_option.patch create mode 100644 hardware/disk/lvm2/files/lvm2-2.02.56-lvm2create_initrd.patch mode change 100755 => 100644 hardware/disk/lvm2/files/lvm2-2.02.63-always-make-static-libdm.patch create mode 100644 hardware/disk/lvm2/files/lvm2-2.02.67-createinitrd.patch mode change 100755 => 100644 hardware/disk/lvm2/files/lvm2-2.02.92-dynamic-static-ldflags.patch create mode 100644 hardware/disk/lvm2/files/lvm2-2.02.99-locale-muck.patch create mode 100644 hardware/disk/lvm2/files/lvm2-2.03.05-dmeventd-no-idle-exit.patch create mode 100644 hardware/disk/lvm2/files/lvm2-2.03.05-dynamic-static-ldflags.patch create mode 100644 hardware/disk/lvm2/files/lvm2-2.03.05-pthread-pkgconfig.patch mode change 100755 => 100644 hardware/disk/lvm2/files/tmpfiles.conf mode change 100755 => 100644 hardware/disk/lvm2/pspec.xml mode change 100755 => 100644 hardware/disk/lvm2/translations.xml diff --git a/hardware/disk/lvm2/actions.py b/hardware/disk/lvm2/actions.py old mode 100755 new mode 100644 index 632d7184..a835311a --- a/hardware/disk/lvm2/actions.py +++ b/hardware/disk/lvm2/actions.py @@ -60,10 +60,14 @@ def builddiet(): def setup(): # Breaks linking when sandbox is disabled - shelltools.export("CLDFLAGS", get.LDFLAGS()) + shelltools.export("CLDFLAGS", "%s -lpthread" %get.LDFLAGS()) shelltools.export("LIB_PTHREAD", "-lpthread") pisitools.dosed("conf/example.conf.in", "use_lvmetad = 0", "use_lvmetad = 1") + + #shelltools.system(""" sed -i -e "1iAR = $(tc-getAR)" -e "s:CC ?= @CC@:CC = $(tc-getCC):" make.tmpl.in || die """) + shelltools.system(""" sed -i -e '/FLAG/s:-O2::' configure || die """) + shelltools.system(""" sed -i -e '/FLAG/s:-O2::' configure.ac || die """) autotools.autoreconf("-fi") autotools.configure("--with-thin-check= \ diff --git a/hardware/disk/lvm2/comar/package.py b/hardware/disk/lvm2/comar/package.py old mode 100755 new mode 100644 diff --git a/hardware/disk/lvm2/files/lvm2-2.02.105-pthread-pkgconfig.patch b/hardware/disk/lvm2/files/lvm2-2.02.105-pthread-pkgconfig.patch old mode 100755 new mode 100644 diff --git a/hardware/disk/lvm2/files/lvm2-2.02.106-static-pkgconfig-libs.patch b/hardware/disk/lvm2/files/lvm2-2.02.106-static-pkgconfig-libs.patch old mode 100755 new mode 100644 diff --git a/hardware/disk/lvm2/files/lvm2-2.02.166-HPPA-no-O_DIRECT.patch b/hardware/disk/lvm2/files/lvm2-2.02.166-HPPA-no-O_DIRECT.patch new file mode 100644 index 00000000..0f830e42 --- /dev/null +++ b/hardware/disk/lvm2/files/lvm2-2.02.166-HPPA-no-O_DIRECT.patch @@ -0,0 +1,12 @@ +--- a/lib/device/dev-io.c ++++ b/lib/device/dev-io.c +@@ -505,7 +505,9 @@ + dev->flags |= DEV_NOT_O_NOATIME; + if ((dev->fd = open(name, flags, 0777)) >= 0) { + log_debug_devs("%s: Not using O_NOATIME", name); ++#ifdef O_DIRECT_SUPPORT + goto opened; ++#endif + } + } + #endif diff --git a/hardware/disk/lvm2/files/lvm2-2.02.171-static-libm.patch b/hardware/disk/lvm2/files/lvm2-2.02.171-static-libm.patch new file mode 100644 index 00000000..1cbf956d --- /dev/null +++ b/hardware/disk/lvm2/files/lvm2-2.02.171-static-libm.patch @@ -0,0 +1,13 @@ +diff --git a/make.tmpl.in b/make.tmpl.in +index a40eaaa15..7eea943aa 100644 +--- a/make.tmpl.in ++++ b/make.tmpl.in +@@ -53,7 +53,7 @@ PYCOMPILE = $(top_srcdir)/autoconf/py-compile + + LIBS = @LIBS@ + # Extra libraries always linked with static binaries +-STATIC_LIBS = $(SELINUX_STATIC_LIBS) $(UDEV_STATIC_LIBS) $(BLKID_STATIC_LIBS) ++STATIC_LIBS = $(SELINUX_STATIC_LIBS) $(UDEV_STATIC_LIBS) $(BLKID_STATIC_LIBS) $(M_LIBS) + DEFS += @DEFS@ + # FIXME set this only where it's needed, not globally? + CFLAGS ?= @COPTIMISE_FLAG@ @CFLAGS@ diff --git a/hardware/disk/lvm2/files/lvm2-2.02.178-static-pkgconfig-libs.patch b/hardware/disk/lvm2/files/lvm2-2.02.178-static-pkgconfig-libs.patch new file mode 100644 index 00000000..989b3082 --- /dev/null +++ b/hardware/disk/lvm2/files/lvm2-2.02.178-static-pkgconfig-libs.patch @@ -0,0 +1,102 @@ +--- LVM2.2.02.178/configure.ac ++++ LVM2.2.02.178/configure.ac +@@ -1238,6 +1238,7 @@ + PKG_CHECK_MODULES(BLKID, blkid >= 2.24, + [ BLKID_WIPING=yes + BLKID_PC="blkid" ++ BLKID_STATIC_LIBS=`$PKG_CONFIG --static --libs $BLKID_PC` + DEFAULT_USE_BLKID_WIPING=1 + AC_DEFINE([BLKID_WIPING_SUPPORT], 1, [Define to 1 to use libblkid detection of signatures when wiping.]) + ], [if test "$BLKID_WIPING" = maybe; then +@@ -1286,6 +1287,7 @@ + if test "$UDEV_SYNC" = yes; then + pkg_config_init + PKG_CHECK_MODULES(UDEV, libudev >= 143, [UDEV_PC="libudev"]) ++ UDEV_STATIC_LIBS=`$PKG_CONFIG --static --libs libudev` + AC_DEFINE([UDEV_SYNC_SUPPORT], 1, [Define to 1 to enable synchronisation with udev processing.]) + + AC_CHECK_LIB(udev, udev_device_get_is_initialized, AC_DEFINE([HAVE_LIBUDEV_UDEV_DEVICE_GET_IS_INITIALIZED], 1, +@@ -1564,19 +1566,32 @@ + if test "$SELINUX" = yes; then + AC_CHECK_LIB([sepol], [sepol_check_context], [ + AC_DEFINE([HAVE_SEPOL], 1, [Define to 1 if sepol_check_context is available.]) +- SELINUX_LIBS="-lsepol"]) ++ SEPOL_LIBS="-lsepol"]) ++ ++ dnl -- init pkgconfig if required ++ if test x$PKGCONFIG_INIT != x1; then ++ pkg_config_init ++ fi ++ PKG_CHECK_MODULES(SELINUX, libselinux, [ ++ SELINUX_PC="libselinux" ++ SELINUX_STATIC_LIBS=`$PKG_CONFIG --static --libs libselinux` ++ SELINUX_LIBS="$SELINUX_LIBS $SEPOL_LIBS" ++ AC_DEFINE([HAVE_SELINUX], 1, [Define to 1 to include support for selinux.]) ++ ],[ ++ dnl -- old non-pkgconfig method, is buggy with static builds + + AC_CHECK_LIB([selinux], [is_selinux_enabled], [ + AC_CHECK_HEADERS([selinux/selinux.h],, hard_bailout) + AC_CHECK_HEADERS([selinux/label.h]) + AC_DEFINE([HAVE_SELINUX], 1, [Define to 1 to include support for selinux.]) +- SELINUX_LIBS="-lselinux $SELINUX_LIBS" ++ SELINUX_LIBS="-lselinux $SEPOL_LIBS" + SELINUX_PC="libselinux" + HAVE_SELINUX=yes ], [ + AC_MSG_WARN(Disabling selinux) + SELINUX_LIBS= + SELINUX_PC= + HAVE_SELINUX=no ]) ++ ]) + fi + + ################################################################################ +@@ -1927,6 +1942,7 @@ + ################################################################################ + AC_SUBST(APPLIB) + AC_SUBST(AWK) ++AC_SUBST(BLKID_STATIC_LIBS) + AC_SUBST(BLKID_PC) + AC_SUBST(BUILD_CMIRRORD) + AC_SUBST(BUILD_DMEVENTD) +@@ -2037,6 +2053,7 @@ + AC_SUBST(SALCK_LIBS) + AC_SUBST(SBINDIR) + AC_SUBST(SELINUX_LIBS) ++AC_SUBST(SELINUX_STATIC_LIBS) + AC_SUBST(SELINUX_PC) + AC_SUBST(SYSCONFDIR) + AC_SUBST(SYSTEMD_LIBS) +@@ -2053,6 +2070,7 @@ + AC_SUBST(CACHE_DUMP_CMD) + AC_SUBST(CACHE_REPAIR_CMD) + AC_SUBST(CACHE_RESTORE_CMD) ++AC_SUBST(UDEV_STATIC_LIBS) + AC_SUBST(UDEV_PC) + AC_SUBST(UDEV_RULES) + AC_SUBST(UDEV_SYNC) +--- LVM2.2.02.178/make.tmpl.in ++++ LVM2.2.02.178/make.tmpl.in +@@ -59,7 +59,7 @@ + + LIBS = @LIBS@ + # Extra libraries always linked with static binaries +-STATIC_LIBS = $(SELINUX_LIBS) $(UDEV_LIBS) $(BLKID_LIBS) ++STATIC_LIBS = $(SELINUX_STATIC_LIBS) $(UDEV_STATIC_LIBS) $(BLKID_STATIC_LIBS) + DEFS += @DEFS@ + # FIXME set this only where it's needed, not globally? + CFLAGS ?= @COPTIMISE_FLAG@ @CFLAGS@ +@@ -75,10 +75,13 @@ + PTHREAD_LIBS = @PTHREAD_LIBS@ + READLINE_LIBS = @READLINE_LIBS@ + SELINUX_LIBS = @SELINUX_LIBS@ ++SELINUX_STATIC_LIBS = @SELINUX_STATIC_LIBS@ + UDEV_CFLAGS = @UDEV_CFLAGS@ + UDEV_LIBS = @UDEV_LIBS@ ++UDEV_STATIC_LIBS = @UDEV_STATIC_LIBS@ + BLKID_CFLAGS = @BLKID_CFLAGS@ + BLKID_LIBS = @BLKID_LIBS@ ++BLKID_STATIC_LIBS = @BLKID_STATIC_LIBS@ + SYSTEMD_LIBS = @SYSTEMD_LIBS@ + VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ + diff --git a/hardware/disk/lvm2/files/lvm2-2.02.184-allow-reading-metadata-with-invalid-creation_time.patch b/hardware/disk/lvm2/files/lvm2-2.02.184-allow-reading-metadata-with-invalid-creation_time.patch new file mode 100644 index 00000000..34968c7c --- /dev/null +++ b/hardware/disk/lvm2/files/lvm2-2.02.184-allow-reading-metadata-with-invalid-creation_time.patch @@ -0,0 +1,72 @@ +From a397b69ce33d811aba7d64d54b5c8e0efb86fd15 Mon Sep 17 00:00:00 2001 +From: Zdenek Kabelac +Date: Fri, 10 May 2019 14:40:11 +0200 +Subject: [PATCH] metadata: allow reading metadata with invalid creation_time + +lvm2 till version 2.02.169 (commit 78d004efa8a1809cea68283e6204edfa9d7c1091) +was printing invalid creation_time argument into metadata on 32bit arch. + +However with commit ba9820b14223b731125c83dbc9709aa44fdcdbf1 we started +to properly validate all input numbers and thus we refused to accept +invalid metadata with 'garbage' string - but this results in the +situation where metadata produced on older lvm2 on 32 bit architecture +will become unreadable after upgrade. + +To fix this case - extend libdm parser in a way, that whenever we +find error integer value, we also check if the parsed value is not for +creation_time node and in this case we let the metadata pass through +with made-up date 2018-05-24 (release date of 2.02.169). +--- + libdm/libdm-config.c | 18 +++++++++++++++--- + 1 file changed, 15 insertions(+), 3 deletions(-) + +diff --git a/libdm/libdm-config.c b/libdm/libdm-config.c +index 3f0d2510e..382f86bbf 100644 +--- a/libdm/libdm-config.c ++++ b/libdm/libdm-config.c +@@ -51,6 +51,8 @@ struct parser { + + struct dm_pool *mem; + int no_dup_node_check; /* whether to disable dup node checking */ ++ const char *key; /* last obtained key */ ++ unsigned ignored_creation_time; + }; + + struct config_output { +@@ -176,7 +178,7 @@ static int _do_dm_config_parse(struct dm_config_tree *cft, const char *start, co + /* TODO? if (start == end) return 1; */ + + struct parser *p; +- if (!(p = dm_pool_alloc(cft->mem, sizeof(*p)))) ++ if (!(p = dm_pool_zalloc(cft->mem, sizeof(*p)))) + return_0; + + p->mem = cft->mem; +@@ -615,6 +617,7 @@ static struct dm_config_node *_section(struct parser *p, struct dm_config_node * + match(TOK_SECTION_E); + } else { + match(TOK_EQ); ++ p->key = root->key; + if (!(value = _value(p))) + return_NULL; + if (root->v) +@@ -682,8 +685,17 @@ static struct dm_config_value *_type(struct parser *p) + errno = 0; + v->v.i = strtoll(p->tb, NULL, 0); /* FIXME: check error */ + if (errno) { +- log_error("Failed to read int token."); +- return NULL; ++ if (errno == ERANGE && p->key && ++ strcmp("creation_time", p->key) == 0) { ++ /* Due to a bug in some older 32bit builds (<2.02.169), ++ * lvm was able to produce invalid creation_time string */ ++ v->v.i = 1527120000; /* Pick 2018-05-24 day instead */ ++ if (!p->ignored_creation_time++) ++ log_warn("WARNING: Invalid creation_time found in metadata (repaired with next metadata update)."); ++ } else { ++ log_error("Failed to read int token."); ++ return NULL; ++ } + } + match(TOK_INT); + break; diff --git a/hardware/disk/lvm2/files/lvm2-2.02.184-mksh_build.patch b/hardware/disk/lvm2/files/lvm2-2.02.184-mksh_build.patch new file mode 100644 index 00000000..49c6853f --- /dev/null +++ b/hardware/disk/lvm2/files/lvm2-2.02.184-mksh_build.patch @@ -0,0 +1,13 @@ +https://bugs.gentoo.org/686652 + +--- LVM2.2.02.184/tools/Makefile.in ++++ LVM2.2.02.184/tools/Makefile.in +@@ -220,6 +220,6 @@ + echo "/* Do not edit. This file is generated by the Makefile. */" && \ + echo -en "const char _command_input[] =\n\n\"" && \ + $(EGREP) -v '^#|\-\-\-|^$$' $(srcdir)/command-lines.in | $(AWK) 'BEGIN {ORS = "\\n\"\n\""} //' && \ +- echo "\\n\";" \ ++ printf "%s\n" "\\n\";" \ + ) > $@ + + $(SOURCES:%.c=%.d) $(SOURCES2:%.c=%.d): command-lines-input.h command-count.h cmds.h diff --git a/hardware/disk/lvm2/files/lvm2-2.02.186-udev_remove_unsupported_option.patch b/hardware/disk/lvm2/files/lvm2-2.02.186-udev_remove_unsupported_option.patch new file mode 100644 index 00000000..f895e192 --- /dev/null +++ b/hardware/disk/lvm2/files/lvm2-2.02.186-udev_remove_unsupported_option.patch @@ -0,0 +1,34 @@ +From f98f79a047dd1c4980008e0ed6c9ad4e18596cdc Mon Sep 17 00:00:00 2001 +From: Peter Rajnoha +Date: Tue, 13 Aug 2019 15:18:30 +0200 +Subject: [PATCH] udev: remove unsupported OPTIONS+="event_timeout" rule + +The OPTIONS+="event_timeout" is Unsupported since systemd/udev version 216, +that is ~5 years ago. + +Since systemd/udev version 243, there's a new message printed if unsupported +OPTIONS value is used: + + Invalid value for OPTIONS key, ignoring: 'event_timeout=180' + +Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1740666 +--- + udev/11-dm-lvm.rules.in | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/udev/11-dm-lvm.rules.in b/udev/11-dm-lvm.rules.in +index 91cb991df9..7c589943b7 100644 +--- a/udev/11-dm-lvm.rules.in ++++ b/udev/11-dm-lvm.rules.in +@@ -37,8 +37,6 @@ ENV{DM_SUBSYSTEM_UDEV_FLAG0}!="1", ENV{DM_NOSCAN}=="1", ENV{DM_UDEV_DISABLE_OTHE + + ENV{DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG}=="1", GOTO="lvm_end" + +-OPTIONS+="event_timeout=180" +- + # Do not create symlinks for inappropriate subdevices. + ENV{DM_LV_NAME}=="pvmove?*|?*_vorigin", GOTO="lvm_disable" + ENV{DM_LV_LAYER}=="?*", GOTO="lvm_disable" +-- +2.24.0 + diff --git a/hardware/disk/lvm2/files/lvm2-2.02.56-lvm2create_initrd.patch b/hardware/disk/lvm2/files/lvm2-2.02.56-lvm2create_initrd.patch new file mode 100644 index 00000000..59aaa9b3 --- /dev/null +++ b/hardware/disk/lvm2/files/lvm2-2.02.56-lvm2create_initrd.patch @@ -0,0 +1,72 @@ +--- LVM2.2.02.56/scripts/lvm2create_initrd/lvm2create_initrd.orig 2006-11-21 22:41:56.000000000 +0000 ++++ LVM2.2.02.56/scripts/lvm2create_initrd/lvm2create_initrd 2009-12-26 01:47:08.025224602 +0000 +@@ -54,7 +54,9 @@ + DEVRAM=/tmp/initrd.$$ + + # set defaults +-BINFILES=${BINFILES:-"`which lvm` `which bash` `which busybox` `which pivot_root`"} ++LVM=`which lvm.static` ++LVM=${LVM:-"`which lvm`"} ++BINFILES=${BINFILES:-"${LVM} `which bash` `which busybox` `which pivot_root`"} + BASICDEVICES=${BASICDEVICES:-"std consoleonly fd"} + BLOCKDEVICES=${BLOCKDEVICES:-"md hda hdb hdc hdd sda sdb sdc sdd"} + MAKEDEV=${MAKEDEV:-"debian"} +@@ -119,6 +121,10 @@ + echo "$PRE Mounting /proc" + mount -t proc none /proc + ++# We need /sys for lvm ++echo "$PRE Mounting /sys" ++mount -t sysfs sysfs /sys ++ + # plug in modules listed in /etc/modules + if [ -f /etc/modules ]; then + echo -n "$PRE plugging in kernel modules:" +@@ -179,26 +185,29 @@ + # run a shell if we're passed lvm2rescue on commandline + grep lvm2rescue /proc/cmdline 1>/dev/null 2>&1 + if [ $? -eq 0 ]; then +- lvm vgchange --ignorelockingfailure -P -a y ++ $LVM vgchange --ignorelockingfailure -P -a y + do_shell + else +- lvm vgchange --ignorelockingfailure -a y ++ $LVM vgchange --ignorelockingfailure -a y + fi + + echo "$PRE Mounting root filesystem $rootvol ro" + mkdir /rootvol + if ! mount -t auto -o ro $rootvol /rootvol; then +- echo "\t*FAILED*"; ++ echo "\t*FAILED TRYING TO MOUNT ROOTVOL*"; + do_shell + fi + + echo "$PRE Umounting /proc" + umount /proc + ++echo "$PRE Umounting /sys" ++umount /sys ++ + echo "$PRE Changing roots" + cd /rootvol + if ! pivot_root . initrd ; then +- echo "\t*FAILED*" ++ echo "\t*FAILED PIVOT TO NEW ROOT*" + do_shell + fi + +@@ -356,7 +365,7 @@ + fi + + verbose "creating basic set of directories in $TMPMNT" +-(cd $TMPMNT; mkdir bin dev etc lib proc sbin var) ++(cd $TMPMNT; mkdir bin dev etc lib proc sbin sys var) + if [ $? -ne 0 ]; then + echo "$cmd -- ERROR creating directories in $TMPMNT" + cleanup 1 +@@ -499,4 +508,3 @@ + FINALTXT + + cleanup 0 +- diff --git a/hardware/disk/lvm2/files/lvm2-2.02.63-always-make-static-libdm.patch b/hardware/disk/lvm2/files/lvm2-2.02.63-always-make-static-libdm.patch old mode 100755 new mode 100644 diff --git a/hardware/disk/lvm2/files/lvm2-2.02.67-createinitrd.patch b/hardware/disk/lvm2/files/lvm2-2.02.67-createinitrd.patch new file mode 100644 index 00000000..7f0bfb89 --- /dev/null +++ b/hardware/disk/lvm2/files/lvm2-2.02.67-createinitrd.patch @@ -0,0 +1,18 @@ +X-Gentoo-Bug-URL: http://bugs.gentoo.org/show_bug.cgi?id=301331 +X-Gentoo-Bug: 301331 + +diff -Nuar LVM2.2.02.67.orig/scripts/lvm2create_initrd/lvm2create_initrd LVM2.2.02.67/scripts/lvm2create_initrd/lvm2create_initrd +--- LVM2.2.02.67.orig/scripts/lvm2create_initrd/lvm2create_initrd 2010-06-07 18:44:34.182980475 +0000 ++++ LVM2.2.02.67/scripts/lvm2create_initrd/lvm2create_initrd 2010-06-07 18:51:27.636312899 +0000 +@@ -469,9 +469,9 @@ + rmdir $TMPMNT/lost+found + + echo "$cmd -- ummounting ram disk" +-umount $DEVRAM ++umount $TMPMNT + if [ $? -ne 0 ]; then +- echo "$cmd -- ERROR umounting $DEVRAM" ++ echo "$cmd -- ERROR umounting $TMPMNT" + cleanup 1 + fi + diff --git a/hardware/disk/lvm2/files/lvm2-2.02.92-dynamic-static-ldflags.patch b/hardware/disk/lvm2/files/lvm2-2.02.92-dynamic-static-ldflags.patch old mode 100755 new mode 100644 diff --git a/hardware/disk/lvm2/files/lvm2-2.02.99-locale-muck.patch b/hardware/disk/lvm2/files/lvm2-2.02.99-locale-muck.patch new file mode 100644 index 00000000..fe7ec879 --- /dev/null +++ b/hardware/disk/lvm2/files/lvm2-2.02.99-locale-muck.patch @@ -0,0 +1,11 @@ +--- LVM2/make.tmpl.in ++++ LVM2/make.tmpl.in +@@ -395,7 +395,7 @@ + ( cat $(srcdir)/.exported_symbols; \ + if test x$(EXPORTED_HEADER) != x; then \ + $(CC) -E -P $(INCLUDES) $(DEFS) $(EXPORTED_HEADER) | \ +- $(SED) -ne "/^typedef|}/!s/.*[ *]\($(EXPORTED_FN_PREFIX)_[a-z0-9_]*\)(.*/\1/p"; \ ++ LC_ALL=C $(SED) -ne "/^typedef|}/!s/.*[ *]\($(EXPORTED_FN_PREFIX)_[a-z0-9_]*\)(.*/\1/p"; \ + fi \ + ) > $@ + diff --git a/hardware/disk/lvm2/files/lvm2-2.03.05-dmeventd-no-idle-exit.patch b/hardware/disk/lvm2/files/lvm2-2.03.05-dmeventd-no-idle-exit.patch new file mode 100644 index 00000000..ec37e5da --- /dev/null +++ b/hardware/disk/lvm2/files/lvm2-2.03.05-dmeventd-no-idle-exit.patch @@ -0,0 +1,81 @@ +From ab3ae0a22dfbe20e2d17e7dc60e0f76184ec098c Mon Sep 17 00:00:00 2001 +From: "Robin H. Johnson" +Date: Wed, 24 Jul 2019 11:22:32 +0200 +Subject: [PATCH] dmeventd configurable idle exit time + +dmeventd nominally exits after 1 hour of idle time. There are use cases for +this, esp. with socket activation, but also cases where users don't expect +dmeventd to exit. + +Provide a tuning knob via environment variable, DMEVENTD_IDLE_EXIT_TIMEOUT, +that can be -1 to not exit, or a configurable time for different idle exit. + +Signed-off-by: Robin H. Johnson +Fixes: https://bugs.gentoo.org/682556 + +Forward-ported from 2.02.184 to 2.03.05 +Signed-off-by: Lars Wendler +--- + daemons/dmeventd/dmeventd.c | 16 ++++++++++++++-- + man/dmeventd.8_main | 4 ++++ + 2 files changed, 18 insertions(+), 2 deletions(-) + +diff --git a/daemons/dmeventd/dmeventd.c b/daemons/dmeventd/dmeventd.c +index 33859ef414..ac0b9743fc 100644 +--- a/daemons/dmeventd/dmeventd.c ++++ b/daemons/dmeventd/dmeventd.c +@@ -2158,6 +2158,18 @@ int main(int argc, char *argv[]) + .server_path = DM_EVENT_FIFO_SERVER + }; + time_t now, idle_exit_timeout = DMEVENTD_IDLE_EXIT_TIMEOUT; ++ ++ /* Provide a basic way to config the idle timeout */ ++ char* idle_exit_timeout_env = getenv("DMEVENTD_IDLE_EXIT_TIMEOUT") ? : NULL; ++ if(NULL != idle_exit_timeout_env) { ++ char* endptr; ++ idle_exit_timeout = strtol(idle_exit_timeout_env, &endptr, 10); ++ if (errno == ERANGE || *endptr != '\0') { ++ fprintf(stderr, "DMEVENTD_IDLE_EXIT_TIMEOUT: bad time input\n"); ++ exit(EXIT_FAILURE); ++ } ++ } ++ + opterr = 0; + optind = 0; + +@@ -2253,7 +2265,7 @@ int main(int argc, char *argv[]) + _process_initial_registrations(); + + for (;;) { +- if (_idle_since) { ++ if (_idle_since || _exit_now) { + if (_exit_now) { + if (_exit_now == DM_SCHEDULED_EXIT) + break; /* Only prints shutdown message */ +@@ -2262,7 +2274,7 @@ int main(int argc, char *argv[]) + (long) (time(NULL) - _idle_since)); + break; + } +- if (idle_exit_timeout) { ++ if (idle_exit_timeout && idle_exit_timeout > 0) { + now = time(NULL); + if (now < _idle_since) + _idle_since = now; /* clock change? */ +diff --git a/man/dmeventd.8_main b/man/dmeventd.8_main +index dc4abf627e..4b0e522041 100644 +--- a/man/dmeventd.8_main ++++ b/man/dmeventd.8_main +@@ -178,6 +178,10 @@ is processed. + Variable is set by thin and vdo plugin to prohibit recursive interation + with dmeventd by any executed lvm2 command from + a thin_command, vdo_command environment. ++.TP ++.B DMEVENTD_IDLE_EXIT_TIMEOUT ++Configure the dmeventd idle exit timeout behavior, value in seconds. Default ++is 3600 (1 hour). -1 means do not exit. + . + .SH SEE ALSO + . +-- +2.22.0 + diff --git a/hardware/disk/lvm2/files/lvm2-2.03.05-dynamic-static-ldflags.patch b/hardware/disk/lvm2/files/lvm2-2.03.05-dynamic-static-ldflags.patch new file mode 100644 index 00000000..2b9a5dd9 --- /dev/null +++ b/hardware/disk/lvm2/files/lvm2-2.03.05-dynamic-static-ldflags.patch @@ -0,0 +1,75 @@ +From 93101699f5e1190184c00c99ab7b6e9717e5019a Mon Sep 17 00:00:00 2001 +From: "Robin H. Johnson" +Date: Wed, 24 Jul 2019 11:11:35 +0200 +Subject: [PATCH] Add dynamic static ldflags + +Forward-ported from 2.02.178 to 2.03.05 +Signed-off-by: Lars Wendler +--- + configure.ac | 2 ++ + daemons/dmeventd/Makefile.in | 2 +- + make.tmpl.in | 1 + + tools/Makefile.in | 2 +- + 4 files changed, 5 insertions(+), 2 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 1e45c0edcb..cc2625294a 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -33,6 +33,7 @@ case "$host_os" in + CLDFLAGS="${CLDFLAGS:"$LDFLAGS"} -Wl,--version-script,.export.sym" + # equivalent to -rdynamic + ELDFLAGS="-Wl,--export-dynamic" ++ STATIC_LDFLAGS="-Wl,--no-export-dynamic" + # FIXME Generate list and use --dynamic-list=.dlopen.sym + CLDWHOLEARCHIVE="-Wl,-whole-archive" + CLDNOWHOLEARCHIVE="-Wl,-no-whole-archive" +@@ -1758,6 +1759,7 @@ AC_SUBST(SYSCONFDIR) + AC_SUBST(SYSTEMD_LIBS) + AC_SUBST(SNAPSHOTS) + AC_SUBST(STATICDIR) ++AC_SUBST(STATIC_LDFLAGS) + AC_SUBST(STATIC_LINK) + AC_SUBST(TESTSUITE_DATA) + AC_SUBST(THIN) +diff --git a/daemons/dmeventd/Makefile.in b/daemons/dmeventd/Makefile.in +index 6bd36d0325..a3c30ec1a0 100644 +--- a/daemons/dmeventd/Makefile.in ++++ b/daemons/dmeventd/Makefile.in +@@ -66,7 +66,7 @@ dmeventd: $(LIB_SHARED) dmeventd.o + + dmeventd.static: $(LIB_STATIC) dmeventd.o + @echo " [CC] $@" +- $(Q) $(CC) $(CFLAGS) $(LDFLAGS) -static -L. -L$(interfacebuilddir) dmeventd.o \ ++ $(Q) $(CC) $(CFLAGS) $(LDFLAGS) $(STATIC_LDFLAGS) -static -L. -L$(interfacebuilddir) dmeventd.o \ + -o $@ $(DL_LIBS) $(DMEVENT_LIBS) $(LIBS) $(STATIC_LIBS) + + ifeq ("@PKGCONFIG@", "yes") +diff --git a/make.tmpl.in b/make.tmpl.in +index f3332e91c1..1489c2afad 100644 +--- a/make.tmpl.in ++++ b/make.tmpl.in +@@ -68,6 +68,7 @@ DEFS += @DEFS@ + # FIXME set this only where it's needed, not globally? + CFLAGS ?= @COPTIMISE_FLAG@ @CFLAGS@ + LDFLAGS ?= @LDFLAGS@ ++STATIC_LDFLAGS += @STATIC_LDFLAGS@ + CLDFLAGS += @CLDFLAGS@ + ELDFLAGS += @ELDFLAGS@ + LDDEPS += @LDDEPS@ +diff --git a/tools/Makefile.in b/tools/Makefile.in +index 2620daa17c..e5fc9c4ae4 100644 +--- a/tools/Makefile.in ++++ b/tools/Makefile.in +@@ -136,7 +136,7 @@ man-generator: man-generator.o + + lvm.static: $(OBJECTS) lvm-static.o $(LVMINTERNAL_LIBS) + @echo " [CC] $@" +- $(Q) $(CC) $(CFLAGS) $(LDFLAGS) -static -L$(interfacebuilddir) -o $@ $+ \ ++ $(Q) $(CC) $(CFLAGS) $(LDFLAGS) $(STATIC_LDFLAGS) -static -L$(interfacebuilddir) -o $@ $+ \ + $(DMEVENT_LIBS) $(STATIC_LIBS) $(LVMLIBS) + + liblvm2cmd.a: $(top_builddir)/lib/liblvm-internal.a $(OBJECTS) lvmcmdlib.o lvm2cmd.o +-- +2.22.0 + diff --git a/hardware/disk/lvm2/files/lvm2-2.03.05-pthread-pkgconfig.patch b/hardware/disk/lvm2/files/lvm2-2.03.05-pthread-pkgconfig.patch new file mode 100644 index 00000000..56aa2a7b --- /dev/null +++ b/hardware/disk/lvm2/files/lvm2-2.03.05-pthread-pkgconfig.patch @@ -0,0 +1,48 @@ +From dbb68df8d02eff87f10df331e17bd0940e158f56 Mon Sep 17 00:00:00 2001 +From: "Robin H. Johnson" +Date: Wed, 24 Jul 2019 11:15:59 +0200 +Subject: [PATCH] Add pthread to libdevmapper pkgconfig file + +Forward-ported from 2.02.176 to 2.03.05 +Signed-off-by: Lars Wendler +--- + libdm/libdevmapper.pc.in | 2 +- + tools/Makefile.in | 5 +++++ + 2 files changed, 6 insertions(+), 1 deletion(-) + +diff --git a/libdm/libdevmapper.pc.in b/libdm/libdevmapper.pc.in +index a325aeb9e0..aa0980378f 100644 +--- a/libdm/libdevmapper.pc.in ++++ b/libdm/libdevmapper.pc.in +@@ -9,4 +9,4 @@ Version: @DM_LIB_PATCHLEVEL@ + Cflags: -I${includedir} + Libs: -L${libdir} -ldevmapper + Requires.private: @SELINUX_PC@ @UDEV_PC@ +-Libs.private: -lm @RT_LIBS@ ++Libs.private: -lm @RT_LIBS@ @PTHREAD_LIBS@ +diff --git a/tools/Makefile.in b/tools/Makefile.in +index e5fc9c4ae4..12e4de2c63 100644 +--- a/tools/Makefile.in ++++ b/tools/Makefile.in +@@ -87,6 +87,7 @@ ifeq ("@STATIC_LINK@", "yes") + TARGETS += lvm.static + INSTALL_LVM_TARGETS += install_tools_static + INSTALL_CMDLIB_TARGETS += install_cmdlib_static ++ STATIC_LIBS += @PTHREAD_LIBS@ + endif + + LVMLIBS = $(SYSTEMD_LIBS) -L$(top_builddir)/libdm -ldevmapper $(LIBS) -laio +@@ -113,6 +114,10 @@ CFLOW_TARGET = lvm + + include $(top_builddir)/make.tmpl + ++ifeq ("@STATIC_LINK@", "yes") ++ STATIC_LIBS += @PTHREAD_LIBS@ ++endif ++ + device-mapper: + + all: device-mapper +-- +2.22.0 + diff --git a/hardware/disk/lvm2/files/tmpfiles.conf b/hardware/disk/lvm2/files/tmpfiles.conf old mode 100755 new mode 100644 diff --git a/hardware/disk/lvm2/pspec.xml b/hardware/disk/lvm2/pspec.xml old mode 100755 new mode 100644 index 84f016b5..3124ad32 --- a/hardware/disk/lvm2/pspec.xml +++ b/hardware/disk/lvm2/pspec.xml @@ -12,17 +12,29 @@ app:console Userland logical volume management tools LVM2 includes all of the support for handling read/write operations physical and logical volumes. - ftp://sources.redhat.com/pub/lvm2/LVM2.2.02.167.tgz + http://mirrors.kernel.org/sourceware/lvm2/LVM2.2.02.186.tgz libutil-linux-devel eudev-devel autoconf-archive + libaio-devel + + + + + lvm2-2.02.178-static-pkgconfig-libs.patch + lvm2-2.02.56-lvm2create_initrd.patch + lvm2-2.02.67-createinitrd.patch + lvm2-2.02.99-locale-muck.patch + lvm2-2.02.171-static-libm.patch + lvm2-2.02.166-HPPA-no-O_DIRECT.patch + lvm2-2.02.184-mksh_build.patch @@ -54,7 +66,7 @@ Device-mapper-devel contains files needed to develop applications that use the device-mapper libraries. device-mapper - eudev-devel + eudev-devel /usr/include/libdevmapper.h @@ -73,6 +85,9 @@ /usr/sbin/dmeventd /usr/lib/libdevmapper-event.a /usr/lib/libdevmapper-event.so* + + /usr/lib/libdevmapper-event-lvm2vdo.so + /usr/lib/device-mapper/libdevmapper-event-lvm2vdo.so /usr/lib/libdevmapper-event-lvm2thin.so /usr/lib/device-mapper/libdevmapper-event-lvm2thin.so /usr/share/man/man8/dmeventd.8 @@ -189,6 +204,13 @@ + + 2019-12-26 + 2.02.186 + Version bump + Kamil Atlı + suvarice@pisilinux.org + 2018-07-23 2.02.167 diff --git a/hardware/disk/lvm2/translations.xml b/hardware/disk/lvm2/translations.xml old mode 100755 new mode 100644 From 895bdcc61c2fda533ca93a867cd18797c6ba6de2 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 12:44:10 +0300 Subject: [PATCH 091/160] comar-api rebuild --- system/base/comar-api/pspec.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/system/base/comar-api/pspec.xml b/system/base/comar-api/pspec.xml index e75edb3a..49bb1ab4 100644 --- a/system/base/comar-api/pspec.xml +++ b/system/base/comar-api/pspec.xml @@ -36,6 +36,13 @@ + + 2019-12-27 + 2.4.9 + Rebuild + Idris Kalp + idriskalp@gmail.com + 2018-07-15 2.4.9 From 21194f661924e668186244a1dea12141cde1eb38 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 12:45:48 +0300 Subject: [PATCH 092/160] cpio rebuild --- .../cpio/files/cpio-2.12-CVE-2016-2037.patch | 42 +++++ .../cpio/files/cpio-2.12-name-overflow.patch | 15 ++ .../cpio-2.12-no-overwrite-symlinks.patch | 153 ++++++++++++++++++ .../files/cpio-2.12-non-gnu-compilers.patch | 11 ++ .../cpio/files/cpio-2.12-svr4compat.patch | 22 +++ system/base/cpio/pspec.xml | 13 ++ 6 files changed, 256 insertions(+) create mode 100644 system/base/cpio/files/cpio-2.12-CVE-2016-2037.patch create mode 100644 system/base/cpio/files/cpio-2.12-name-overflow.patch create mode 100644 system/base/cpio/files/cpio-2.12-no-overwrite-symlinks.patch create mode 100644 system/base/cpio/files/cpio-2.12-non-gnu-compilers.patch create mode 100644 system/base/cpio/files/cpio-2.12-svr4compat.patch diff --git a/system/base/cpio/files/cpio-2.12-CVE-2016-2037.patch b/system/base/cpio/files/cpio-2.12-CVE-2016-2037.patch new file mode 100644 index 00000000..3979d131 --- /dev/null +++ b/system/base/cpio/files/cpio-2.12-CVE-2016-2037.patch @@ -0,0 +1,42 @@ +Other calls to cpio_safer_name_suffix seem to be safe. + +* src/copyin.c (process_copy_in): Make sure that file_hdr.c_name +has at least two bytes allocated. +* src/util.c (cpio_safer_name_suffix): Document that use of this +function requires to be careful. +--- + src/copyin.c | 2 ++ + src/util.c | 5 ++++- + 2 files changed, 6 insertions(+), 1 deletion(-) + +diff --git a/src/copyin.c b/src/copyin.c +index cde911e..032d35f 100644 +--- a/src/copyin.c ++++ b/src/copyin.c +@@ -1430,6 +1430,8 @@ process_copy_in () + break; + } + ++ if (file_hdr.c_namesize <= 1) ++ file_hdr.c_name = xrealloc(file_hdr.c_name, 2); + cpio_safer_name_suffix (file_hdr.c_name, false, !no_abs_paths_flag, + false); + +diff --git a/src/util.c b/src/util.c +index 6ff6032..2763ac1 100644 +--- a/src/util.c ++++ b/src/util.c +@@ -1411,7 +1411,10 @@ set_file_times (int fd, + } + + /* Do we have to ignore absolute paths, and if so, does the filename +- have an absolute path? */ ++ have an absolute path? ++ Before calling this function make sure that the allocated NAME buffer has ++ capacity at least 2 bytes to allow us to store the "." string inside. */ ++ + void + cpio_safer_name_suffix (char *name, bool link_target, bool absolute_names, + bool strip_leading_dots) +-- +2.5.0 diff --git a/system/base/cpio/files/cpio-2.12-name-overflow.patch b/system/base/cpio/files/cpio-2.12-name-overflow.patch new file mode 100644 index 00000000..f8524688 --- /dev/null +++ b/system/base/cpio/files/cpio-2.12-name-overflow.patch @@ -0,0 +1,15 @@ +https://bugs.gentoo.org/572428 +https://lists.gnu.org/archive/html/bug-cpio/2016-01/msg00002.html +http://seclists.org/oss-sec/2016/q1/136 + +--- a/src/copyin.c ++++ b/src/copyin.c +@@ -1385,6 +1385,8 @@ + break; + } + ++ if (file_hdr.c_namesize <= 1) ++ file_hdr.c_name = xrealloc (file_hdr.c_name, 2); + cpio_safer_name_suffix (file_hdr.c_name, false, !no_abs_paths_flag, + false); + diff --git a/system/base/cpio/files/cpio-2.12-no-overwrite-symlinks.patch b/system/base/cpio/files/cpio-2.12-no-overwrite-symlinks.patch new file mode 100644 index 00000000..7f09a419 --- /dev/null +++ b/system/base/cpio/files/cpio-2.12-no-overwrite-symlinks.patch @@ -0,0 +1,153 @@ +Index: cpio-2.12/src/copyin.c +=================================================================== +--- cpio-2.12.orig/src/copyin.c 2015-09-12 12:57:30.000000000 +0200 ++++ cpio-2.12/src/copyin.c 2016-03-15 16:59:17.044993467 +0100 +@@ -695,6 +695,51 @@ + free (link_name); + } + ++ ++static int ++path_contains_symlink(char *path) ++{ ++ struct stat st; ++ char *slash; ++ char *nextslash; ++ ++ /* we got NULL pointer or empty string */ ++ if (!path || !*path) { ++ return false; ++ } ++ ++ slash = path; ++ ++ while ((nextslash = strchr(slash + 1, '/')) != NULL) { ++ slash = nextslash; ++ *slash = '\0'; ++ ++ if (lstat(path, &st) != 0) { ++ if (errno == ELOOP) { ++ /* ELOOP - too many symlinks */ ++ *slash = '/'; ++ return true; ++ } else if (errno == ENOMEM) { ++ /* No memory for lstat - terminate */ ++ xalloc_die(); ++ } else { ++ /* cannot lstat path - give up */ ++ *slash = '/'; ++ return false; ++ } ++ } ++ ++ if (S_ISLNK(st.st_mode)) { ++ *slash = '/'; ++ return true; ++ } ++ ++ *slash = '/'; ++ } ++ ++ return false; ++} ++ + static void + copyin_file (struct cpio_file_stat *file_hdr, int in_file_des) + { +@@ -1468,6 +1513,23 @@ + { + /* Copy the input file into the directory structure. */ + ++ /* Can we write files over symlinks? */ ++ if (!extract_over_symlinks) ++ { ++ if (path_contains_symlink(file_hdr.c_name)) ++ { ++ /* skip the file */ ++ /* ++ fprintf(stderr, "Can't write over symlinks. Skipping %s\n", file_hdr.c_name); ++ tape_toss_input (in_file_des, file_hdr.c_filesize); ++ tape_skip_padding (in_file_des, file_hdr.c_filesize); ++ continue; ++ */ ++ /* terminate */ ++ error (1, 0, _("Can't write over symlinks: %s\n"), file_hdr.c_name); ++ } ++ } ++ + /* Do we need to rename the file? */ + if (rename_flag || rename_batch_file) + { +Index: cpio-2.12/src/global.c +=================================================================== +--- cpio-2.12.orig/src/global.c 2015-09-12 12:57:30.000000000 +0200 ++++ cpio-2.12/src/global.c 2016-03-15 17:01:38.559293625 +0100 +@@ -187,6 +187,9 @@ + /* The name this program was run with. */ + char *program_name; + ++/* Extract files over symbolic links */ ++bool extract_over_symlinks; ++ + /* A pointer to either lstat or stat, depending on whether + dereferencing of symlinks is done for input files. */ + int (*xstat) (); +Index: cpio-2.12/src/main.c +=================================================================== +--- cpio-2.12.orig/src/main.c 2015-09-12 12:57:30.000000000 +0200 ++++ cpio-2.12/src/main.c 2016-03-15 17:03:14.295363569 +0100 +@@ -61,7 +61,8 @@ + TO_STDOUT_OPTION, + RENUMBER_INODES_OPTION, + IGNORE_DEVNO_OPTION, +- DEVICE_INDEPENDENT_OPTION ++ DEVICE_INDEPENDENT_OPTION, ++ EXTRACT_OVER_SYMLINKS + }; + + const char *program_authors[] = +@@ -243,6 +244,8 @@ + N_("Create leading directories where needed"), GRID+1 }, + {"no-preserve-owner", NO_PRESERVE_OWNER_OPTION, 0, 0, + N_("Do not change the ownership of the files"), GRID+1 }, ++ {"extract-over-symlinks", EXTRACT_OVER_SYMLINKS, 0, 0, ++ N_("Force writing over symbolic links"), GRID+1 }, + {"unconditional", 'u', NULL, 0, + N_("Replace all files unconditionally"), GRID+1 }, + {"sparse", SPARSE_OPTION, NULL, 0, +@@ -432,6 +435,10 @@ + no_chown_flag = true; + break; + ++ case EXTRACT_OVER_SYMLINKS: /* --extract-over-symlinks */ ++ extract_over_symlinks = true; ++ break; ++ + case 'o': /* Copy-out mode. */ + if (copy_function != 0) + USAGE_ERROR ((0, 0, _("Mode already defined"))); +Index: cpio-2.12/src/extern.h +=================================================================== +--- cpio-2.12.orig/src/extern.h 2015-09-12 12:57:30.000000000 +0200 ++++ cpio-2.12/src/extern.h 2016-03-15 17:07:29.203583995 +0100 +@@ -96,6 +96,7 @@ + extern char output_is_special; + extern char input_is_seekable; + extern char output_is_seekable; ++extern bool extract_over_symlinks; + extern int (*xstat) (); + extern void (*copy_function) (); + extern char *change_directory_option; + +Index: cpio-2.12/doc/cpio.1 +=================================================================== +--- cpio-2.12.orig/doc/cpio.1 2015-09-12 12:57:30.000000000 +0200 ++++ cpio-2.12/doc/cpio.1 2016-03-15 17:09:00.610213320 +0100 +@@ -49,6 +49,7 @@ + [\fB\-\-no\-preserve\-owner\fR] [\fB\-\-message=\fIMESSAGE\fR] + [\fB\-\-force\-local\fR] [\fB\-\-no\-absolute\-filenames\fR] [\fB\-\-sparse\fR] + [\fB\-\-only\-verify\-crc\fR] [\fB\-\-to\-stdout\fR] [\fB\-\-quiet\fR] ++[\-\-extract\-over\-symlinks] + [\fB\-\-rsh\-command=\fICOMMAND\fR] + [\fIpattern\fR...] [\fB<\fR \fIarchive\fR] + diff --git a/system/base/cpio/files/cpio-2.12-non-gnu-compilers.patch b/system/base/cpio/files/cpio-2.12-non-gnu-compilers.patch new file mode 100644 index 00000000..c7fc7f95 --- /dev/null +++ b/system/base/cpio/files/cpio-2.12-non-gnu-compilers.patch @@ -0,0 +1,11 @@ +--- cpio-2.12/src/cpiohdr.h ++++ cpio-2.12/src/cpiohdr.h +@@ -25,6 +25,8 @@ + + # ifdef HAVE_ATTRIB_PACKED + # define ATTRIB_PACKED __attribute__((packed)) ++# else ++# define ATTRIB_PACKED + # endif + + # ifdef HAVE_PRAGMA_PACK diff --git a/system/base/cpio/files/cpio-2.12-svr4compat.patch b/system/base/cpio/files/cpio-2.12-svr4compat.patch new file mode 100644 index 00000000..45e1a875 --- /dev/null +++ b/system/base/cpio/files/cpio-2.12-svr4compat.patch @@ -0,0 +1,22 @@ +--- cpio-2.12/doc/cpio.texi.orig 2015-12-31 15:56:15.606713144 -0500 ++++ cpio-2.12/doc/cpio.texi 2015-12-31 16:00:05.186934057 -0500 +@@ -261,7 +261,8 @@ Sets the I/O block size to @var{block-si + @item -B + Set the I/O block size to 5120 bytes. + @item -c +-Use the old portable (ASCII) archive format. ++Identical to ``-H newc'', use the new (SVR4) portable format. ++If you wish the old portable (ASCII) archive format, use ``-H odc'' instead. + @item -C @var{number} + @itemx --io-size=@var{number} + Set the I/O block size to the given @var{number} of bytes. +--- cpio-2.12/src/main.c.orig 2015-12-31 15:56:15.606713144 -0500 ++++ cpio-2.12/src/main.c 2015-12-31 16:02:24.047067176 -0500 +@@ -329,6 +329,7 @@ parse_opt (int key, char *arg, struct ar + case 'c': /* Use the old portable ASCII format. */ + if (archive_format != arf_unknown) + USAGE_ERROR ((0, 0, _("Archive format multiply defined"))); ++#define SVR4_COMPAT + #ifdef SVR4_COMPAT + archive_format = arf_newascii; /* -H newc. */ + #else diff --git a/system/base/cpio/pspec.xml b/system/base/cpio/pspec.xml index dc100509..bd0f48ca 100644 --- a/system/base/cpio/pspec.xml +++ b/system/base/cpio/pspec.xml @@ -17,6 +17,12 @@ cpio-2.9-exitCode.patch CVE-2010-0624-rpatelib-overflow.patch + cpio-2.12-name-overflow.patch + cpio-2.12-non-gnu-compilers.patch + cpio-2.12-no-overwrite-symlinks.patch + cpio-2.12-svr4compat.patch + CVE-2010-0624-rpatelib-overflow.patch + @@ -32,6 +38,13 @@ + + 2019-12-27 + 2.12 + Rebuild + Idris Kalp + idriskalp@gmail.com + 2018-07-15 2.12 From 3d721f53e2ab0e128029fdf0f83fc630e82a1b89 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 12:47:50 +0300 Subject: [PATCH 093/160] popt rebuild --- system/base/popt/pspec.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/system/base/popt/pspec.xml b/system/base/popt/pspec.xml index 99c256d2..e7d6e676 100644 --- a/system/base/popt/pspec.xml +++ b/system/base/popt/pspec.xml @@ -45,6 +45,13 @@ + + 2019-12-27 + 1.16 + Rebuild + idris Kalp + idriskalp@gmail.com + 2018-07-15 1.16 From d14d210f53fae1f6d9e8f9632e6253b15797ef4f Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 12:57:55 +0300 Subject: [PATCH 094/160] json-c 0.13.1 --- system/base/json-c/pspec.xml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/system/base/json-c/pspec.xml b/system/base/json-c/pspec.xml index 2659faba..7e2d4084 100644 --- a/system/base/json-c/pspec.xml +++ b/system/base/json-c/pspec.xml @@ -12,9 +12,9 @@ library A JSON implementation in C json-c implements a reference counting object model that allows you to easily construct JSON objects in C, output them as JSON formatted strings and parse JSON formatted strings back into the C representation of JSON objects. - https://s3.amazonaws.com/json-c_releases/releases/json-c-0.12.1.tar.gz + https://github.com/json-c/json-c/archive/json-c-0.13.1-20180305.tar.gz - wno-werror.patch + @@ -55,6 +55,13 @@ + + 2019-12-27 + 0.13.1_20180305 + Version bump + idris Kalp + idriskalp@gmail.com + 2018-07-15 0.12.1 From b85ba7e0f617b3af538a212b6513d7b825c9a6b5 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 13:02:18 +0300 Subject: [PATCH 095/160] cryptsetup 2.2.2 --- system/base/cryptsetup/pspec.xml | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/system/base/cryptsetup/pspec.xml b/system/base/cryptsetup/pspec.xml index 53fadc2a..0ed1f212 100644 --- a/system/base/cryptsetup/pspec.xml +++ b/system/base/cryptsetup/pspec.xml @@ -13,15 +13,17 @@ app:cli Userspace setup tool for transparent encryption of block devices using dm-crypt Userspace setup tool for transparent encryption of block devices using dm-crypt - https://www.kernel.org/pub/linux/utils/cryptsetup/v1.7/cryptsetup-1.7.5.tar.xz + https://mirrors.edge.kernel.org/pub/linux/utils/cryptsetup/v2.2/cryptsetup-2.2.2.tar.xz - device-mapper-devel + device-mapper-devel libgpg-error-devel libgcrypt-devel python-devel libutil-linux-devel popt-devel popt + openssl-devel + json-c-devel @@ -31,6 +33,7 @@ libcryptsetup popt + libutil-linux /sbin @@ -49,6 +52,8 @@ libgpg-error libgcrypt libutil-linux + openssl + json-c /lib/libcryptsetup.so* @@ -68,7 +73,7 @@ - + + + 2019-12-27 + 2.2.2 + Version bump + idris Kalp + idriskalp@gmail.com + 2019-01-01 1.7.5 From 4dda20d3eeed4caa888d71e5eb7d4f29a60844d6 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 13:02:41 +0300 Subject: [PATCH 096/160] dbus-glib 0.110 --- system/base/dbus-glib/pspec.xml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/system/base/dbus-glib/pspec.xml b/system/base/dbus-glib/pspec.xml index 99334fae..4214971a 100644 --- a/system/base/dbus-glib/pspec.xml +++ b/system/base/dbus-glib/pspec.xml @@ -13,7 +13,7 @@ library Glib bindings for D-Bus dbus-glib is an add-on library to integrate the standard D-Bus library with the GLib thread abstraction and main loop. - http://dbus.freedesktop.org/releases/dbus-glib/dbus-glib-0.108.tar.gz + http://dbus.freedesktop.org/releases/dbus-glib/dbus-glib-0.110.tar.gz dbus-devel @@ -63,11 +63,11 @@ - 2018-10-31 - 0.108 - Rebuild. - Ertuğrul Erata - ertugrulerata@gmail.com + 2019-12-27 + 0.110 + Version bump + idris Kalp + idriskalp@gmail.com 2018-07-20 From 47fc423c85ff5a7a61c9c4be1f75ab6b6757f5b8 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 13:06:52 +0300 Subject: [PATCH 097/160] dbus-python 1.2.14 --- system/base/dbus-python/pspec.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/system/base/dbus-python/pspec.xml b/system/base/dbus-python/pspec.xml index afe5d104..ab5787a1 100644 --- a/system/base/dbus-python/pspec.xml +++ b/system/base/dbus-python/pspec.xml @@ -13,7 +13,7 @@ library D-Bus Python bindings dbus-python provides a Python module which wraps the D-Bus programming API. - https://dbus.freedesktop.org/releases/dbus-python/dbus-python-1.2.4.tar.gz + https://dbus.freedesktop.org/releases/dbus-python/dbus-python-1.2.14.tar.gz python-devel @@ -56,6 +56,13 @@ + + 2019-12-27 + 1.2.14 + Version bump + idris Kalp + idriskalp@gmail.com + 2018-10-31 1.2.4 From 8636e239388d96425eb1bc57b015869ce1804e4a Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 13:07:13 +0300 Subject: [PATCH 098/160] dhcpcd 8.1.4 --- system/base/dhcpcd/pspec.xml | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/system/base/dhcpcd/pspec.xml b/system/base/dhcpcd/pspec.xml index 78f6062b..a02cc947 100644 --- a/system/base/dhcpcd/pspec.xml +++ b/system/base/dhcpcd/pspec.xml @@ -12,12 +12,12 @@ app:console A dhcp client only An RFC2131 and RFC1541 compliant DHCP client daemon. dhcpcd gets an IP address and other information from a corresponding DHCP server, configures the network interface automatically, and tries to renew the lease time according to RFC2131 or RFC1541 depending on the command line option. - http://ftp.osuosl.org/pub/blfs/conglomeration/dhcpcd/dhcpcd-7.1.1.tar.xz - + http://ftp.osuosl.org/pub/blfs/conglomeration/dhcpcd/dhcpcd-8.1.4.tar.xz + eudev-devel @@ -45,6 +45,13 @@ + + 2019-12-27 + 8.1.4 + Version bump + idris Kalp + idriskalp@gmail.com + 2019-06-02 7.1.1 From bb2dd28924ea152df05207e6c081b544adb0b0b7 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 13:09:40 +0300 Subject: [PATCH 099/160] libunwind 1.3.1 --- system/base/libunwind/actions.py | 2 +- system/base/libunwind/pspec.xml | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/system/base/libunwind/actions.py b/system/base/libunwind/actions.py index 6b11f28f..36449812 100644 --- a/system/base/libunwind/actions.py +++ b/system/base/libunwind/actions.py @@ -50,6 +50,6 @@ def install(): return # FIXME: Fedora removes it, Suse keeps it, breaks samba build, investigate further - pisitools.remove("/usr/lib/libunwind*.a") + #pisitools.remove("/usr/lib/libunwind*.a") pisitools.dodoc("AUTHORS", "ChangeLog", "README*", "NEWS", "TODO") diff --git a/system/base/libunwind/pspec.xml b/system/base/libunwind/pspec.xml index 2fda6e0e..4a1bf798 100644 --- a/system/base/libunwind/pspec.xml +++ b/system/base/libunwind/pspec.xml @@ -12,7 +12,7 @@ library Call chain tracer of a program libunwind is a portable and efficient C programming interface (API) to determine the call chain of a program. - http://download.savannah.gnu.org/releases/libunwind/libunwind-1.1.tar.gz + http://mirror.rackdc.com/savannah/libunwind/libunwind-1.3.1.tar.gz xz-devel @@ -61,6 +61,13 @@ + + 2019-12-27 + 1.3.1 + Version bump + idris Kalp + idriskalp@gmail.com + 2018-11-06 1.1 From d3bdf40be333c1e9412d829035f15d9b55d1fcf4 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 13:12:39 +0300 Subject: [PATCH 100/160] gperftools 2.7 --- system/base/gperftools/pspec.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/system/base/gperftools/pspec.xml b/system/base/gperftools/pspec.xml index 5e67c700..ae97aa7a 100644 --- a/system/base/gperftools/pspec.xml +++ b/system/base/gperftools/pspec.xml @@ -13,7 +13,7 @@ app:console Google Performance Tools Perf Tools is a collection of a high-performance multi-threaded malloc() implementation, plus some pretty nifty performance analysis tools. - https://github.com/gperftools/gperftools/releases/download/gperftools-2.5/gperftools-2.5.tar.gz + https://github.com/gperftools/gperftools/releases/download/gperftools-2.7/gperftools-2.7.tar.gz libunwind-devel @@ -62,6 +62,13 @@ + + 2019-12-27 + 2.7 + Version bump + idris Kalp + idriskalp@gmail.com + 2018-07-15 2.5 From 27566510bdf6778ee41f90146e3e330a68b7e0b7 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 13:15:30 +0300 Subject: [PATCH 101/160] snappy 1.1.7 --- system/base/snappy/actions.py | 22 +++++++++++++--------- system/base/snappy/files/snappy.pc | 10 ++++++++++ system/base/snappy/pspec.xml | 18 +++++++++++++++--- 3 files changed, 38 insertions(+), 12 deletions(-) create mode 100644 system/base/snappy/files/snappy.pc diff --git a/system/base/snappy/actions.py b/system/base/snappy/actions.py index 15bc60f3..3bd5d08a 100644 --- a/system/base/snappy/actions.py +++ b/system/base/snappy/actions.py @@ -7,24 +7,28 @@ from pisi.actionsapi import shelltools from pisi.actionsapi import autotools from pisi.actionsapi import pisitools +from pisi.actionsapi import cmaketools from pisi.actionsapi import get def setup(): pisitools.flags.remove("-DNDEBUG") - shelltools.system("./autogen.sh") - autotools.configure("--prefix=/usr \ - --disable-static \ - --enable-shared") + #shelltools.system("./autogen.sh") + #autotools.configure("--prefix=/usr \ + #--disable-static \ + #--enable-shared") - pisitools.dosed("libtool", " -shared ", " -Wl,-O1,--as-needed -shared ") + #pisitools.dosed("libtool", " -shared ", " -Wl,-O1,--as-needed -shared ") + + cmaketools.configure("-DBUILD_SHARED_LIBS=ON \ + -DCMAKE_INSTALL_LIBDIR=lib") def build(): - autotools.make() + cmaketools.make() -def build(): - autotools.make("check") +def check(): + cmaketools.make("test") def install(): autotools.rawInstall("DESTDIR=%s" % get.installDIR()) - pisitools.dodoc("README", "COPYING", "ChangeLog", "NEWS", "AUTHORS") \ No newline at end of file + pisitools.dodoc("README.md", "COPYING", "AUTHORS") \ No newline at end of file diff --git a/system/base/snappy/files/snappy.pc b/system/base/snappy/files/snappy.pc new file mode 100644 index 00000000..09a56006 --- /dev/null +++ b/system/base/snappy/files/snappy.pc @@ -0,0 +1,10 @@ +prefix=/usr +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: snappy +Description: A fast compression/decompression library +Version: 1.1.7 +Libs: -L${libdir} -lsnappy +Cflags: -I${includedir} diff --git a/system/base/snappy/pspec.xml b/system/base/snappy/pspec.xml index b56d3d65..5daea8b8 100644 --- a/system/base/snappy/pspec.xml +++ b/system/base/snappy/pspec.xml @@ -15,10 +15,11 @@ lzo-devel zlib-devel + cmake - https://github.com/google/snappy/releases/download/1.1.3/snappy-1.1.3.tar.gz + https://github.com/google/snappy/archive/1.1.7.tar.gz - snappy-unittest.patch + @@ -37,11 +38,22 @@ snappy + + snappy.pc + - /usr/include + /usr/lib/pkgconfig + /usr/include + + 2019-12-27 + 1.1.7 + Version bump + idris Kalp + idriskalp@gmail.com + 2018-07-15 1.1.3 From 9203d458ff3711beb596e1ba4c23fbe952a3a459 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 13:41:41 +0300 Subject: [PATCH 102/160] leveldb 1.22 --- system/base/leveldb/actions.py | 25 +++++++----- ...e-soname-versioning-with-CMake-build.patch | 39 +++++++++++++++++++ system/base/leveldb/pspec.xml | 13 ++++++- 3 files changed, 67 insertions(+), 10 deletions(-) create mode 100644 system/base/leveldb/files/0001-Restore-soname-versioning-with-CMake-build.patch diff --git a/system/base/leveldb/actions.py b/system/base/leveldb/actions.py index 7fbc4392..4fb0ced6 100644 --- a/system/base/leveldb/actions.py +++ b/system/base/leveldb/actions.py @@ -6,20 +6,27 @@ from pisi.actionsapi import autotools from pisi.actionsapi import pisitools from pisi.actionsapi import shelltools +from pisi.actionsapi import cmaketools +from pisi.actionsapi import get + +def setup(): + cmaketools.configure("-DBUILD_SHARED_LIBS=ON \ + -DCMAKE_INSTALL_LIBDIR=lib") def build(): - shelltools.chmod("build_detect_platform", 0755) - autotools.make() + #shelltools.chmod("build_detect_platform", 0755) + cmaketools.make() def check(): - autotools.make("check") + cmaketools.make("test") def install(): - pisitools.dolib_so("libleveldb.so.1.18") - pisitools.dosym("libleveldb.so.1.18", "/usr/lib/libleveldb.so.1") - pisitools.dosym("libleveldb.so.1.18", "/usr/lib/libleveldb.so") + autotools.rawInstall("DESTDIR=%s" % get.installDIR()) + #pisitools.dolib_so("libleveldb.so.1.18") + #pisitools.dosym("libleveldb.so.1.18", "/usr/lib/libleveldb.so.1") + #pisitools.dosym("libleveldb.so.1.18", "/usr/lib/libleveldb.so") - pisitools.insinto("/usr/include", "include/*") - pisitools.insinto("/usr/include", "helpers/memenv/memenv.h") + #pisitools.insinto("/usr/include", "include/*") + #pisitools.insinto("/usr/include", "helpers/memenv/memenv.h") - pisitools.dodoc("README", "LICENSE", "NEWS", "AUTHORS") \ No newline at end of file + pisitools.dodoc("README.md", "LICENSE", "NEWS", "AUTHORS") \ No newline at end of file diff --git a/system/base/leveldb/files/0001-Restore-soname-versioning-with-CMake-build.patch b/system/base/leveldb/files/0001-Restore-soname-versioning-with-CMake-build.patch new file mode 100644 index 00000000..01a9e6e0 --- /dev/null +++ b/system/base/leveldb/files/0001-Restore-soname-versioning-with-CMake-build.patch @@ -0,0 +1,39 @@ +From 37300aa54b8256dd2edfd504942eb2bd20823647 Mon Sep 17 00:00:00 2001 +From: leveldb Team +Date: Mon, 1 Apr 2019 08:59:17 -0700 +Subject: [PATCH] Restore soname versioning with CMake build + +Before: + +$ readelf -d build/libleveldb.so | grep soname + 0x000000000000000e (SONAME) Library soname: [libleveldb.so] + +After: +$ readelf -d build/libleveldb.so | grep soname + 0x000000000000000e (SONAME) Library soname: [libleveldb.so.1] + +This matches the soname from v1.20. + +PiperOrigin-RevId: 241334113 +--- + CMakeLists.txt | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index e471a2a..ceb5dd9 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -233,6 +233,10 @@ if(BUILD_SHARED_LIBS) + # Used by include/export.h. + LEVELDB_SHARED_LIBRARY + ) ++ set_target_properties(leveldb ++ PROPERTIES VERSION ${PROJECT_VERSION}) ++ set_target_properties(leveldb ++ PROPERTIES SOVERSION 1) + endif(BUILD_SHARED_LIBS) + + if(HAVE_CLANG_THREAD_SAFETY) +-- +2.21.0 + diff --git a/system/base/leveldb/pspec.xml b/system/base/leveldb/pspec.xml index 2d17cf20..cd5f3c02 100644 --- a/system/base/leveldb/pspec.xml +++ b/system/base/leveldb/pspec.xml @@ -16,7 +16,10 @@ gperftools-devel snappy-devel - https://github.com/google/leveldb/archive/v1.18.tar.gz + https://github.com/google/leveldb/archive/1.22.tar.gz + + 0001-Restore-soname-versioning-with-CMake-build.patch + @@ -38,10 +41,18 @@ /usr/include + /usr/lib/cmake + + 2019-12-27 + 1.22 + Version bump + idris Kalp + idriskalp@gmail.com + 2018-07-15 1.18 From 192a457ef38abc45f21b4ebaa681e8e6d28d8e6c Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 14:10:52 +0300 Subject: [PATCH 103/160] leveldb revert to 1.18 --- system/base/leveldb/actions.py | 27 ++++++++++----------------- system/base/leveldb/pspec.xml | 10 +++------- 2 files changed, 13 insertions(+), 24 deletions(-) diff --git a/system/base/leveldb/actions.py b/system/base/leveldb/actions.py index 4fb0ced6..83d709fa 100644 --- a/system/base/leveldb/actions.py +++ b/system/base/leveldb/actions.py @@ -6,27 +6,20 @@ from pisi.actionsapi import autotools from pisi.actionsapi import pisitools from pisi.actionsapi import shelltools -from pisi.actionsapi import cmaketools -from pisi.actionsapi import get - -def setup(): - cmaketools.configure("-DBUILD_SHARED_LIBS=ON \ - -DCMAKE_INSTALL_LIBDIR=lib") def build(): - #shelltools.chmod("build_detect_platform", 0755) - cmaketools.make() + shelltools.chmod("build_detect_platform", 0755) + autotools.make() -def check(): - cmaketools.make("test") +#def check(): + #autotools.make("check") def install(): - autotools.rawInstall("DESTDIR=%s" % get.installDIR()) - #pisitools.dolib_so("libleveldb.so.1.18") - #pisitools.dosym("libleveldb.so.1.18", "/usr/lib/libleveldb.so.1") - #pisitools.dosym("libleveldb.so.1.18", "/usr/lib/libleveldb.so") + pisitools.dolib_so("libleveldb.so.1.18") + pisitools.dosym("libleveldb.so.1.18", "/usr/lib/libleveldb.so.1") + pisitools.dosym("libleveldb.so.1.18", "/usr/lib/libleveldb.so") - #pisitools.insinto("/usr/include", "include/*") - #pisitools.insinto("/usr/include", "helpers/memenv/memenv.h") + pisitools.insinto("/usr/include", "include/*") + pisitools.insinto("/usr/include", "helpers/memenv/memenv.h") - pisitools.dodoc("README.md", "LICENSE", "NEWS", "AUTHORS") \ No newline at end of file + pisitools.dodoc("README", "LICENSE", "NEWS", "AUTHORS") \ No newline at end of file diff --git a/system/base/leveldb/pspec.xml b/system/base/leveldb/pspec.xml index cd5f3c02..78cd0a24 100644 --- a/system/base/leveldb/pspec.xml +++ b/system/base/leveldb/pspec.xml @@ -16,10 +16,7 @@ gperftools-devel snappy-devel - https://github.com/google/leveldb/archive/1.22.tar.gz - - 0001-Restore-soname-versioning-with-CMake-build.patch - + https://github.com/google/leveldb/archive/v1.18.tar.gz @@ -41,15 +38,14 @@ /usr/include - /usr/lib/cmake 2019-12-27 - 1.22 - Version bump + 1.18 + Rebuild idris Kalp idriskalp@gmail.com From ae8618e9fb45803bb25055b1585e8ce26e8c7107 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 14:11:15 +0300 Subject: [PATCH 104/160] libestr 0.1.11 --- system/base/libestr/pspec.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/system/base/libestr/pspec.xml b/system/base/libestr/pspec.xml index 6eaff99e..f4eb6f06 100644 --- a/system/base/libestr/pspec.xml +++ b/system/base/libestr/pspec.xml @@ -12,7 +12,7 @@ library Library for some string essentials libestr - some essentials for string handling (and a bit more) - http://libestr.adiscon.com/files/download/libestr-0.1.10.tar.gz + http://libestr.adiscon.com/files/download/libestr-0.1.11.tar.gz @@ -37,6 +37,13 @@ + + 2019-12-27 + 0.1.11 + Version bump + idris Kalp + idriskalp@gmail.com + 2018-07-15 0.1.10 From fe993fae2fb459a39f0bf626088255a08d35c0e2 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 15:04:31 +0300 Subject: [PATCH 105/160] libfastjson 0.99.8 --- system/base/libfastjson/pspec.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/system/base/libfastjson/pspec.xml b/system/base/libfastjson/pspec.xml index 42ec9122..d3b475ca 100644 --- a/system/base/libfastjson/pspec.xml +++ b/system/base/libfastjson/pspec.xml @@ -12,7 +12,7 @@ library A performance-focused json library for C A performance-focused json library for C - https://github.com/rsyslog/libfastjson/archive/v0.99.4.tar.gz + https://github.com/rsyslog/libfastjson/archive/v0.99.8.tar.gz @@ -37,6 +37,13 @@ + + 2019-12-27 + 0.99.8 + Version bump + idris Kalp + idriskalp@gmail.com + 2018-07-19 0.99.4 From 09e9e625e42ce91d2ac5c55b95449307fb0f2491 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 15:07:55 +0300 Subject: [PATCH 106/160] libidn 1.35 --- system/base/libidn/pspec.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/system/base/libidn/pspec.xml b/system/base/libidn/pspec.xml index be1d55c4..c8daf6b5 100644 --- a/system/base/libidn/pspec.xml +++ b/system/base/libidn/pspec.xml @@ -14,7 +14,7 @@ library Internationalized Domain Names (IDN) implementation GNU Libidn is an implementation of the Stringprep, Punycode and IDNA specifications defined by the IETF Internationalized Domain Names (IDN) working group, used for internationalized domain names. The C library is available under the GNU Lesser General Public License. - http://ftp.gnu.org/gnu/libidn/libidn-1.33.tar.gz + http://ftp.gnu.org/gnu/libidn/libidn-1.35.tar.gz @@ -63,6 +63,13 @@ + + 2019-12-27 + 1.35 + Version bump + Idris Kalp + idriskalp@gmail.com + 2018-07-15 1.33 From 8f9875c106991bd0ae99b22ce925f797eff412d3 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 15:10:04 +0300 Subject: [PATCH 107/160] liblogging 1.0.6 --- system/base/liblogging/actions.py | 4 +++- system/base/liblogging/pspec.xml | 9 ++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/system/base/liblogging/actions.py b/system/base/liblogging/actions.py index 24794ff8..f5f34907 100644 --- a/system/base/liblogging/actions.py +++ b/system/base/liblogging/actions.py @@ -8,9 +8,11 @@ from pisi.actionsapi import autotools from pisi.actionsapi import pisitools def setup(): + autotools.autoreconf("-vfi") autotools.configure("--disable-static \ --disable-rfc3195 \ - --disable-journal") + --disable-journal \ + --disable-man-pages") def build(): autotools.make() diff --git a/system/base/liblogging/pspec.xml b/system/base/liblogging/pspec.xml index 375545a3..54be3277 100644 --- a/system/base/liblogging/pspec.xml +++ b/system/base/liblogging/pspec.xml @@ -12,7 +12,7 @@ library Easy to use, portable, open source library for system logging Liblogging offers an enhanced replacement for the syslog() call, but retains its ease of use. - https://sourceforge.net/projects/pisilinux/files/source/liblogging-1.0.5.tar.gz + https://github.com/rsyslog/liblogging/archive/v1.0.6.tar.gz @@ -39,6 +39,13 @@ + + 2019-12-27 + 1.0.6 + Version bump + idris Kalp + idriskalp@gmail.com + 2018-07-19 1.0.5 From 0933c464bc102c2c59a19d01029296ad3fd0cf83 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 15:12:10 +0300 Subject: [PATCH 108/160] libusb 1.0.22 --- system/base/libusb/pspec.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/system/base/libusb/pspec.xml b/system/base/libusb/pspec.xml index cf59adcf..314fbcfc 100644 --- a/system/base/libusb/pspec.xml +++ b/system/base/libusb/pspec.xml @@ -12,7 +12,7 @@ library Userspace access to USB devices Project's main aim is to create a library for use by user level applications to access USB devices regardless of OS. - https://sourceforge.net/projects/libusb/files/libusb-1.0/libusb-1.0.21/libusb-1.0.21.tar.bz2 + https://sourceforge.net/projects/libusb/files/libusb-1.0/libusb-1.0.22/libusb-1.0.22.tar.bz2 eudev-devel @@ -82,6 +82,13 @@ + + 2019-12-27 + 1.0.22 + Version bump + idris Kalp + idriskalp@gmail.com + 2018-07-15 1.0.21 From 05f93c696652e0defce8b310b9d86619be58f270 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 15:13:28 +0300 Subject: [PATCH 109/160] libusb-compat rebuild --- system/base/libusb-compat/pspec.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/system/base/libusb-compat/pspec.xml b/system/base/libusb-compat/pspec.xml index eb3682f7..c0610ffb 100644 --- a/system/base/libusb-compat/pspec.xml +++ b/system/base/libusb-compat/pspec.xml @@ -65,6 +65,13 @@ + + 2019-12-27 + 1.0.5 + Rebuild + idris Kalp + idriskalp@gmail.com + 2018-07-15 0.1.5 From 37784082dd26b7f184b68ba7760cf7103e2a88f8 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 15:15:00 +0300 Subject: [PATCH 110/160] libuser rebuild --- system/base/libuser/pspec.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/system/base/libuser/pspec.xml b/system/base/libuser/pspec.xml index 1d57394e..181e204f 100644 --- a/system/base/libuser/pspec.xml +++ b/system/base/libuser/pspec.xml @@ -76,6 +76,13 @@ + + 2019-2-27 + 0.62 + Rebuild + idris Kalp + idriskalp@gmail.com + 2018-09-16 0.62 From 31e040ceb8c8ff28a1d1e53b77866ffa4992306f Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 15:16:25 +0300 Subject: [PATCH 111/160] lsb-release rebuild --- system/base/lsb-release/pspec.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/system/base/lsb-release/pspec.xml b/system/base/lsb-release/pspec.xml index dad05c3c..5b52ae91 100644 --- a/system/base/lsb-release/pspec.xml +++ b/system/base/lsb-release/pspec.xml @@ -31,6 +31,13 @@ + + 2019-12-27 + 1.4 + Rebuild + idris Kalp + idriskalp@gmail.com + 2018-11-14 1.4 From 76e93a70b9594dd767fbd28851e5d94ada6f7892 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 15:17:55 +0300 Subject: [PATCH 112/160] mailcap 2.1.48 --- system/base/mailcap/pspec.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/system/base/mailcap/pspec.xml b/system/base/mailcap/pspec.xml index bcbf66ed..25b581c5 100644 --- a/system/base/mailcap/pspec.xml +++ b/system/base/mailcap/pspec.xml @@ -13,7 +13,7 @@ data Helper application and MIME type associations for file types mailcap file is used by the metamail program. Metamail reads the mailcap file to determine how it should display non-text or multimedia material. - https://releases.pagure.org/mailcap/mailcap-2.1.46.tar.xz + https://releases.pagure.org/mailcap/mailcap-2.1.48.tar.xz extend-mailcap.patch @@ -30,6 +30,13 @@ + + 2019-12-27 + 2.1.48 + Version bump + idris Kalp + idriskalp@gmail.com + 2018-07-15 2.1.46 From fa8239c114b953c577eb9de7e63bc415c9e4f4bd Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 15:21:21 +0300 Subject: [PATCH 113/160] mingetty rebuild --- system/base/mingetty/pspec.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/system/base/mingetty/pspec.xml b/system/base/mingetty/pspec.xml index 897df0fa..2885ea2f 100644 --- a/system/base/mingetty/pspec.xml +++ b/system/base/mingetty/pspec.xml @@ -43,6 +43,13 @@ + + 2019-12-27 + 1.08 + Rebuild + idris Kalp + idriskalp@gmail.com + 2018-07-15 1.08 From f26ae163d68812b2e0bfc39c482f0db50c3435dc Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 15:21:31 +0300 Subject: [PATCH 114/160] man-pages 4.04 --- system/base/man-pages/actions.py | 2 +- system/base/man-pages/pspec.xml | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/system/base/man-pages/actions.py b/system/base/man-pages/actions.py index 549aecfd..86e4176b 100644 --- a/system/base/man-pages/actions.py +++ b/system/base/man-pages/actions.py @@ -10,7 +10,7 @@ from pisi.actionsapi import get def install(): autotools.rawInstall("DESTDIR=%s" % get.installDIR()) - autotools.rawInstall("DESTDIR=%s -C man-pages-posix-2003-a" % get.installDIR()) + autotools.rawInstall("DESTDIR=%s -C man-pages-posix-2013-a" % get.installDIR()) # These come from attr pisitools.remove("/usr/share/man/man2/flistxattr.2") diff --git a/system/base/man-pages/pspec.xml b/system/base/man-pages/pspec.xml index 1bbc269b..a6834e0b 100644 --- a/system/base/man-pages/pspec.xml +++ b/system/base/man-pages/pspec.xml @@ -12,8 +12,8 @@ data:doc A somewhat comprehensive collection of Linux man pages A large collection of man pages (documentation) from the Linux Documentation Project (LDP). - https://www.kernel.org/pub/linux/docs/man-pages/man-pages-5.04.tar.xz - http://www.kernel.org/pub/linux/docs/man-pages/man-pages-posix/man-pages-posix-2003-a.tar.xz + https://mirrors.edge.kernel.org/pub/linux/docs/man-pages/man-pages-5.04.tar.xz + https://mirrors.edge.kernel.org/pub/linux/docs/man-pages/man-pages-posix/man-pages-posix-2013-a.tar.xz @@ -32,12 +32,12 @@ - - 2019-12-11 + + 2019-12-27 5.04 Version bump. - Mustafa Cinasal - muscnsl@gmail.com + Idris Kalp + idriskalp@gmail.com 2018-11-29 From 76b849ff62074300f9179626e4b40bb5072336c7 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 15:22:58 +0300 Subject: [PATCH 115/160] miscfiles rebuild --- system/base/miscfiles/pspec.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/system/base/miscfiles/pspec.xml b/system/base/miscfiles/pspec.xml index f21d9865..3c635aaa 100644 --- a/system/base/miscfiles/pspec.xml +++ b/system/base/miscfiles/pspec.xml @@ -26,6 +26,13 @@ + + 2019-12-27 + 1.5 + Rebuild + Idris Kalp + idriskalp@gmail.com + 2018-07-15 1.5 From 24d1387d0e67866dda64c9db6c7cf1b884ac513e Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 15:26:39 +0300 Subject: [PATCH 116/160] ncompress rebuild --- system/base/ncompress/pspec.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/system/base/ncompress/pspec.xml b/system/base/ncompress/pspec.xml index 651fdfbf..5e3d042f 100644 --- a/system/base/ncompress/pspec.xml +++ b/system/base/ncompress/pspec.xml @@ -30,6 +30,13 @@ + + 2019-12-27 + 4.2.4.4 + Rebuild + idris Kalp + idriskalp@gmail.com + 2018-07-15 4.2.4.4 From 03b044d7d13da563941632e81dd903e8ee7ed586 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 15:31:47 +0300 Subject: [PATCH 117/160] net-tools rebuild --- system/base/net-tools/pspec.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/system/base/net-tools/pspec.xml b/system/base/net-tools/pspec.xml index 2aedf244..6c785057 100644 --- a/system/base/net-tools/pspec.xml +++ b/system/base/net-tools/pspec.xml @@ -61,6 +61,13 @@ + + 2019-12-27 + 1.60 + Rebuild + idris Kalp + idriskalp@gmail.com + 2018-07-15 1.60 From 3391a35732e47fe2d5a0b6b2b65c8db42776ae87 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 15:33:59 +0300 Subject: [PATCH 118/160] nspr 4.24 --- system/base/nspr/pspec.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/system/base/nspr/pspec.xml b/system/base/nspr/pspec.xml index 481ee0ac..e81a1c33 100644 --- a/system/base/nspr/pspec.xml +++ b/system/base/nspr/pspec.xml @@ -12,7 +12,7 @@ library Netscape Portable Runtime Netscape Portable Runtime (NSPR) provides a platform-neutral API for system level and libc like functions. The API is used in the Mozilla client, many of Netscape/AOL/iPlanet's and other software offerings. - https://ftp.mozilla.org/pub/nspr/releases/v4.23/src/nspr-4.23.tar.gz + https://ftp.mozilla.org/pub/nspr/releases/v4.24/src/nspr-4.24.tar.gz nspr.pc.in generate-pc-config.sh @@ -41,6 +41,13 @@ + + 2019-12-27 + 4.24 + Version bump. + Idris Kalp + idriskalp@gmail.com + 2019-12-02 4.23 From af2894ff5dae6647dc1b0d4f603abb0648a42aca Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 15:35:08 +0300 Subject: [PATCH 119/160] nss-mdns rebuild --- system/base/nss-mdns/pspec.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/system/base/nss-mdns/pspec.xml b/system/base/nss-mdns/pspec.xml index 05f74018..38963968 100644 --- a/system/base/nss-mdns/pspec.xml +++ b/system/base/nss-mdns/pspec.xml @@ -31,6 +31,13 @@ + + 2019-12-27 + 0.10 + Rebuild + idris Kalp + idriskalp@gmail.com + 2018-07-15 0.10 From fe391ecf16958e79a487d0f2c74da7ceab85028f Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 15:38:53 +0300 Subject: [PATCH 120/160] sysfsutils rebuild --- system/base/sysfsutils/pspec.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/system/base/sysfsutils/pspec.xml b/system/base/sysfsutils/pspec.xml index 1ca3fec4..6de546f1 100644 --- a/system/base/sysfsutils/pspec.xml +++ b/system/base/sysfsutils/pspec.xml @@ -44,6 +44,13 @@ + + 2019-12-27 + 2.1.0 + Rebuild + idris Kalp + idriskalp@gmail.com + 2018-07-15 2.1.0 From 25dbb9b45a00d991d74db20b19d237de97002f5e Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 15:40:18 +0300 Subject: [PATCH 121/160] pcmciautils rebuild --- system/base/pcmciautils/pspec.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/system/base/pcmciautils/pspec.xml b/system/base/pcmciautils/pspec.xml index c283d00f..0f1a03d8 100644 --- a/system/base/pcmciautils/pspec.xml +++ b/system/base/pcmciautils/pspec.xml @@ -34,6 +34,13 @@ + + 2019-12-27 + 018 + Rebuild + idris Kalp + idriskalp@gmail.com + 2018-07-15 018 From c01f12d0c2169682bf0f5a75fac80b18a872333c Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 15:42:18 +0300 Subject: [PATCH 122/160] plyvel rebuild --- system/base/plyvel/pspec.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/system/base/plyvel/pspec.xml b/system/base/plyvel/pspec.xml index a6973e85..3b0fe162 100644 --- a/system/base/plyvel/pspec.xml +++ b/system/base/plyvel/pspec.xml @@ -31,6 +31,13 @@ + + 2019-12-27 + 0.9 + Rebuild + Idris Kalp + idriskalp@gmail.com + 2019-04-10 0.9 From b7cec94f021d4e73ca28cf80692a283298e765cd Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 15:43:17 +0300 Subject: [PATCH 123/160] procps rebuild --- system/base/procps/pspec.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/base/procps/pspec.xml b/system/base/procps/pspec.xml index 0edf1f35..f12dbfb2 100644 --- a/system/base/procps/pspec.xml +++ b/system/base/procps/pspec.xml @@ -39,7 +39,7 @@ - 2019-12-25 + 2019-12-27 3.3.15 Rebuild Idris Kalp From 89e068d7c9fcd319d2fafb04277d1a48dc854107 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 15:51:31 +0300 Subject: [PATCH 124/160] bzip2 add symlink --- system/base/bzip2/actions.py | 1 + system/base/bzip2/pspec.xml | 74 ++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100755 system/base/bzip2/pspec.xml diff --git a/system/base/bzip2/actions.py b/system/base/bzip2/actions.py index 904fb9af..42ea32a2 100755 --- a/system/base/bzip2/actions.py +++ b/system/base/bzip2/actions.py @@ -39,6 +39,7 @@ def install(): pisitools.dolib("libbz2.so.%s" % libversion, "/lib") pisitools.dosym("libbz2.so.1", "/lib/libbz2.so") + pisitools.dosym("libbz2.so.1", "/lib/libbz2.so.1.0") pisitools.dosym("libbz2.so.%s" % libversion, "/lib/libbz2.so.1") pisitools.dohtml("manual.html") diff --git a/system/base/bzip2/pspec.xml b/system/base/bzip2/pspec.xml new file mode 100755 index 00000000..ffed2383 --- /dev/null +++ b/system/base/bzip2/pspec.xml @@ -0,0 +1,74 @@ + + + + + bzip2 + http://www.bzip.org/ + + PisiLinux Community + admins@pisilinux.org + + BZIP2 + app:console + A high-quality data compressor + bzip2 is high-quality data compressor. It typically compresses files to within 10% to 15% of the best available techniques (the PPM family of statistical compressors), whilst being around twice as fast at compression and six times faster at decompression. + https://sourceware.org/pub/bzip2/bzip2-1.0.6.tar.gz + + bzip2-1.0.2-progress.patch + bzip2-1.0.4-bzip2recover.patch + bzip2-1.0.4-man-links.patch + bzip2-1.0.6-saneso.patch + manpath.patch + + + + + bzip2 + + /bin + /lib + /usr/lib + /usr/share/doc + /usr/share/man + /usr/include + + + + + + 2019-10-01 + 1.0.6 + Rebuild + Idris Kalp + idriskalp@gmail.com + + + 2018-07-15 + 1.0.6 + Rebuild + Ertuğrul Erata + ertugrulerata@gmail.com + + + 2017-01-07 + 1.0.6 + Version bump. + Ertuğrul Erata + ertugrulerata@gmail.com + + + 2016-04-27 + 1.0.6 + Release Bump + PisiLinux Community + admin@pisilinux.org + + + 2016-02-28 + 1.0.6 + First release + Ertuğrul Erata + ertugrulerata@gmail.com + + + From 3a7dfb56a94ff76e74b829de4a158bec3c3d64e7 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 15:53:29 +0300 Subject: [PATCH 125/160] python-pyliblzma rebuild --- system/base/python-pyliblzma/pspec.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/system/base/python-pyliblzma/pspec.xml b/system/base/python-pyliblzma/pspec.xml index 3c1908bc..806a7bf6 100644 --- a/system/base/python-pyliblzma/pspec.xml +++ b/system/base/python-pyliblzma/pspec.xml @@ -12,7 +12,7 @@ library Python bindings for lzma pyliblzma provides a python interface for the liblzma library to read/write data that has been compressed/decompressed with lzma utils. - http://pypi.python.org/packages/source/p/pyliblzma/pyliblzma-0.5.3.tar.bz2 + https://files.pythonhosted.org/packages/17/48/5292ade507dafe573360560ba53783395587dc42eb32b347feb2ac70fc6b/pyliblzma-0.5.3.tar.bz2 xz-devel python-setuptools @@ -33,6 +33,13 @@ + + 2019-12-27 + 0.5.3 + Rebuild + idris Kalp + idriskalp@gmail.com + 2018-07-15 0.5.3 From e3d80fd14656b11a8359587de18ce383327a54cd Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 15:56:14 +0300 Subject: [PATCH 126/160] rsyslog 8.1910.0 --- system/base/rsyslog/pspec.xml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/system/base/rsyslog/pspec.xml b/system/base/rsyslog/pspec.xml index 37f670cf..2005aedb 100644 --- a/system/base/rsyslog/pspec.xml +++ b/system/base/rsyslog/pspec.xml @@ -12,9 +12,10 @@ service Enhanced system logging and kernel message trapping daemons rsyslog is an enhanced multi-threaded syslogd supporting, among others, MySQL, syslog/tcp, RFC 3195, permitted sender lists, filtering on any message part, and fine grain output format control. It is quite compatible with stock sysklogd and can be used as a drop-in replacement. - http://www.rsyslog.com/files/download/rsyslog/rsyslog-8.24.0.tar.gz + https://www.rsyslog.com/files/download/rsyslog/rsyslog-8.1910.0.tar.gz zlib-devel + curl-devel json-c-devel libestr-devel libgcrypt-devel @@ -27,6 +28,7 @@ rsyslog zlib + curl json-c libestr libgcrypt @@ -56,6 +58,13 @@ + + 2019-12-27 + 8.1910.0 + Version bump + idris Kalp + idriskalp@gmail.com + 2018-08-05 8.24.0 From 115894e5eb1de3ee27d2240968fe2928ace5ee04 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 15:58:02 +0300 Subject: [PATCH 127/160] run-parts rebuild --- system/base/run-parts/pspec.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/system/base/run-parts/pspec.xml b/system/base/run-parts/pspec.xml index 77447d43..d1888649 100644 --- a/system/base/run-parts/pspec.xml +++ b/system/base/run-parts/pspec.xml @@ -9,7 +9,7 @@ GPLv2+ run scripts or programs in a directory run scripts or programs in a directory - https://mirror.fccn.pt/repos/pub/ubuntu/ubuntu/pool/main/d/debianutils/debianutils_4.8.1.tar.xz + http://old.kali.org/kali/pool/main/d/debianutils/debianutils_4.9.tar.xz @@ -22,6 +22,13 @@ + + 2019-12-27 + 4.9 + Version bump + idris Kalp + idriskalp@gmail.com + 2018-07-15 4.8.1 From 9c4c07a83a59cbcbd454e8f15b2ca295a68db6c1 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 15:59:24 +0300 Subject: [PATCH 128/160] tcp-wrappers rebuild --- system/base/tcp-wrappers/pspec.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/system/base/tcp-wrappers/pspec.xml b/system/base/tcp-wrappers/pspec.xml index 5e220a7e..293cc2d0 100644 --- a/system/base/tcp-wrappers/pspec.xml +++ b/system/base/tcp-wrappers/pspec.xml @@ -65,6 +65,13 @@ + + 2019-12-27 + 7.6 + Rebuild + idris Kalp + idriskalp@gmail.com + 2018-07-15 7.6 From 9eee3d312533f187126340e4c9fc27613278f68d Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 16:00:33 +0300 Subject: [PATCH 129/160] time 1.9 --- system/base/time/actions.py | 3 +++ system/base/time/pspec.xml | 11 +++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/system/base/time/actions.py b/system/base/time/actions.py index f6a97668..96374a8b 100644 --- a/system/base/time/actions.py +++ b/system/base/time/actions.py @@ -13,5 +13,8 @@ def setup(): def build(): autotools.make() +def check(): + autotools.make("check") + def install(): autotools.rawInstall("DESTDIR=%s" % get.installDIR()) diff --git a/system/base/time/pspec.xml b/system/base/time/pspec.xml index fa1ff8cc..6b3cb385 100644 --- a/system/base/time/pspec.xml +++ b/system/base/time/pspec.xml @@ -12,9 +12,9 @@ app:console A GNU utility for monitoring a program's use of system resources time utility runs another program, collects information about the resources used by that program while it is running, and displays the results. - ftp://prep.ai.mit.edu/pub/gnu/time/time-1.7.tar.gz + https://ftp.gnu.org/gnu/time/time-1.9.tar.gz - time-1.7-destdir.patch + @@ -27,6 +27,13 @@ + + 2019-12-27 + 1.9 + Version bump + idris Kalp + idriskalp@gmail.com + 2018-07-15 1.7 From 86bc13da885dd9e7f3ab9def3776c7fc6f429444 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 16:05:05 +0300 Subject: [PATCH 130/160] unzip rebuild --- system/base/unzip/pspec.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/system/base/unzip/pspec.xml b/system/base/unzip/pspec.xml index 42fd04bc..c2e27be0 100644 --- a/system/base/unzip/pspec.xml +++ b/system/base/unzip/pspec.xml @@ -43,6 +43,13 @@ + + 2019-12-27 + 60 + Rebuild + idris Kalp + idriskalp@gmail.com + 2018-07-15 60 From 92edabf5c2b8c7976d4227ea89bf97954f55405b Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 16:06:53 +0300 Subject: [PATCH 131/160] usbutils 012 --- system/base/usbutils/actions.py | 10 +++++++--- system/base/usbutils/pspec.xml | 9 ++++++++- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/system/base/usbutils/actions.py b/system/base/usbutils/actions.py index 6c119f45..7f69d1f6 100644 --- a/system/base/usbutils/actions.py +++ b/system/base/usbutils/actions.py @@ -6,11 +6,15 @@ from pisi.actionsapi import autotools from pisi.actionsapi import pisitools +from pisi.actionsapi import shelltools from pisi.actionsapi import get def setup(): - autotools.configure("--datadir=/usr/share/misc \ - --disable-zlib") + shelltools.system("./autogen.sh \ + --datadir=/usr/share/misc \ + --disable-zlib") + #autotools.configure("--datadir=/usr/share/misc \ + #--disable-zlib") def build(): autotools.make() @@ -20,4 +24,4 @@ def install(): #pisitools.removeDir("/usr/sbin") - pisitools.dodoc("AUTHORS", "ChangeLog", "NEWS", "README") + pisitools.dodoc("NEWS", "README.md") diff --git a/system/base/usbutils/pspec.xml b/system/base/usbutils/pspec.xml index 941ddb0e..5e58f0bf 100644 --- a/system/base/usbutils/pspec.xml +++ b/system/base/usbutils/pspec.xml @@ -12,7 +12,7 @@ app:console Linux USB utilities usbutils provides utilities for inspecting devices connected to a USB bus. - https://www.kernel.org/pub/linux/utils/usb/usbutils/usbutils-009.tar.xz + https://mirrors.edge.kernel.org/pub/linux/utils/usb/usbutils/usbutils-012.tar.xz usb.ids @@ -42,6 +42,13 @@ + + 2019-12-27 + 012 + Version bump + idris Kalp + idriskalp@gmail.com + 2018-07-15 009 From fe2b4f2d0721517ef7153f63b814f56c46cb6d72 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 16:09:31 +0300 Subject: [PATCH 132/160] v86d rebuild --- system/base/v86d/pspec.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/system/base/v86d/pspec.xml b/system/base/v86d/pspec.xml index 66ead397..fe19a576 100644 --- a/system/base/v86d/pspec.xml +++ b/system/base/v86d/pspec.xml @@ -14,7 +14,7 @@ Userspace helper for uvesafb v86d is a userspace helper that runs x86 code in an emulated environment. It is used by the kernel framebuffer driver uvesafb. - http://ftp.linux.org.tr/gentoo/distfiles/v86d-0.1.10.tar.bz2 + https://sourceforge.net/projects/openspa/files/sources/v86d-0.1.10.tar.bz2 @@ -28,6 +28,13 @@ + + 2019-12-27 + 0.1.10 + Rebuild + idris Kalp + idriskalp@gmail.com + 2018-07-15 0.1.10 From 30d252e66e5715e00a37985f92ac072350eccde4 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 16:11:13 +0300 Subject: [PATCH 133/160] vixie-cron rebuild --- system/base/vixie-cron/pspec.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/system/base/vixie-cron/pspec.xml b/system/base/vixie-cron/pspec.xml index 7b5b8437..3d8038fc 100644 --- a/system/base/vixie-cron/pspec.xml +++ b/system/base/vixie-cron/pspec.xml @@ -55,6 +55,13 @@ + + 2019-12-27 + 4.1 + Rebuild + idris Kalp + idriskalp@gmail.com + 2018-07-15 4.1 From 8631d392ab33581bbc4fcfa2415151d0c4860f4b Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 16:12:20 +0300 Subject: [PATCH 134/160] which rebuild --- system/base/which/pspec.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/system/base/which/pspec.xml b/system/base/which/pspec.xml index 44fe6a03..1d0637f9 100644 --- a/system/base/which/pspec.xml +++ b/system/base/which/pspec.xml @@ -29,6 +29,13 @@ + + 2019-12-27 + 2.21 + Rebuild + idris Kalp + idriskalp@gmail.com + 2018-07-15 2.21 From f2e1c336d64b0adf036c0106ea5ed6a80ac45cd4 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 16:14:58 +0300 Subject: [PATCH 135/160] wireless-tools rebuild --- system/base/wireless-tools/pspec.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/system/base/wireless-tools/pspec.xml b/system/base/wireless-tools/pspec.xml index 134beb62..99ca5b8b 100644 --- a/system/base/wireless-tools/pspec.xml +++ b/system/base/wireless-tools/pspec.xml @@ -50,6 +50,13 @@ + + 2019-12-27 + 30 + Rebuild + idris Kalp + idriskalp@gmail.com + 2018-09-21 30 From 9de15ff5c6461c35af0e308d1b83c4697faf2699 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 16:15:11 +0300 Subject: [PATCH 136/160] zip rebuild --- system/base/zip/pspec.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/system/base/zip/pspec.xml b/system/base/zip/pspec.xml index 3c62ec7a..eeb9f2ad 100644 --- a/system/base/zip/pspec.xml +++ b/system/base/zip/pspec.xml @@ -12,7 +12,7 @@ app:console Info ZIP (encryption support) Zip is a compression and file packaging/archive utility. Zip is useful for packaging a set of files for distribution, for archiving files, and for saving disk space by temporarily compressing unused files or directories. - ftp://ftp.info-zip.org/pub/infozip/src/zip30.tgz + https://ftp.osuosl.org/pub/blfs/conglomeration/zip/zip30.tar.gz @@ -28,6 +28,13 @@ + + 2019-12-27 + 3.0 + Rebuild + idris Kalp + idriskalp@gmail.com + 2018-07-15 3.0 From c5b465c57537c49396f8a5bac4e8390a62852823 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 16:15:30 +0300 Subject: [PATCH 137/160] piksemel rebuild --- system/base/piksemel/pspec.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/system/base/piksemel/pspec.xml b/system/base/piksemel/pspec.xml index df8b57eb..636225de 100644 --- a/system/base/piksemel/pspec.xml +++ b/system/base/piksemel/pspec.xml @@ -12,7 +12,7 @@ library Python binding for iksemel A simple, fast, small and robust XML parser for Python, based on iksemel. - http://source.pisilinux.org/1.0/piksemel-1.3.1.tar.gz + https://sourceforge.net/projects/pisilinux/files/source/piksemel-1.3.1.tar.gz python-devel @@ -33,6 +33,13 @@ + + 2019-12-27 + 1.3.1 + Rebuild + Idris Kalp + idriskalp@gmail.com + 2018-07-15 1.3.1 From 7547e1e6a085fe941f323c44da1c7ed0af062db7 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 16:23:23 +0300 Subject: [PATCH 138/160] python-pytz --- programming/language/python/python-pytz/pspec.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programming/language/python/python-pytz/pspec.xml b/programming/language/python/python-pytz/pspec.xml index fac167b0..8e9a9197 100755 --- a/programming/language/python/python-pytz/pspec.xml +++ b/programming/language/python/python-pytz/pspec.xml @@ -26,7 +26,7 @@ - 2019-10-03 + 2019-12-27 2019.2 Version bump idris Kalp From 32c2a0d8f1ce7ede38718feb77cf2c1798e0afe7 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 16:26:13 +0300 Subject: [PATCH 139/160] libee rebuild --- system/base/libee/pspec.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/system/base/libee/pspec.xml b/system/base/libee/pspec.xml index b52edbde..92293aca 100644 --- a/system/base/libee/pspec.xml +++ b/system/base/libee/pspec.xml @@ -12,7 +12,7 @@ library An Event Expression Library inspired by CEE Libee - An Event Expression Library inspired by CEE - http://www.libee.org/download/files/download/libee-0.4.1.tar.gz + http://ftp.osuosl.org/pub/clfs/conglomeration/libee/libee-0.4.1.tar.gz libestr-devel @@ -44,6 +44,13 @@ + + 2019-12-27 + 0.4.1 + Rebuild + idris Kalp + idriskalp@gmail.com + 2018-07-19 0.4.1 From 2db61d5c5886a8c48307a114bc56c219306e0c68 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 16:26:40 +0300 Subject: [PATCH 140/160] urlgrabber fix dep --- system/base/urlgrabber/pspec.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/system/base/urlgrabber/pspec.xml b/system/base/urlgrabber/pspec.xml index 728a8d7f..ffc44221 100644 --- a/system/base/urlgrabber/pspec.xml +++ b/system/base/urlgrabber/pspec.xml @@ -23,6 +23,7 @@ python pycurl + python-six /usr/lib From f635a8f1419d76c7f9b91cb02c77269351e89e99 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 16:26:56 +0300 Subject: [PATCH 141/160] pisilinux-python rebuild --- system/base/pisilinux-python/pspec.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/system/base/pisilinux-python/pspec.xml b/system/base/pisilinux-python/pspec.xml index 96b5e997..fab2867c 100644 --- a/system/base/pisilinux-python/pspec.xml +++ b/system/base/pisilinux-python/pspec.xml @@ -12,7 +12,7 @@ library Python modules for Pisi Linux Python modules for Pisi Linux provides functions for common task, with the aim of easing development. - http://source.pisilinux.org/1.0/pisilinux-python-0.4.8.tar.gz + https://sourceforge.net/projects/pisilinux/files/source/pisilinux-python-0.4.8.tar.gz python-devel libX11-devel @@ -48,6 +48,13 @@ + + 2019-12-27 + 0.4.8 + Rebuild + Idris Kalp + idriskalp@gmail.com + 2018-07-23 0.4.8 From e42a8592117dd5872f0c5db99788819767e590b4 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 16:27:18 +0300 Subject: [PATCH 142/160] pisi rebuild --- system/base/pisi/pspec.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/system/base/pisi/pspec.xml b/system/base/pisi/pspec.xml index 50b8e29c..b4abc8fa 100644 --- a/system/base/pisi/pspec.xml +++ b/system/base/pisi/pspec.xml @@ -12,7 +12,7 @@ app:console PISI is the package management system of Pisi Linux PISI is a modern package management system implemented in Python. Some of its main features are: package sources are written in XML and python, implements all functions through a simple-to-use API, integrates low-level and high-level package management features. - http://source.pisilinux.org/1.0/pisi-2.6.tar.xz + https://sourceforge.net/projects/pisilinux/files/source/pisi-2.6.tar.xz pisi.conf-i686 pisi.conf-x86_64 @@ -88,6 +88,13 @@ + + 2019-12-27 + 2.6 + Rebuild + Idris Kalp + idriskalp@gmail.com + 2019-01-20 2.6 From b67f0d23c5a93d4bccfba33e651828998ac5e71f Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 16:27:40 +0300 Subject: [PATCH 143/160] timezone 2019c --- system/base/timezone/pspec.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/system/base/timezone/pspec.xml b/system/base/timezone/pspec.xml index f0b2842d..93fe1726 100644 --- a/system/base/timezone/pspec.xml +++ b/system/base/timezone/pspec.xml @@ -14,7 +14,7 @@ data Timezone data files and tools timezone includes timezone data files and tools to use them. Package contents are synchronized with glibc tree. - http://www.iana.org/time-zones/repository/releases/tzdata2018e.tar.gz + https://data.iana.org/time-zones/releases/tzdata2019c.tar.gz perl gawk @@ -36,6 +36,13 @@ + + 2019-12-27 + 2019c + Version bump + idris Kalp + idriskalp@gmail.com + 2018-11-29 2018e From 2bc4fadb886f59bb48fa6b887b4aa63b21f9205e Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 16:35:58 +0300 Subject: [PATCH 144/160] python-sphinx fix dep --- programming/language/python/python-sphinx/pspec.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/programming/language/python/python-sphinx/pspec.xml b/programming/language/python/python-sphinx/pspec.xml index 30e47e39..408e9d97 100755 --- a/programming/language/python/python-sphinx/pspec.xml +++ b/programming/language/python/python-sphinx/pspec.xml @@ -14,7 +14,7 @@ It's a very common documentation generator especially using for python based documentation.It can generate HTML or PDF, Ps outputs with Latex output support. https://files.pythonhosted.org/packages/8b/7e/b188d9a3b9c938e736e02a74c1363c2888e095d770df2c72b4c312f9fdcb/Sphinx-1.6.5.tar.gz - docutils + python-docutils python-six python-requests python-sphinx-alabaster-theme @@ -32,7 +32,7 @@ python-sphinx - docutils + python-docutils python-Pygments python-Jinja2 From 7967be878067cbc51b4513732e673239a1c70477 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 16:40:29 +0300 Subject: [PATCH 145/160] disktype rebuild --- hardware/disk/disktype/pspec.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/hardware/disk/disktype/pspec.xml b/hardware/disk/disktype/pspec.xml index 0290a95e..91430de5 100644 --- a/hardware/disk/disktype/pspec.xml +++ b/hardware/disk/disktype/pspec.xml @@ -21,7 +21,7 @@ klibc - colorgcc + @@ -35,6 +35,13 @@ + + 2019-12-27 + 9 + Rebuild + idris Kalp + idriskalp@gmail.com + 2018-07-23 9 From 96abe63f4aa2bfeb5b4982479a6bd8ebcaacbb3b Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 16:41:38 +0300 Subject: [PATCH 146/160] mdadm rebuild --- hardware/disk/mdadm/pspec.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/hardware/disk/mdadm/pspec.xml b/hardware/disk/mdadm/pspec.xml index 3051fa9f..1e8ef187 100644 --- a/hardware/disk/mdadm/pspec.xml +++ b/hardware/disk/mdadm/pspec.xml @@ -57,6 +57,13 @@ + + 2019-12-27 + 3.4 + Rebuild + idris Kalp + idriskalp@gmail.com + 2018-10-02 3.4 From 9006d92aca14c50e827a380774d6a590266dbb19 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 16:42:35 +0300 Subject: [PATCH 147/160] mtools rebuild --- hardware/disk/mtools/pspec.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/hardware/disk/mtools/pspec.xml b/hardware/disk/mtools/pspec.xml index 6f69ccd9..4ac9669d 100644 --- a/hardware/disk/mtools/pspec.xml +++ b/hardware/disk/mtools/pspec.xml @@ -27,6 +27,13 @@ + + 2019-12-27 + 4.0.18 + Rebuild + idris Kalp + idriskalp@gmail.com + 2018-07-15 4.0.18 From 47ee2882515229c82994f17ab537f533b52dbc1e Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 16:56:09 +0300 Subject: [PATCH 148/160] wireless-regdb rebuild --- hardware/firmware/wireless-regdb/pspec.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/hardware/firmware/wireless-regdb/pspec.xml b/hardware/firmware/wireless-regdb/pspec.xml index df82e8d5..0a578580 100644 --- a/hardware/firmware/wireless-regdb/pspec.xml +++ b/hardware/firmware/wireless-regdb/pspec.xml @@ -13,7 +13,7 @@ app:console This package contains the wireless regulatory database used by all cfg80211 based Linux wireless drivers This package contains the wireless regulatory database used by all cfg80211 based Linux wireless drivers - https://mirrors.edge.kernel.org/pub/software/network/wireless-regdb/wireless-regdb-2018.10.24.tar.xz + https://mirrors.edge.kernel.org/pub/software/network/wireless-regdb/wireless-regdb-2019.06.03.tar.xz @@ -28,6 +28,13 @@ + + 2019-12-27 + 2019.06.03 + Version bump + Idris Kalp + idriskalp@gmail.com + 2019-01-15 2018.10.24 From 64e0d73cb41a89ae6fe31196373aa1661029ab19 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 17:15:10 +0300 Subject: [PATCH 149/160] linux-firmware update --- hardware/firmware/linux-firmware/actions.py | 11 ++++++----- hardware/firmware/linux-firmware/pspec.xml | 11 +++++++++-- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/hardware/firmware/linux-firmware/actions.py b/hardware/firmware/linux-firmware/actions.py index aaddc341..3fd0582c 100644 --- a/hardware/firmware/linux-firmware/actions.py +++ b/hardware/firmware/linux-firmware/actions.py @@ -10,6 +10,7 @@ from pisi.actionsapi import pisitools from pisi.actionsapi import get WorkDir = "linux-firmware" +NoStrip = ["/lib"] def setup(): # Remove source files @@ -29,15 +30,15 @@ def install(): pisitools.insinto("/lib/firmware", "mix/*") # Remove installed and LIC* files from /lib/firmware - pisitools.remove("/lib/firmware/GPL-3") + #pisitools.remove("/lib/firmware/GPL-3") pisitools.remove("/lib/firmware/LICENCE*") pisitools.remove("/lib/firmware/LICENSE*") - pisitools.remove("/lib/firmware/configure") - pisitools.remove("/lib/firmware/Makefile") - pisitools.removeDir("/lib/firmware/mix") + #pisitools.remove("/lib/firmware/configure") + #pisitools.remove("/lib/firmware/Makefile") + #pisitools.removeDir("/lib/firmware/mix") #conflict on alsa-firmware #pisitools.remove("/lib/firmware/ctefx.bin") pisitools.remove("/lib/firmware/ctspeq.bin") # Install LICENSE files - pisitools.dodoc("WHENCE", "LICENCE.*", "LICENSE.*", "GPL-3") + pisitools.dodoc("WHENCE", "LICENCE.*", "LICENSE.*") diff --git a/hardware/firmware/linux-firmware/pspec.xml b/hardware/firmware/linux-firmware/pspec.xml index bf897649..2325978a 100644 --- a/hardware/firmware/linux-firmware/pspec.xml +++ b/hardware/firmware/linux-firmware/pspec.xml @@ -17,8 +17,8 @@ data Firmware files used by the Linux kernel linux-firmware contains different firmware files required for some devices to operate correctly. - - https://sourceforge.net/projects/pisilinux/files/source/linux-firmware-20190514.tar.xz + + https://sourceforge.net/projects/pisilinux/files/source/linux-firmware-20191220.tar.xz http://source.pisilinux.org/common-fw/common-fw.tar.xz http://source.pisilinux.org/firmware-ipw/firmware-ipw.tar.xz http://source.pisilinux.org/firmware-nonfreebox/firmware-nonfreebox-2-tar.bz2 @@ -49,6 +49,13 @@ + + 2019-12-27 + 20191220 + Update + Idris Kalp + idriskalp@gmail.com + 2019-06-05 20190514 From 0ae82b3f88731e3ceeea579fbc20b0e5b64ccbe6 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 17:16:32 +0300 Subject: [PATCH 150/160] libpng 1.6.37 --- .../libpng/files/libpng-1.6.37-apng.patch.gz | Bin 0 -> 10781 bytes multimedia/graphics/libpng/pspec.xml | 11 +++++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 multimedia/graphics/libpng/files/libpng-1.6.37-apng.patch.gz diff --git a/multimedia/graphics/libpng/files/libpng-1.6.37-apng.patch.gz b/multimedia/graphics/libpng/files/libpng-1.6.37-apng.patch.gz new file mode 100644 index 0000000000000000000000000000000000000000..4e2a48ae7f1d782418d26e0d3f668b005b24c259 GIT binary patch literal 10781 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 Portable Network Graphics library The Portable Network Graphics (PNG) format was designed to replace the older and simpler GIF format and, to some extent, the much more complex TIFF format. Project's main aim is to concentrate on two major uses: the World Wide Web (WWW) and image-editing. - mirrors://sourceforge/libpng/libpng-1.6.34.tar.xz + mirrors://sourceforge/libpng/libpng-1.6.37.tar.xz zlib-devel - libpng-1.6.34-apng.patch.gz + libpng-1.6.37-apng.patch.gz libpng-multilib.patch @@ -67,6 +67,13 @@ + + 2019-12-27 + 1.6.37 + Version bump + idris Kalp + idriskalp@gmail.com + 2018-12-21 1.6.34 From 694e6ce1dab56f84ef1115825865bdaace9d6bdd Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 17:19:00 +0300 Subject: [PATCH 151/160] freetype 2.10.1 --- desktop/font/freetype/pspec.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/desktop/font/freetype/pspec.xml b/desktop/font/freetype/pspec.xml index 3aa7eb82..f0c113ba 100644 --- a/desktop/font/freetype/pspec.xml +++ b/desktop/font/freetype/pspec.xml @@ -72,6 +72,13 @@ + + 2019-12-27 + 2.10.1 + Rebuild + Idris Kalp + idriskalp@gmail.com + 2019-08-01 2.10.1 From 1aaba423d3cba9c32800eaaa130ae095aa7f086c Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 18:59:37 +0300 Subject: [PATCH 152/160] kernel 5.4.6 --- .../kernel/files/configs/kernel-i686-config | 0 .../kernel/files/configs/kernel-x86_64-config | 17293 ++++--- .../kernel/files/patches/linux/patch-5.4.6.xz | Bin 0 -> 167272 bytes .../files/patches/mageia/CVE-2019-12379.patch | 37 + .../disable-mrproper-in-devel-rpms.patch | 74 + .../patches/mageia/fs-aufs-5.4-modular.patch | 321 + .../patches/mageia/fs-aufs-5.4-version.patch | 12 + .../files/patches/mageia/fs-aufs-5.4.patch | 37876 ++++++++++++++++ .../files/patches/mageia/fs-vboxsf.patch | 3410 ++ .../pisilinux/kernel-5.4-build-fix.patch | 18 + .../patches/pisilinux/revert-Makefile.patch | 780 + .../kernel/files/scripts/generate-module-list | 0 kernel/kernel/pspec.xml | 31 +- 13 files changed, 52519 insertions(+), 7333 deletions(-) mode change 100644 => 100755 kernel/kernel/files/configs/kernel-i686-config mode change 100644 => 100755 kernel/kernel/files/configs/kernel-x86_64-config create mode 100644 kernel/kernel/files/patches/linux/patch-5.4.6.xz create mode 100644 kernel/kernel/files/patches/mageia/CVE-2019-12379.patch create mode 100644 kernel/kernel/files/patches/mageia/disable-mrproper-in-devel-rpms.patch create mode 100644 kernel/kernel/files/patches/mageia/fs-aufs-5.4-modular.patch create mode 100755 kernel/kernel/files/patches/mageia/fs-aufs-5.4-version.patch create mode 100644 kernel/kernel/files/patches/mageia/fs-aufs-5.4.patch create mode 100644 kernel/kernel/files/patches/mageia/fs-vboxsf.patch create mode 100644 kernel/kernel/files/patches/pisilinux/kernel-5.4-build-fix.patch create mode 100644 kernel/kernel/files/patches/pisilinux/revert-Makefile.patch mode change 100644 => 100755 kernel/kernel/files/scripts/generate-module-list diff --git a/kernel/kernel/files/configs/kernel-i686-config b/kernel/kernel/files/configs/kernel-i686-config old mode 100644 new mode 100755 diff --git a/kernel/kernel/files/configs/kernel-x86_64-config b/kernel/kernel/files/configs/kernel-x86_64-config old mode 100644 new mode 100755 index 4b4b19ec..e4359c8b --- a/kernel/kernel/files/configs/kernel-x86_64-config +++ b/kernel/kernel/files/configs/kernel-x86_64-config @@ -1,7325 +1,9968 @@ -# -# Automatically generated file; DO NOT EDIT. -# Linux/x86_64 4.19.56 Kernel Configuration -# - -# -# Compiler: gcc (Pisi Linux) 7.3.0 -# -CONFIG_CC_IS_GCC=y -CONFIG_GCC_VERSION=70300 -CONFIG_CLANG_VERSION=0 -CONFIG_CC_HAS_ASM_GOTO=y -CONFIG_IRQ_WORK=y -CONFIG_BUILDTIME_EXTABLE_SORT=y -CONFIG_THREAD_INFO_IN_TASK=y - -# -# General setup -# -CONFIG_INIT_ENV_ARG_LIMIT=32 -# CONFIG_COMPILE_TEST is not set -CONFIG_LOCALVERSION="" -# CONFIG_LOCALVERSION_AUTO is not set -CONFIG_BUILD_SALT="" -CONFIG_HAVE_KERNEL_GZIP=y -CONFIG_HAVE_KERNEL_BZIP2=y -CONFIG_HAVE_KERNEL_LZMA=y -CONFIG_HAVE_KERNEL_XZ=y -CONFIG_HAVE_KERNEL_LZO=y -CONFIG_HAVE_KERNEL_LZ4=y -CONFIG_KERNEL_GZIP=y -# CONFIG_KERNEL_BZIP2 is not set -# CONFIG_KERNEL_LZMA is not set -# CONFIG_KERNEL_XZ is not set -# CONFIG_KERNEL_LZO is not set -# CONFIG_KERNEL_LZ4 is not set -CONFIG_DEFAULT_HOSTNAME="" -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -CONFIG_SYSVIPC_SYSCTL=y -CONFIG_POSIX_MQUEUE=y -CONFIG_POSIX_MQUEUE_SYSCTL=y -CONFIG_CROSS_MEMORY_ATTACH=y -# CONFIG_USELIB is not set -CONFIG_AUDIT=y -CONFIG_HAVE_ARCH_AUDITSYSCALL=y -CONFIG_AUDITSYSCALL=y -CONFIG_AUDIT_WATCH=y -CONFIG_AUDIT_TREE=y - -# -# IRQ subsystem -# -CONFIG_GENERIC_IRQ_PROBE=y -CONFIG_GENERIC_IRQ_SHOW=y -CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y -CONFIG_GENERIC_PENDING_IRQ=y -CONFIG_GENERIC_IRQ_MIGRATION=y -CONFIG_GENERIC_IRQ_CHIP=y -CONFIG_IRQ_DOMAIN=y -CONFIG_IRQ_SIM=y -CONFIG_IRQ_DOMAIN_HIERARCHY=y -CONFIG_GENERIC_MSI_IRQ=y -CONFIG_GENERIC_MSI_IRQ_DOMAIN=y -CONFIG_GENERIC_IRQ_MATRIX_ALLOCATOR=y -CONFIG_GENERIC_IRQ_RESERVATION_MODE=y -CONFIG_IRQ_FORCED_THREADING=y -CONFIG_SPARSE_IRQ=y -# CONFIG_GENERIC_IRQ_DEBUGFS is not set -CONFIG_CLOCKSOURCE_WATCHDOG=y -CONFIG_ARCH_CLOCKSOURCE_DATA=y -CONFIG_CLOCKSOURCE_VALIDATE_LAST_CYCLE=y -CONFIG_GENERIC_TIME_VSYSCALL=y -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y -CONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST=y -CONFIG_GENERIC_CMOS_UPDATE=y - -# -# Timers subsystem -# -CONFIG_TICK_ONESHOT=y -CONFIG_NO_HZ_COMMON=y -# CONFIG_HZ_PERIODIC is not set -CONFIG_NO_HZ_IDLE=y -# CONFIG_NO_HZ_FULL is not set -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y -# CONFIG_PREEMPT_NONE is not set -CONFIG_PREEMPT_VOLUNTARY=y -# CONFIG_PREEMPT is not set - -# -# CPU/Task time and stats accounting -# -CONFIG_TICK_CPU_ACCOUNTING=y -# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set -# CONFIG_IRQ_TIME_ACCOUNTING is not set -CONFIG_HAVE_SCHED_AVG_IRQ=y -CONFIG_BSD_PROCESS_ACCT=y -CONFIG_BSD_PROCESS_ACCT_V3=y -CONFIG_TASKSTATS=y -CONFIG_TASK_DELAY_ACCT=y -CONFIG_TASK_XACCT=y -CONFIG_TASK_IO_ACCOUNTING=y -CONFIG_CPU_ISOLATION=y - -# -# RCU Subsystem -# -CONFIG_TREE_RCU=y -# CONFIG_RCU_EXPERT is not set -CONFIG_SRCU=y -CONFIG_TREE_SRCU=y -CONFIG_RCU_STALL_COMMON=y -CONFIG_RCU_NEED_SEGCBLIST=y -CONFIG_BUILD_BIN2C=y -CONFIG_IKCONFIG=y -CONFIG_IKCONFIG_PROC=y -CONFIG_LOG_BUF_SHIFT=18 -CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 -CONFIG_PRINTK_SAFE_LOG_BUF_SHIFT=13 -CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y -CONFIG_ARCH_SUPPORTS_NUMA_BALANCING=y -CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH=y -CONFIG_ARCH_SUPPORTS_INT128=y -# CONFIG_NUMA_BALANCING is not set -CONFIG_CGROUPS=y -CONFIG_PAGE_COUNTER=y -CONFIG_MEMCG=y -CONFIG_MEMCG_SWAP=y -CONFIG_MEMCG_SWAP_ENABLED=y -CONFIG_MEMCG_KMEM=y -CONFIG_BLK_CGROUP=y -# CONFIG_DEBUG_BLK_CGROUP is not set -CONFIG_CGROUP_WRITEBACK=y -CONFIG_CGROUP_SCHED=y -CONFIG_FAIR_GROUP_SCHED=y -CONFIG_CFS_BANDWIDTH=y -CONFIG_RT_GROUP_SCHED=y -CONFIG_CGROUP_PIDS=y -# CONFIG_CGROUP_RDMA is not set -CONFIG_CGROUP_FREEZER=y -CONFIG_CGROUP_HUGETLB=y -CONFIG_CPUSETS=y -CONFIG_PROC_PID_CPUSET=y -CONFIG_CGROUP_DEVICE=y -CONFIG_CGROUP_CPUACCT=y -CONFIG_CGROUP_PERF=y -# CONFIG_CGROUP_BPF is not set -CONFIG_SOCK_CGROUP_DATA=y -CONFIG_NAMESPACES=y -CONFIG_UTS_NS=y -CONFIG_IPC_NS=y -CONFIG_USER_NS=y -CONFIG_PID_NS=y -CONFIG_NET_NS=y -# CONFIG_CHECKPOINT_RESTORE is not set -CONFIG_SCHED_AUTOGROUP=y -# CONFIG_SYSFS_DEPRECATED is not set -CONFIG_RELAY=y -CONFIG_BLK_DEV_INITRD=y -CONFIG_INITRAMFS_SOURCE="" -CONFIG_RD_GZIP=y -CONFIG_RD_BZIP2=y -CONFIG_RD_LZMA=y -CONFIG_RD_XZ=y -CONFIG_RD_LZO=y -CONFIG_RD_LZ4=y -CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y -# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -CONFIG_SYSCTL=y -CONFIG_ANON_INODES=y -CONFIG_HAVE_UID16=y -CONFIG_SYSCTL_EXCEPTION_TRACE=y -CONFIG_HAVE_PCSPKR_PLATFORM=y -CONFIG_BPF=y -# CONFIG_EXPERT is not set -CONFIG_UID16=y -CONFIG_MULTIUSER=y -CONFIG_SGETMASK_SYSCALL=y -CONFIG_SYSFS_SYSCALL=y -CONFIG_FHANDLE=y -CONFIG_POSIX_TIMERS=y -CONFIG_PRINTK=y -CONFIG_PRINTK_NMI=y -CONFIG_BUG=y -CONFIG_ELF_CORE=y -CONFIG_PCSPKR_PLATFORM=y -CONFIG_BASE_FULL=y -CONFIG_FUTEX=y -CONFIG_FUTEX_PI=y -CONFIG_EPOLL=y -CONFIG_SIGNALFD=y -CONFIG_TIMERFD=y -CONFIG_EVENTFD=y -CONFIG_SHMEM=y -CONFIG_AIO=y -CONFIG_ADVISE_SYSCALLS=y -CONFIG_MEMBARRIER=y -CONFIG_KALLSYMS=y -CONFIG_KALLSYMS_ABSOLUTE_PERCPU=y -CONFIG_KALLSYMS_BASE_RELATIVE=y -CONFIG_BPF_SYSCALL=y -# CONFIG_BPF_JIT_ALWAYS_ON is not set -# CONFIG_USERFAULTFD is not set -CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y -CONFIG_RSEQ=y -# CONFIG_EMBEDDED is not set -CONFIG_HAVE_PERF_EVENTS=y - -# -# Kernel Performance Events And Counters -# -CONFIG_PERF_EVENTS=y -CONFIG_VM_EVENT_COUNTERS=y -# CONFIG_COMPAT_BRK is not set -CONFIG_SLAB=y -# CONFIG_SLUB is not set -CONFIG_SLAB_MERGE_DEFAULT=y -# CONFIG_SLAB_FREELIST_RANDOM is not set -CONFIG_SYSTEM_DATA_VERIFICATION=y -CONFIG_PROFILING=y -CONFIG_TRACEPOINTS=y -CONFIG_64BIT=y -CONFIG_X86_64=y -CONFIG_X86=y -CONFIG_INSTRUCTION_DECODER=y -CONFIG_OUTPUT_FORMAT="elf64-x86-64" -CONFIG_ARCH_DEFCONFIG="arch/x86/configs/x86_64_defconfig" -CONFIG_LOCKDEP_SUPPORT=y -CONFIG_STACKTRACE_SUPPORT=y -CONFIG_MMU=y -CONFIG_ARCH_MMAP_RND_BITS_MIN=28 -CONFIG_ARCH_MMAP_RND_BITS_MAX=32 -CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=8 -CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=16 -CONFIG_GENERIC_ISA_DMA=y -CONFIG_GENERIC_BUG=y -CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y -CONFIG_GENERIC_HWEIGHT=y -CONFIG_ARCH_MAY_HAVE_PC_FDC=y -CONFIG_RWSEM_XCHGADD_ALGORITHM=y -CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_ARCH_HAS_CPU_RELAX=y -CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y -CONFIG_ARCH_HAS_FILTER_PGPROT=y -CONFIG_HAVE_SETUP_PER_CPU_AREA=y -CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y -CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y -CONFIG_ARCH_HIBERNATION_POSSIBLE=y -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y -CONFIG_ARCH_WANT_GENERAL_HUGETLB=y -CONFIG_ZONE_DMA32=y -CONFIG_AUDIT_ARCH=y -CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y -CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y -CONFIG_HAVE_INTEL_TXT=y -CONFIG_X86_64_SMP=y -CONFIG_ARCH_SUPPORTS_UPROBES=y -CONFIG_FIX_EARLYCON_MEM=y -CONFIG_PGTABLE_LEVELS=4 -CONFIG_CC_HAS_SANE_STACKPROTECTOR=y - -# -# Processor type and features -# -CONFIG_ZONE_DMA=y -CONFIG_SMP=y -CONFIG_X86_FEATURE_NAMES=y -CONFIG_X86_X2APIC=y -CONFIG_X86_MPPARSE=y -# CONFIG_GOLDFISH is not set -CONFIG_RETPOLINE=y -# CONFIG_INTEL_RDT is not set -CONFIG_X86_EXTENDED_PLATFORM=y -# CONFIG_X86_NUMACHIP is not set -# CONFIG_X86_VSMP is not set -# CONFIG_X86_UV is not set -# CONFIG_X86_GOLDFISH is not set -# CONFIG_X86_INTEL_MID is not set -# CONFIG_X86_INTEL_LPSS is not set -CONFIG_X86_AMD_PLATFORM_DEVICE=y -CONFIG_IOSF_MBI=m -# CONFIG_IOSF_MBI_DEBUG is not set -CONFIG_X86_SUPPORTS_MEMORY_FAILURE=y -CONFIG_SCHED_OMIT_FRAME_POINTER=y -CONFIG_HYPERVISOR_GUEST=y -CONFIG_PARAVIRT=y -# CONFIG_PARAVIRT_SPINLOCKS is not set -CONFIG_XEN=y -CONFIG_XEN_PV=y -CONFIG_XEN_PV_SMP=y -CONFIG_XEN_DOM0=y -CONFIG_XEN_PVHVM=y -CONFIG_XEN_PVHVM_SMP=y -CONFIG_XEN_512GB=y -CONFIG_XEN_SAVE_RESTORE=y -CONFIG_XEN_DEBUG_FS=y -CONFIG_XEN_PVH=y -CONFIG_KVM_GUEST=y -# CONFIG_KVM_DEBUG_FS is not set -CONFIG_PARAVIRT_TIME_ACCOUNTING=y -CONFIG_PARAVIRT_CLOCK=y -# CONFIG_JAILHOUSE_GUEST is not set -CONFIG_NO_BOOTMEM=y -# CONFIG_MK8 is not set -# CONFIG_MPSC is not set -# CONFIG_MCORE2 is not set -# CONFIG_MATOM is not set -CONFIG_GENERIC_CPU=y -CONFIG_X86_INTERNODE_CACHE_SHIFT=6 -CONFIG_X86_L1_CACHE_SHIFT=6 -CONFIG_X86_TSC=y -CONFIG_X86_CMPXCHG64=y -CONFIG_X86_CMOV=y -CONFIG_X86_MINIMUM_CPU_FAMILY=64 -CONFIG_X86_DEBUGCTLMSR=y -CONFIG_CPU_SUP_INTEL=y -CONFIG_CPU_SUP_AMD=y -CONFIG_CPU_SUP_CENTAUR=y -CONFIG_HPET_TIMER=y -CONFIG_HPET_EMULATE_RTC=y -CONFIG_DMI=y -CONFIG_GART_IOMMU=y -# CONFIG_CALGARY_IOMMU is not set -CONFIG_NR_CPUS_RANGE_BEGIN=2 -CONFIG_NR_CPUS_RANGE_END=512 -CONFIG_NR_CPUS_DEFAULT=64 -CONFIG_NR_CPUS=8 -CONFIG_SCHED_SMT=y -CONFIG_SCHED_MC=y -CONFIG_SCHED_MC_PRIO=y -CONFIG_X86_LOCAL_APIC=y -CONFIG_X86_IO_APIC=y -CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS=y -CONFIG_X86_MCE=y -# CONFIG_X86_MCELOG_LEGACY is not set -CONFIG_X86_MCE_INTEL=y -CONFIG_X86_MCE_AMD=y -CONFIG_X86_MCE_THRESHOLD=y -# CONFIG_X86_MCE_INJECT is not set -CONFIG_X86_THERMAL_VECTOR=y - -# -# Performance monitoring -# -CONFIG_PERF_EVENTS_INTEL_UNCORE=y -CONFIG_PERF_EVENTS_INTEL_RAPL=y -CONFIG_PERF_EVENTS_INTEL_CSTATE=y -# CONFIG_PERF_EVENTS_AMD_POWER is not set -CONFIG_X86_16BIT=y -CONFIG_X86_ESPFIX64=y -CONFIG_X86_VSYSCALL_EMULATION=y -CONFIG_I8K=m -CONFIG_MICROCODE=y -CONFIG_MICROCODE_INTEL=y -CONFIG_MICROCODE_AMD=y -CONFIG_MICROCODE_OLD_INTERFACE=y -CONFIG_X86_MSR=y -CONFIG_X86_CPUID=y -# CONFIG_X86_5LEVEL is not set -CONFIG_X86_DIRECT_GBPAGES=y -CONFIG_ARCH_HAS_MEM_ENCRYPT=y -# CONFIG_AMD_MEM_ENCRYPT is not set -CONFIG_NUMA=y -CONFIG_AMD_NUMA=y -CONFIG_X86_64_ACPI_NUMA=y -CONFIG_NODES_SPAN_OTHER_NODES=y -# CONFIG_NUMA_EMU is not set -CONFIG_NODES_SHIFT=10 -CONFIG_ARCH_SPARSEMEM_ENABLE=y -CONFIG_ARCH_SPARSEMEM_DEFAULT=y -CONFIG_ARCH_SELECT_MEMORY_MODEL=y -CONFIG_ARCH_MEMORY_PROBE=y -CONFIG_ARCH_PROC_KCORE_TEXT=y -CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 -# CONFIG_X86_PMEM_LEGACY is not set -CONFIG_X86_CHECK_BIOS_CORRUPTION=y -CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK=y -CONFIG_X86_RESERVE_LOW=64 -CONFIG_MTRR=y -CONFIG_MTRR_SANITIZER=y -CONFIG_MTRR_SANITIZER_ENABLE_DEFAULT=1 -CONFIG_MTRR_SANITIZER_SPARE_REG_NR_DEFAULT=1 -CONFIG_X86_PAT=y -CONFIG_ARCH_USES_PG_UNCACHED=y -CONFIG_ARCH_RANDOM=y -CONFIG_X86_SMAP=y -CONFIG_X86_INTEL_UMIP=y -# CONFIG_X86_INTEL_MPX is not set -CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS=y -CONFIG_EFI=y -CONFIG_EFI_STUB=y -# CONFIG_EFI_MIXED is not set -CONFIG_SECCOMP=y -# CONFIG_HZ_100 is not set -# CONFIG_HZ_250 is not set -# CONFIG_HZ_300 is not set -CONFIG_HZ_1000=y -CONFIG_HZ=1000 -CONFIG_SCHED_HRTICK=y -CONFIG_KEXEC=y -# CONFIG_KEXEC_FILE is not set -CONFIG_CRASH_DUMP=y -CONFIG_KEXEC_JUMP=y -CONFIG_PHYSICAL_START=0x200000 -CONFIG_RELOCATABLE=y -CONFIG_RANDOMIZE_BASE=y -CONFIG_X86_NEED_RELOCS=y -CONFIG_PHYSICAL_ALIGN=0x1000000 -CONFIG_DYNAMIC_MEMORY_LAYOUT=y -CONFIG_RANDOMIZE_MEMORY=y -CONFIG_RANDOMIZE_MEMORY_PHYSICAL_PADDING=0xa -CONFIG_HOTPLUG_CPU=y -# CONFIG_BOOTPARAM_HOTPLUG_CPU0 is not set -# CONFIG_DEBUG_HOTPLUG_CPU0 is not set -# CONFIG_COMPAT_VDSO is not set -CONFIG_LEGACY_VSYSCALL_EMULATE=y -# CONFIG_LEGACY_VSYSCALL_NONE is not set -# CONFIG_CMDLINE_BOOL is not set -CONFIG_MODIFY_LDT_SYSCALL=y -CONFIG_HAVE_LIVEPATCH=y -CONFIG_ARCH_HAS_ADD_PAGES=y -CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y -CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y -CONFIG_USE_PERCPU_NUMA_NODE_ID=y -CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK=y -CONFIG_ARCH_ENABLE_HUGEPAGE_MIGRATION=y -CONFIG_ARCH_ENABLE_THP_MIGRATION=y - -# -# Power management and ACPI options -# -CONFIG_ARCH_HIBERNATION_HEADER=y -CONFIG_SUSPEND=y -CONFIG_SUSPEND_FREEZER=y -CONFIG_HIBERNATE_CALLBACKS=y -CONFIG_HIBERNATION=y -CONFIG_PM_STD_PARTITION="" -CONFIG_PM_SLEEP=y -CONFIG_PM_SLEEP_SMP=y -# CONFIG_PM_AUTOSLEEP is not set -# CONFIG_PM_WAKELOCKS is not set -CONFIG_PM=y -CONFIG_PM_DEBUG=y -# CONFIG_PM_ADVANCED_DEBUG is not set -CONFIG_PM_TEST_SUSPEND=y -CONFIG_PM_SLEEP_DEBUG=y -CONFIG_PM_TRACE=y -CONFIG_PM_TRACE_RTC=y -CONFIG_PM_CLK=y -# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set -CONFIG_ARCH_SUPPORTS_ACPI=y -CONFIG_ACPI=y -CONFIG_ACPI_LEGACY_TABLES_LOOKUP=y -CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC=y -CONFIG_ACPI_SYSTEM_POWER_STATES_SUPPORT=y -# CONFIG_ACPI_DEBUGGER is not set -CONFIG_ACPI_SPCR_TABLE=y -CONFIG_ACPI_LPIT=y -CONFIG_ACPI_SLEEP=y -# CONFIG_ACPI_PROCFS_POWER is not set -CONFIG_ACPI_REV_OVERRIDE_POSSIBLE=y -CONFIG_ACPI_EC_DEBUGFS=m -CONFIG_ACPI_AC=y -CONFIG_ACPI_BATTERY=y -CONFIG_ACPI_BUTTON=y -CONFIG_ACPI_VIDEO=m -CONFIG_ACPI_FAN=y -# CONFIG_ACPI_TAD is not set -CONFIG_ACPI_DOCK=y -CONFIG_ACPI_CPU_FREQ_PSS=y -CONFIG_ACPI_PROCESSOR_CSTATE=y -CONFIG_ACPI_PROCESSOR_IDLE=y -CONFIG_ACPI_CPPC_LIB=y -CONFIG_ACPI_PROCESSOR=y -CONFIG_ACPI_IPMI=m -CONFIG_ACPI_HOTPLUG_CPU=y -CONFIG_ACPI_PROCESSOR_AGGREGATOR=m -CONFIG_ACPI_THERMAL=y -CONFIG_ACPI_NUMA=y -CONFIG_ARCH_HAS_ACPI_TABLE_UPGRADE=y -CONFIG_ACPI_TABLE_UPGRADE=y -# CONFIG_ACPI_DEBUG is not set -CONFIG_ACPI_PCI_SLOT=y -CONFIG_ACPI_CONTAINER=y -CONFIG_ACPI_HOTPLUG_MEMORY=y -CONFIG_ACPI_HOTPLUG_IOAPIC=y -CONFIG_ACPI_SBS=m -CONFIG_ACPI_HED=y -CONFIG_ACPI_CUSTOM_METHOD=m -CONFIG_ACPI_BGRT=y -# CONFIG_ACPI_NFIT is not set -CONFIG_HAVE_ACPI_APEI=y -CONFIG_HAVE_ACPI_APEI_NMI=y -CONFIG_ACPI_APEI=y -CONFIG_ACPI_APEI_GHES=y -CONFIG_ACPI_APEI_PCIEAER=y -CONFIG_ACPI_APEI_MEMORY_FAILURE=y -# CONFIG_ACPI_APEI_EINJ is not set -# CONFIG_ACPI_APEI_ERST_DEBUG is not set -CONFIG_DPTF_POWER=m -CONFIG_ACPI_WATCHDOG=y -CONFIG_ACPI_EXTLOG=m -# CONFIG_PMIC_OPREGION is not set -CONFIG_ACPI_CONFIGFS=m -CONFIG_X86_PM_TIMER=y -CONFIG_SFI=y - -# -# CPU Frequency scaling -# -CONFIG_CPU_FREQ=y -CONFIG_CPU_FREQ_GOV_ATTR_SET=y -CONFIG_CPU_FREQ_GOV_COMMON=y -CONFIG_CPU_FREQ_STAT=y -CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y -# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set -# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set -# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set -# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set -# CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL is not set -CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -CONFIG_CPU_FREQ_GOV_POWERSAVE=m -CONFIG_CPU_FREQ_GOV_USERSPACE=y -CONFIG_CPU_FREQ_GOV_ONDEMAND=m -CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m -# CONFIG_CPU_FREQ_GOV_SCHEDUTIL is not set - -# -# CPU frequency scaling drivers -# -CONFIG_X86_INTEL_PSTATE=y -CONFIG_X86_PCC_CPUFREQ=y -CONFIG_X86_ACPI_CPUFREQ=y -CONFIG_X86_ACPI_CPUFREQ_CPB=y -CONFIG_X86_POWERNOW_K8=y -CONFIG_X86_AMD_FREQ_SENSITIVITY=m -# CONFIG_X86_SPEEDSTEP_CENTRINO is not set -CONFIG_X86_P4_CLOCKMOD=y - -# -# shared options -# -CONFIG_X86_SPEEDSTEP_LIB=y - -# -# CPU Idle -# -CONFIG_CPU_IDLE=y -CONFIG_CPU_IDLE_GOV_LADDER=y -CONFIG_CPU_IDLE_GOV_MENU=y -CONFIG_INTEL_IDLE=y - -# -# Bus options (PCI etc.) -# -CONFIG_PCI=y -CONFIG_PCI_DIRECT=y -CONFIG_PCI_MMCONFIG=y -CONFIG_PCI_XEN=y -CONFIG_PCI_DOMAINS=y -CONFIG_MMCONF_FAM10H=y -CONFIG_PCIEPORTBUS=y -CONFIG_HOTPLUG_PCI_PCIE=y -CONFIG_PCIEAER=y -CONFIG_PCIEAER_INJECT=m -CONFIG_PCIE_ECRC=y -CONFIG_PCIEASPM=y -# CONFIG_PCIEASPM_DEBUG is not set -CONFIG_PCIEASPM_DEFAULT=y -# CONFIG_PCIEASPM_POWERSAVE is not set -# CONFIG_PCIEASPM_POWER_SUPERSAVE is not set -# CONFIG_PCIEASPM_PERFORMANCE is not set -CONFIG_PCIE_PME=y -# CONFIG_PCIE_DPC is not set -# CONFIG_PCIE_PTM is not set -CONFIG_PCI_MSI=y -CONFIG_PCI_MSI_IRQ_DOMAIN=y -CONFIG_PCI_QUIRKS=y -# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set -CONFIG_PCI_STUB=y -# CONFIG_PCI_PF_STUB is not set -CONFIG_XEN_PCIDEV_FRONTEND=m -CONFIG_PCI_ATS=y -CONFIG_PCI_LOCKLESS_CONFIG=y -CONFIG_PCI_IOV=y -CONFIG_PCI_PRI=y -CONFIG_PCI_PASID=y -CONFIG_PCI_LABEL=y -# CONFIG_PCI_HYPERV is not set -CONFIG_HOTPLUG_PCI=y -CONFIG_HOTPLUG_PCI_ACPI=y -CONFIG_HOTPLUG_PCI_ACPI_IBM=m -# CONFIG_HOTPLUG_PCI_CPCI is not set -# CONFIG_HOTPLUG_PCI_SHPC is not set - -# -# PCI controller drivers -# - -# -# Cadence PCIe controllers support -# -# CONFIG_VMD is not set - -# -# DesignWare PCI Core Support -# -# CONFIG_PCIE_DW_PLAT_HOST is not set - -# -# PCI Endpoint -# -# CONFIG_PCI_ENDPOINT is not set - -# -# PCI switch controller drivers -# -# CONFIG_PCI_SW_SWITCHTEC is not set -CONFIG_ISA_DMA_API=y -CONFIG_AMD_NB=y -CONFIG_PCCARD=y -CONFIG_PCMCIA=y -CONFIG_PCMCIA_LOAD_CIS=y -CONFIG_CARDBUS=y - -# -# PC-card bridges -# -CONFIG_YENTA=m -CONFIG_YENTA_O2=y -CONFIG_YENTA_RICOH=y -CONFIG_YENTA_TI=y -CONFIG_YENTA_ENE_TUNE=y -CONFIG_YENTA_TOSHIBA=y -CONFIG_PD6729=m -CONFIG_I82092=m -CONFIG_PCCARD_NONSTATIC=y -# CONFIG_RAPIDIO is not set -# CONFIG_X86_SYSFB is not set - -# -# Binary Emulations -# -CONFIG_IA32_EMULATION=y -# CONFIG_IA32_AOUT is not set -CONFIG_X86_X32=y -CONFIG_COMPAT_32=y -CONFIG_COMPAT=y -CONFIG_COMPAT_FOR_U64_ALIGNMENT=y -CONFIG_SYSVIPC_COMPAT=y -CONFIG_X86_DEV_DMA_OPS=y -CONFIG_HAVE_GENERIC_GUP=y - -# -# Firmware Drivers -# -CONFIG_EDD=m -# CONFIG_EDD_OFF is not set -CONFIG_FIRMWARE_MEMMAP=y -CONFIG_DELL_RBU=m -CONFIG_DCDBAS=m -CONFIG_DMIID=y -CONFIG_DMI_SYSFS=y -CONFIG_DMI_SCAN_MACHINE_NON_EFI_FALLBACK=y -CONFIG_ISCSI_IBFT_FIND=y -CONFIG_ISCSI_IBFT=m -# CONFIG_FW_CFG_SYSFS is not set -CONFIG_GOOGLE_FIRMWARE=y -CONFIG_GOOGLE_SMI=m -# CONFIG_GOOGLE_COREBOOT_TABLE_ACPI is not set -# CONFIG_GOOGLE_MEMCONSOLE_X86_LEGACY is not set - -# -# EFI (Extensible Firmware Interface) Support -# -CONFIG_EFI_VARS=m -CONFIG_EFI_ESRT=y -CONFIG_EFI_VARS_PSTORE=m -# CONFIG_EFI_VARS_PSTORE_DEFAULT_DISABLE is not set -CONFIG_EFI_RUNTIME_MAP=y -# CONFIG_EFI_FAKE_MEMMAP is not set -CONFIG_EFI_RUNTIME_WRAPPERS=y -CONFIG_EFI_BOOTLOADER_CONTROL=m -CONFIG_EFI_CAPSULE_LOADER=m -CONFIG_EFI_TEST=m -CONFIG_APPLE_PROPERTIES=y -# CONFIG_RESET_ATTACK_MITIGATION is not set -CONFIG_UEFI_CPER=y -CONFIG_UEFI_CPER_X86=y -CONFIG_EFI_DEV_PATH_PARSER=y - -# -# Tegra firmware driver -# -CONFIG_HAVE_KVM=y -CONFIG_HAVE_KVM_IRQCHIP=y -CONFIG_HAVE_KVM_IRQFD=y -CONFIG_HAVE_KVM_IRQ_ROUTING=y -CONFIG_HAVE_KVM_EVENTFD=y -CONFIG_KVM_MMIO=y -CONFIG_KVM_ASYNC_PF=y -CONFIG_HAVE_KVM_MSI=y -CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT=y -CONFIG_KVM_VFIO=y -CONFIG_KVM_GENERIC_DIRTYLOG_READ_PROTECT=y -CONFIG_KVM_COMPAT=y -CONFIG_HAVE_KVM_IRQ_BYPASS=y -CONFIG_VIRTUALIZATION=y -CONFIG_KVM=m -CONFIG_KVM_INTEL=m -CONFIG_KVM_AMD=m -CONFIG_KVM_AMD_SEV=y -CONFIG_KVM_MMU_AUDIT=y -CONFIG_VHOST_NET=m -CONFIG_VHOST_SCSI=m -CONFIG_VHOST_VSOCK=m -CONFIG_VHOST=m -# CONFIG_VHOST_CROSS_ENDIAN_LEGACY is not set - -# -# General architecture-dependent options -# -CONFIG_CRASH_CORE=y -CONFIG_KEXEC_CORE=y -CONFIG_HOTPLUG_SMT=y -CONFIG_OPROFILE=m -CONFIG_OPROFILE_EVENT_MULTIPLEX=y -CONFIG_HAVE_OPROFILE=y -CONFIG_OPROFILE_NMI_TIMER=y -CONFIG_KPROBES=y -CONFIG_JUMP_LABEL=y -# CONFIG_STATIC_KEYS_SELFTEST is not set -CONFIG_OPTPROBES=y -CONFIG_KPROBES_ON_FTRACE=y -CONFIG_UPROBES=y -CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y -CONFIG_ARCH_USE_BUILTIN_BSWAP=y -CONFIG_KRETPROBES=y -CONFIG_USER_RETURN_NOTIFIER=y -CONFIG_HAVE_IOREMAP_PROT=y -CONFIG_HAVE_KPROBES=y -CONFIG_HAVE_KRETPROBES=y -CONFIG_HAVE_OPTPROBES=y -CONFIG_HAVE_KPROBES_ON_FTRACE=y -CONFIG_HAVE_FUNCTION_ERROR_INJECTION=y -CONFIG_HAVE_NMI=y -CONFIG_HAVE_ARCH_TRACEHOOK=y -CONFIG_HAVE_DMA_CONTIGUOUS=y -CONFIG_GENERIC_SMP_IDLE_THREAD=y -CONFIG_ARCH_HAS_FORTIFY_SOURCE=y -CONFIG_ARCH_HAS_SET_MEMORY=y -CONFIG_HAVE_ARCH_THREAD_STRUCT_WHITELIST=y -CONFIG_ARCH_WANTS_DYNAMIC_TASK_STRUCT=y -CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y -CONFIG_HAVE_RSEQ=y -CONFIG_HAVE_CLK=y -CONFIG_HAVE_HW_BREAKPOINT=y -CONFIG_HAVE_MIXED_BREAKPOINTS_REGS=y -CONFIG_HAVE_USER_RETURN_NOTIFIER=y -CONFIG_HAVE_PERF_EVENTS_NMI=y -CONFIG_HAVE_HARDLOCKUP_DETECTOR_PERF=y -CONFIG_HAVE_PERF_REGS=y -CONFIG_HAVE_PERF_USER_STACK_DUMP=y -CONFIG_HAVE_ARCH_JUMP_LABEL=y -CONFIG_HAVE_RCU_TABLE_FREE=y -CONFIG_HAVE_RCU_TABLE_INVALIDATE=y -CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y -CONFIG_HAVE_CMPXCHG_LOCAL=y -CONFIG_HAVE_CMPXCHG_DOUBLE=y -CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION=y -CONFIG_ARCH_WANT_OLD_COMPAT_IPC=y -CONFIG_HAVE_ARCH_SECCOMP_FILTER=y -CONFIG_SECCOMP_FILTER=y -CONFIG_HAVE_STACKPROTECTOR=y -CONFIG_CC_HAS_STACKPROTECTOR_NONE=y -CONFIG_STACKPROTECTOR=y -CONFIG_STACKPROTECTOR_STRONG=y -CONFIG_HAVE_ARCH_WITHIN_STACK_FRAMES=y -CONFIG_HAVE_CONTEXT_TRACKING=y -CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y -CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y -CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y -CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD=y -CONFIG_HAVE_ARCH_HUGE_VMAP=y -CONFIG_HAVE_ARCH_SOFT_DIRTY=y -CONFIG_HAVE_MOD_ARCH_SPECIFIC=y -CONFIG_MODULES_USE_ELF_RELA=y -CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK=y -CONFIG_ARCH_HAS_ELF_RANDOMIZE=y -CONFIG_HAVE_ARCH_MMAP_RND_BITS=y -CONFIG_HAVE_EXIT_THREAD=y -CONFIG_ARCH_MMAP_RND_BITS=28 -CONFIG_HAVE_ARCH_MMAP_RND_COMPAT_BITS=y -CONFIG_ARCH_MMAP_RND_COMPAT_BITS=8 -CONFIG_HAVE_ARCH_COMPAT_MMAP_BASES=y -CONFIG_HAVE_COPY_THREAD_TLS=y -CONFIG_HAVE_STACK_VALIDATION=y -CONFIG_HAVE_RELIABLE_STACKTRACE=y -CONFIG_OLD_SIGSUSPEND3=y -CONFIG_COMPAT_OLD_SIGACTION=y -CONFIG_COMPAT_32BIT_TIME=y -CONFIG_HAVE_ARCH_VMAP_STACK=y -CONFIG_VMAP_STACK=y -CONFIG_ARCH_HAS_STRICT_KERNEL_RWX=y -CONFIG_STRICT_KERNEL_RWX=y -CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y -CONFIG_STRICT_MODULE_RWX=y -CONFIG_ARCH_HAS_REFCOUNT=y -# CONFIG_REFCOUNT_FULL is not set -CONFIG_HAVE_ARCH_PREL32_RELOCATIONS=y - -# -# GCOV-based kernel profiling -# -# CONFIG_GCOV_KERNEL is not set -CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y -CONFIG_PLUGIN_HOSTCC="" -CONFIG_HAVE_GCC_PLUGINS=y -CONFIG_RT_MUTEXES=y -CONFIG_BASE_SMALL=0 -CONFIG_MODULES=y -CONFIG_MODULE_FORCE_LOAD=y -CONFIG_MODULE_UNLOAD=y -CONFIG_MODULE_FORCE_UNLOAD=y -# CONFIG_MODVERSIONS is not set -# CONFIG_MODULE_SRCVERSION_ALL is not set -# CONFIG_MODULE_SIG is not set -# CONFIG_MODULE_COMPRESS is not set -CONFIG_MODULES_TREE_LOOKUP=y -CONFIG_BLOCK=y -CONFIG_BLK_SCSI_REQUEST=y -CONFIG_BLK_DEV_BSG=y -CONFIG_BLK_DEV_BSGLIB=y -CONFIG_BLK_DEV_INTEGRITY=y -# CONFIG_BLK_DEV_ZONED is not set -CONFIG_BLK_DEV_THROTTLING=y -# CONFIG_BLK_DEV_THROTTLING_LOW is not set -CONFIG_BLK_CMDLINE_PARSER=y -# CONFIG_BLK_WBT is not set -# CONFIG_BLK_CGROUP_IOLATENCY is not set -CONFIG_BLK_DEBUG_FS=y -# CONFIG_BLK_SED_OPAL is not set - -# -# Partition Types -# -CONFIG_PARTITION_ADVANCED=y -# CONFIG_ACORN_PARTITION is not set -# CONFIG_AIX_PARTITION is not set -CONFIG_OSF_PARTITION=y -CONFIG_AMIGA_PARTITION=y -# CONFIG_ATARI_PARTITION is not set -CONFIG_MAC_PARTITION=y -CONFIG_MSDOS_PARTITION=y -CONFIG_BSD_DISKLABEL=y -CONFIG_MINIX_SUBPARTITION=y -CONFIG_SOLARIS_X86_PARTITION=y -CONFIG_UNIXWARE_DISKLABEL=y -# CONFIG_LDM_PARTITION is not set -CONFIG_SGI_PARTITION=y -# CONFIG_ULTRIX_PARTITION is not set -CONFIG_SUN_PARTITION=y -CONFIG_KARMA_PARTITION=y -CONFIG_EFI_PARTITION=y -# CONFIG_SYSV68_PARTITION is not set -CONFIG_CMDLINE_PARTITION=y -CONFIG_BLOCK_COMPAT=y -CONFIG_BLK_MQ_PCI=y -CONFIG_BLK_MQ_VIRTIO=y -CONFIG_BLK_MQ_RDMA=y - -# -# IO Schedulers -# -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y -CONFIG_CFQ_GROUP_IOSCHED=y -CONFIG_DEFAULT_DEADLINE=y -# CONFIG_DEFAULT_CFQ is not set -# CONFIG_DEFAULT_NOOP is not set -CONFIG_DEFAULT_IOSCHED="deadline" -CONFIG_MQ_IOSCHED_DEADLINE=y -CONFIG_MQ_IOSCHED_KYBER=y -# CONFIG_IOSCHED_BFQ is not set -CONFIG_PREEMPT_NOTIFIERS=y -CONFIG_PADATA=y -CONFIG_ASN1=y -CONFIG_INLINE_SPIN_UNLOCK_IRQ=y -CONFIG_INLINE_READ_UNLOCK=y -CONFIG_INLINE_READ_UNLOCK_IRQ=y -CONFIG_INLINE_WRITE_UNLOCK=y -CONFIG_INLINE_WRITE_UNLOCK_IRQ=y -CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y -CONFIG_MUTEX_SPIN_ON_OWNER=y -CONFIG_RWSEM_SPIN_ON_OWNER=y -CONFIG_LOCK_SPIN_ON_OWNER=y -CONFIG_ARCH_USE_QUEUED_SPINLOCKS=y -CONFIG_QUEUED_SPINLOCKS=y -CONFIG_ARCH_USE_QUEUED_RWLOCKS=y -CONFIG_QUEUED_RWLOCKS=y -CONFIG_ARCH_HAS_SYNC_CORE_BEFORE_USERMODE=y -CONFIG_ARCH_HAS_SYSCALL_WRAPPER=y -CONFIG_FREEZER=y - -# -# Executable file formats -# -CONFIG_BINFMT_ELF=y -CONFIG_COMPAT_BINFMT_ELF=y -CONFIG_ELFCORE=y -CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y -CONFIG_BINFMT_SCRIPT=y -CONFIG_BINFMT_MISC=m -CONFIG_COREDUMP=y - -# -# Memory Management options -# -CONFIG_SELECT_MEMORY_MODEL=y -CONFIG_SPARSEMEM_MANUAL=y -CONFIG_SPARSEMEM=y -CONFIG_NEED_MULTIPLE_NODES=y -CONFIG_HAVE_MEMORY_PRESENT=y -CONFIG_SPARSEMEM_EXTREME=y -CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y -CONFIG_SPARSEMEM_VMEMMAP=y -CONFIG_HAVE_MEMBLOCK=y -CONFIG_HAVE_MEMBLOCK_NODE_MAP=y -CONFIG_ARCH_DISCARD_MEMBLOCK=y -CONFIG_MEMORY_ISOLATION=y -CONFIG_HAVE_BOOTMEM_INFO_NODE=y -CONFIG_MEMORY_HOTPLUG=y -CONFIG_MEMORY_HOTPLUG_SPARSE=y -# CONFIG_MEMORY_HOTPLUG_DEFAULT_ONLINE is not set -CONFIG_MEMORY_HOTREMOVE=y -CONFIG_SPLIT_PTLOCK_CPUS=4 -CONFIG_MEMORY_BALLOON=y -CONFIG_BALLOON_COMPACTION=y -CONFIG_COMPACTION=y -CONFIG_MIGRATION=y -CONFIG_PHYS_ADDR_T_64BIT=y -CONFIG_BOUNCE=y -CONFIG_VIRT_TO_BUS=y -CONFIG_MMU_NOTIFIER=y -CONFIG_KSM=y -CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 -CONFIG_ARCH_SUPPORTS_MEMORY_FAILURE=y -CONFIG_MEMORY_FAILURE=y -CONFIG_TRANSPARENT_HUGEPAGE=y -CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y -# CONFIG_TRANSPARENT_HUGEPAGE_MADVISE is not set -CONFIG_ARCH_WANTS_THP_SWAP=y -CONFIG_THP_SWAP=y -CONFIG_TRANSPARENT_HUGE_PAGECACHE=y -CONFIG_CLEANCACHE=y -CONFIG_FRONTSWAP=y -# CONFIG_CMA is not set -# CONFIG_ZSWAP is not set -CONFIG_ZPOOL=y -# CONFIG_ZBUD is not set -# CONFIG_Z3FOLD is not set -# CONFIG_ZSMALLOC is not set -CONFIG_GENERIC_EARLY_IOREMAP=y -# CONFIG_DEFERRED_STRUCT_PAGE_INIT is not set -# CONFIG_IDLE_PAGE_TRACKING is not set -CONFIG_ARCH_HAS_ZONE_DEVICE=y -CONFIG_ZONE_DEVICE=y -CONFIG_ARCH_HAS_HMM=y -CONFIG_DEV_PAGEMAP_OPS=y -# CONFIG_HMM_MIRROR is not set -# CONFIG_DEVICE_PRIVATE is not set -# CONFIG_DEVICE_PUBLIC is not set -CONFIG_FRAME_VECTOR=y -CONFIG_ARCH_USES_HIGH_VMA_FLAGS=y -CONFIG_ARCH_HAS_PKEYS=y -# CONFIG_PERCPU_STATS is not set -# CONFIG_GUP_BENCHMARK is not set -CONFIG_ARCH_HAS_PTE_SPECIAL=y -CONFIG_NET=y -CONFIG_COMPAT_NETLINK_MESSAGES=y -CONFIG_NET_INGRESS=y -CONFIG_NET_EGRESS=y - -# -# Networking options -# -CONFIG_PACKET=y -CONFIG_PACKET_DIAG=m -CONFIG_UNIX=y -CONFIG_UNIX_DIAG=m -# CONFIG_TLS is not set -CONFIG_XFRM=y -CONFIG_XFRM_ALGO=y -CONFIG_XFRM_USER=y -# CONFIG_XFRM_INTERFACE is not set -CONFIG_XFRM_SUB_POLICY=y -CONFIG_XFRM_MIGRATE=y -CONFIG_XFRM_STATISTICS=y -CONFIG_XFRM_IPCOMP=m -CONFIG_NET_KEY=m -CONFIG_NET_KEY_MIGRATE=y -# CONFIG_SMC is not set -# CONFIG_XDP_SOCKETS is not set -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -CONFIG_IP_ADVANCED_ROUTER=y -CONFIG_IP_FIB_TRIE_STATS=y -CONFIG_IP_MULTIPLE_TABLES=y -CONFIG_IP_ROUTE_MULTIPATH=y -CONFIG_IP_ROUTE_VERBOSE=y -CONFIG_IP_ROUTE_CLASSID=y -# CONFIG_IP_PNP is not set -CONFIG_NET_IPIP=m -CONFIG_NET_IPGRE_DEMUX=m -CONFIG_NET_IP_TUNNEL=m -CONFIG_NET_IPGRE=m -CONFIG_NET_IPGRE_BROADCAST=y -CONFIG_IP_MROUTE_COMMON=y -CONFIG_IP_MROUTE=y -CONFIG_IP_MROUTE_MULTIPLE_TABLES=y -CONFIG_IP_PIMSM_V1=y -CONFIG_IP_PIMSM_V2=y -CONFIG_SYN_COOKIES=y -CONFIG_NET_IPVTI=m -CONFIG_NET_UDP_TUNNEL=m -# CONFIG_NET_FOU is not set -# CONFIG_NET_FOU_IP_TUNNELS is not set -CONFIG_INET_AH=m -CONFIG_INET_ESP=m -# CONFIG_INET_ESP_OFFLOAD is not set -CONFIG_INET_IPCOMP=m -CONFIG_INET_XFRM_TUNNEL=m -CONFIG_INET_TUNNEL=m -CONFIG_INET_XFRM_MODE_TRANSPORT=m -CONFIG_INET_XFRM_MODE_TUNNEL=m -CONFIG_INET_XFRM_MODE_BEET=m -CONFIG_INET_DIAG=m -CONFIG_INET_TCP_DIAG=m -CONFIG_INET_UDP_DIAG=m -# CONFIG_INET_RAW_DIAG is not set -# CONFIG_INET_DIAG_DESTROY is not set -CONFIG_TCP_CONG_ADVANCED=y -CONFIG_TCP_CONG_BIC=m -CONFIG_TCP_CONG_CUBIC=y -CONFIG_TCP_CONG_WESTWOOD=m -CONFIG_TCP_CONG_HTCP=m -CONFIG_TCP_CONG_HSTCP=m -CONFIG_TCP_CONG_HYBLA=m -CONFIG_TCP_CONG_VEGAS=m -CONFIG_TCP_CONG_NV=m -CONFIG_TCP_CONG_SCALABLE=m -CONFIG_TCP_CONG_LP=m -CONFIG_TCP_CONG_VENO=m -CONFIG_TCP_CONG_YEAH=m -CONFIG_TCP_CONG_ILLINOIS=m -# CONFIG_TCP_CONG_DCTCP is not set -# CONFIG_TCP_CONG_CDG is not set -# CONFIG_TCP_CONG_BBR is not set -CONFIG_DEFAULT_CUBIC=y -# CONFIG_DEFAULT_RENO is not set -CONFIG_DEFAULT_TCP_CONG="cubic" -CONFIG_TCP_MD5SIG=y -CONFIG_IPV6=y -CONFIG_IPV6_ROUTER_PREF=y -CONFIG_IPV6_ROUTE_INFO=y -CONFIG_IPV6_OPTIMISTIC_DAD=y -CONFIG_INET6_AH=m -CONFIG_INET6_ESP=m -# CONFIG_INET6_ESP_OFFLOAD is not set -CONFIG_INET6_IPCOMP=m -CONFIG_IPV6_MIP6=y -CONFIG_IPV6_ILA=m -CONFIG_INET6_XFRM_TUNNEL=m -CONFIG_INET6_TUNNEL=m -CONFIG_INET6_XFRM_MODE_TRANSPORT=m -CONFIG_INET6_XFRM_MODE_TUNNEL=m -CONFIG_INET6_XFRM_MODE_BEET=m -CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m -CONFIG_IPV6_VTI=m -CONFIG_IPV6_SIT=m -CONFIG_IPV6_SIT_6RD=y -CONFIG_IPV6_NDISC_NODETYPE=y -CONFIG_IPV6_TUNNEL=m -CONFIG_IPV6_GRE=m -CONFIG_IPV6_MULTIPLE_TABLES=y -CONFIG_IPV6_SUBTREES=y -CONFIG_IPV6_MROUTE=y -CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y -CONFIG_IPV6_PIMSM_V2=y -# CONFIG_IPV6_SEG6_LWTUNNEL is not set -# CONFIG_IPV6_SEG6_HMAC is not set -CONFIG_NETLABEL=y -CONFIG_NETWORK_SECMARK=y -CONFIG_NET_PTP_CLASSIFY=y -CONFIG_NETWORK_PHY_TIMESTAMPING=y -CONFIG_NETFILTER=y -CONFIG_NETFILTER_ADVANCED=y -CONFIG_BRIDGE_NETFILTER=m - -# -# Core Netfilter Configuration -# -CONFIG_NETFILTER_INGRESS=y -CONFIG_NETFILTER_NETLINK=m -CONFIG_NETFILTER_FAMILY_BRIDGE=y -CONFIG_NETFILTER_FAMILY_ARP=y -CONFIG_NETFILTER_NETLINK_ACCT=m -CONFIG_NETFILTER_NETLINK_QUEUE=m -CONFIG_NETFILTER_NETLINK_LOG=m -CONFIG_NETFILTER_NETLINK_OSF=m -CONFIG_NF_CONNTRACK=m -CONFIG_NF_LOG_COMMON=m -# CONFIG_NF_LOG_NETDEV is not set -CONFIG_NETFILTER_CONNCOUNT=m -CONFIG_NF_CONNTRACK_MARK=y -CONFIG_NF_CONNTRACK_SECMARK=y -CONFIG_NF_CONNTRACK_ZONES=y -CONFIG_NF_CONNTRACK_PROCFS=y -CONFIG_NF_CONNTRACK_EVENTS=y -# CONFIG_NF_CONNTRACK_TIMEOUT is not set -CONFIG_NF_CONNTRACK_TIMESTAMP=y -CONFIG_NF_CONNTRACK_LABELS=y -CONFIG_NF_CT_PROTO_DCCP=y -CONFIG_NF_CT_PROTO_GRE=m -CONFIG_NF_CT_PROTO_SCTP=y -CONFIG_NF_CT_PROTO_UDPLITE=y -CONFIG_NF_CONNTRACK_AMANDA=m -CONFIG_NF_CONNTRACK_FTP=m -CONFIG_NF_CONNTRACK_H323=m -CONFIG_NF_CONNTRACK_IRC=m -CONFIG_NF_CONNTRACK_BROADCAST=m -CONFIG_NF_CONNTRACK_NETBIOS_NS=m -CONFIG_NF_CONNTRACK_SNMP=m -CONFIG_NF_CONNTRACK_PPTP=m -CONFIG_NF_CONNTRACK_SANE=m -CONFIG_NF_CONNTRACK_SIP=m -CONFIG_NF_CONNTRACK_TFTP=m -CONFIG_NF_CT_NETLINK=m -# CONFIG_NETFILTER_NETLINK_GLUE_CT is not set -CONFIG_NF_NAT=m -CONFIG_NF_NAT_NEEDED=y -CONFIG_NF_NAT_PROTO_DCCP=y -CONFIG_NF_NAT_PROTO_UDPLITE=y -CONFIG_NF_NAT_PROTO_SCTP=y -CONFIG_NF_NAT_AMANDA=m -CONFIG_NF_NAT_FTP=m -CONFIG_NF_NAT_IRC=m -CONFIG_NF_NAT_SIP=m -CONFIG_NF_NAT_TFTP=m -CONFIG_NF_NAT_REDIRECT=y -CONFIG_NF_TABLES=m -# CONFIG_NF_TABLES_SET is not set -# CONFIG_NF_TABLES_INET is not set -# CONFIG_NF_TABLES_NETDEV is not set -# CONFIG_NFT_NUMGEN is not set -CONFIG_NFT_CT=m -CONFIG_NFT_COUNTER=m -# CONFIG_NFT_CONNLIMIT is not set -CONFIG_NFT_LOG=m -CONFIG_NFT_LIMIT=m -# CONFIG_NFT_MASQ is not set -# CONFIG_NFT_REDIR is not set -CONFIG_NFT_NAT=m -# CONFIG_NFT_TUNNEL is not set -# CONFIG_NFT_OBJREF is not set -CONFIG_NFT_QUEUE=m -# CONFIG_NFT_QUOTA is not set -CONFIG_NFT_REJECT=m -CONFIG_NFT_COMPAT=m -CONFIG_NFT_HASH=m -# CONFIG_NFT_SOCKET is not set -# CONFIG_NFT_OSF is not set -# CONFIG_NFT_TPROXY is not set -# CONFIG_NF_FLOW_TABLE is not set -CONFIG_NETFILTER_XTABLES=y - -# -# Xtables combined modules -# -CONFIG_NETFILTER_XT_MARK=m -CONFIG_NETFILTER_XT_CONNMARK=m -CONFIG_NETFILTER_XT_SET=m - -# -# Xtables targets -# -CONFIG_NETFILTER_XT_TARGET_AUDIT=m -CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m -CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m -CONFIG_NETFILTER_XT_TARGET_CONNMARK=m -CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m -CONFIG_NETFILTER_XT_TARGET_CT=m -CONFIG_NETFILTER_XT_TARGET_DSCP=m -CONFIG_NETFILTER_XT_TARGET_HL=m -CONFIG_NETFILTER_XT_TARGET_HMARK=m -CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m -CONFIG_NETFILTER_XT_TARGET_LED=m -CONFIG_NETFILTER_XT_TARGET_LOG=m -CONFIG_NETFILTER_XT_TARGET_MARK=m -CONFIG_NETFILTER_XT_NAT=m -CONFIG_NETFILTER_XT_TARGET_NETMAP=m -CONFIG_NETFILTER_XT_TARGET_NFLOG=m -CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m -CONFIG_NETFILTER_XT_TARGET_NOTRACK=m -CONFIG_NETFILTER_XT_TARGET_RATEEST=m -CONFIG_NETFILTER_XT_TARGET_REDIRECT=m -CONFIG_NETFILTER_XT_TARGET_TEE=m -CONFIG_NETFILTER_XT_TARGET_TPROXY=m -CONFIG_NETFILTER_XT_TARGET_TRACE=m -CONFIG_NETFILTER_XT_TARGET_SECMARK=m -CONFIG_NETFILTER_XT_TARGET_TCPMSS=m -CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m - -# -# Xtables matches -# -CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m -CONFIG_NETFILTER_XT_MATCH_BPF=m -CONFIG_NETFILTER_XT_MATCH_CGROUP=m -CONFIG_NETFILTER_XT_MATCH_CLUSTER=m -CONFIG_NETFILTER_XT_MATCH_COMMENT=m -CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m -CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m -CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m -CONFIG_NETFILTER_XT_MATCH_CONNMARK=m -CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m -CONFIG_NETFILTER_XT_MATCH_CPU=m -CONFIG_NETFILTER_XT_MATCH_DCCP=m -CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m -CONFIG_NETFILTER_XT_MATCH_DSCP=m -CONFIG_NETFILTER_XT_MATCH_ECN=m -CONFIG_NETFILTER_XT_MATCH_ESP=m -CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m -CONFIG_NETFILTER_XT_MATCH_HELPER=m -CONFIG_NETFILTER_XT_MATCH_HL=m -CONFIG_NETFILTER_XT_MATCH_IPCOMP=m -CONFIG_NETFILTER_XT_MATCH_IPRANGE=m -CONFIG_NETFILTER_XT_MATCH_IPVS=m -CONFIG_NETFILTER_XT_MATCH_L2TP=m -CONFIG_NETFILTER_XT_MATCH_LENGTH=m -CONFIG_NETFILTER_XT_MATCH_LIMIT=m -CONFIG_NETFILTER_XT_MATCH_MAC=m -CONFIG_NETFILTER_XT_MATCH_MARK=m -CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m -CONFIG_NETFILTER_XT_MATCH_NFACCT=m -CONFIG_NETFILTER_XT_MATCH_OSF=m -CONFIG_NETFILTER_XT_MATCH_OWNER=m -CONFIG_NETFILTER_XT_MATCH_POLICY=m -CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m -CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m -CONFIG_NETFILTER_XT_MATCH_QUOTA=m -CONFIG_NETFILTER_XT_MATCH_RATEEST=m -CONFIG_NETFILTER_XT_MATCH_REALM=m -CONFIG_NETFILTER_XT_MATCH_RECENT=m -CONFIG_NETFILTER_XT_MATCH_SCTP=m -# CONFIG_NETFILTER_XT_MATCH_SOCKET is not set -CONFIG_NETFILTER_XT_MATCH_STATE=m -CONFIG_NETFILTER_XT_MATCH_STATISTIC=m -CONFIG_NETFILTER_XT_MATCH_STRING=m -CONFIG_NETFILTER_XT_MATCH_TCPMSS=m -CONFIG_NETFILTER_XT_MATCH_TIME=m -CONFIG_NETFILTER_XT_MATCH_U32=m -CONFIG_IP_SET=m -CONFIG_IP_SET_MAX=256 -CONFIG_IP_SET_BITMAP_IP=m -CONFIG_IP_SET_BITMAP_IPMAC=m -CONFIG_IP_SET_BITMAP_PORT=m -CONFIG_IP_SET_HASH_IP=m -CONFIG_IP_SET_HASH_IPMARK=m -CONFIG_IP_SET_HASH_IPPORT=m -CONFIG_IP_SET_HASH_IPPORTIP=m -CONFIG_IP_SET_HASH_IPPORTNET=m -# CONFIG_IP_SET_HASH_IPMAC is not set -# CONFIG_IP_SET_HASH_MAC is not set -CONFIG_IP_SET_HASH_NETPORTNET=m -CONFIG_IP_SET_HASH_NET=m -CONFIG_IP_SET_HASH_NETNET=m -CONFIG_IP_SET_HASH_NETPORT=m -CONFIG_IP_SET_HASH_NETIFACE=m -CONFIG_IP_SET_LIST_SET=m -CONFIG_IP_VS=m -CONFIG_IP_VS_IPV6=y -# CONFIG_IP_VS_DEBUG is not set -CONFIG_IP_VS_TAB_BITS=12 - -# -# IPVS transport protocol load balancing support -# -CONFIG_IP_VS_PROTO_TCP=y -CONFIG_IP_VS_PROTO_UDP=y -CONFIG_IP_VS_PROTO_AH_ESP=y -CONFIG_IP_VS_PROTO_ESP=y -CONFIG_IP_VS_PROTO_AH=y -CONFIG_IP_VS_PROTO_SCTP=y - -# -# IPVS scheduler -# -CONFIG_IP_VS_RR=m -CONFIG_IP_VS_WRR=m -CONFIG_IP_VS_LC=m -CONFIG_IP_VS_WLC=m -# CONFIG_IP_VS_FO is not set -CONFIG_IP_VS_OVF=m -CONFIG_IP_VS_LBLC=m -CONFIG_IP_VS_LBLCR=m -CONFIG_IP_VS_DH=m -CONFIG_IP_VS_SH=m -# CONFIG_IP_VS_MH is not set -CONFIG_IP_VS_SED=m -CONFIG_IP_VS_NQ=m - -# -# IPVS SH scheduler -# -CONFIG_IP_VS_SH_TAB_BITS=8 - -# -# IPVS MH scheduler -# -CONFIG_IP_VS_MH_TAB_INDEX=12 - -# -# IPVS application helper -# -CONFIG_IP_VS_FTP=m -CONFIG_IP_VS_NFCT=y -CONFIG_IP_VS_PE_SIP=m - -# -# IP: Netfilter Configuration -# -CONFIG_NF_DEFRAG_IPV4=m -# CONFIG_NF_SOCKET_IPV4 is not set -CONFIG_NF_TPROXY_IPV4=m -# CONFIG_NF_TABLES_IPV4 is not set -# CONFIG_NF_TABLES_ARP is not set -CONFIG_NF_DUP_IPV4=m -CONFIG_NF_LOG_ARP=m -CONFIG_NF_LOG_IPV4=m -CONFIG_NF_REJECT_IPV4=y -CONFIG_NF_NAT_IPV4=m -CONFIG_NF_NAT_MASQUERADE_IPV4=y -CONFIG_NF_NAT_SNMP_BASIC=m -CONFIG_NF_NAT_PROTO_GRE=m -CONFIG_NF_NAT_PPTP=m -CONFIG_NF_NAT_H323=m -CONFIG_IP_NF_IPTABLES=y -CONFIG_IP_NF_MATCH_AH=m -CONFIG_IP_NF_MATCH_ECN=m -CONFIG_IP_NF_MATCH_RPFILTER=m -CONFIG_IP_NF_MATCH_TTL=m -CONFIG_IP_NF_FILTER=y -CONFIG_IP_NF_TARGET_REJECT=y -# CONFIG_IP_NF_TARGET_SYNPROXY is not set -CONFIG_IP_NF_NAT=m -CONFIG_IP_NF_TARGET_MASQUERADE=m -CONFIG_IP_NF_TARGET_NETMAP=m -CONFIG_IP_NF_TARGET_REDIRECT=m -CONFIG_IP_NF_MANGLE=m -CONFIG_IP_NF_TARGET_CLUSTERIP=m -CONFIG_IP_NF_TARGET_ECN=m -CONFIG_IP_NF_TARGET_TTL=m -CONFIG_IP_NF_RAW=m -CONFIG_IP_NF_SECURITY=m -CONFIG_IP_NF_ARPTABLES=m -CONFIG_IP_NF_ARPFILTER=m -CONFIG_IP_NF_ARP_MANGLE=m - -# -# IPv6: Netfilter Configuration -# -# CONFIG_NF_SOCKET_IPV6 is not set -CONFIG_NF_TPROXY_IPV6=m -# CONFIG_NF_TABLES_IPV6 is not set -CONFIG_NF_DUP_IPV6=m -CONFIG_NF_REJECT_IPV6=m -CONFIG_NF_LOG_IPV6=m -CONFIG_NF_NAT_IPV6=m -CONFIG_NF_NAT_MASQUERADE_IPV6=y -CONFIG_IP6_NF_IPTABLES=m -CONFIG_IP6_NF_MATCH_AH=m -CONFIG_IP6_NF_MATCH_EUI64=m -CONFIG_IP6_NF_MATCH_FRAG=m -CONFIG_IP6_NF_MATCH_OPTS=m -CONFIG_IP6_NF_MATCH_HL=m -CONFIG_IP6_NF_MATCH_IPV6HEADER=m -CONFIG_IP6_NF_MATCH_MH=m -CONFIG_IP6_NF_MATCH_RPFILTER=m -CONFIG_IP6_NF_MATCH_RT=m -# CONFIG_IP6_NF_MATCH_SRH is not set -CONFIG_IP6_NF_TARGET_HL=m -CONFIG_IP6_NF_FILTER=m -CONFIG_IP6_NF_TARGET_REJECT=m -# CONFIG_IP6_NF_TARGET_SYNPROXY is not set -CONFIG_IP6_NF_MANGLE=m -CONFIG_IP6_NF_RAW=m -CONFIG_IP6_NF_SECURITY=m -CONFIG_IP6_NF_NAT=m -CONFIG_IP6_NF_TARGET_MASQUERADE=m -CONFIG_IP6_NF_TARGET_NPT=m -CONFIG_NF_DEFRAG_IPV6=m -# CONFIG_NF_TABLES_BRIDGE is not set -CONFIG_BRIDGE_NF_EBTABLES=m -CONFIG_BRIDGE_EBT_BROUTE=m -CONFIG_BRIDGE_EBT_T_FILTER=m -CONFIG_BRIDGE_EBT_T_NAT=m -CONFIG_BRIDGE_EBT_802_3=m -CONFIG_BRIDGE_EBT_AMONG=m -CONFIG_BRIDGE_EBT_ARP=m -CONFIG_BRIDGE_EBT_IP=m -CONFIG_BRIDGE_EBT_IP6=m -CONFIG_BRIDGE_EBT_LIMIT=m -CONFIG_BRIDGE_EBT_MARK=m -CONFIG_BRIDGE_EBT_PKTTYPE=m -CONFIG_BRIDGE_EBT_STP=m -CONFIG_BRIDGE_EBT_VLAN=m -CONFIG_BRIDGE_EBT_ARPREPLY=m -CONFIG_BRIDGE_EBT_DNAT=m -CONFIG_BRIDGE_EBT_MARK_T=m -CONFIG_BRIDGE_EBT_REDIRECT=m -CONFIG_BRIDGE_EBT_SNAT=m -CONFIG_BRIDGE_EBT_LOG=m -CONFIG_BRIDGE_EBT_NFLOG=m -# CONFIG_BPFILTER is not set -CONFIG_IP_DCCP=m -CONFIG_INET_DCCP_DIAG=m - -# -# DCCP CCIDs Configuration -# -# CONFIG_IP_DCCP_CCID2_DEBUG is not set -CONFIG_IP_DCCP_CCID3=y -# CONFIG_IP_DCCP_CCID3_DEBUG is not set -CONFIG_IP_DCCP_TFRC_LIB=y -CONFIG_IP_SCTP=m -# CONFIG_SCTP_DBG_OBJCNT is not set -CONFIG_SCTP_DEFAULT_COOKIE_HMAC_MD5=y -# CONFIG_SCTP_DEFAULT_COOKIE_HMAC_SHA1 is not set -# CONFIG_SCTP_DEFAULT_COOKIE_HMAC_NONE is not set -CONFIG_SCTP_COOKIE_HMAC_MD5=y -CONFIG_SCTP_COOKIE_HMAC_SHA1=y -CONFIG_INET_SCTP_DIAG=m -CONFIG_RDS=m -CONFIG_RDS_RDMA=m -CONFIG_RDS_TCP=m -# CONFIG_RDS_DEBUG is not set -# CONFIG_TIPC is not set -CONFIG_ATM=m -CONFIG_ATM_CLIP=m -# CONFIG_ATM_CLIP_NO_ICMP is not set -CONFIG_ATM_LANE=m -# CONFIG_ATM_MPOA is not set -CONFIG_ATM_BR2684=m -# CONFIG_ATM_BR2684_IPFILTER is not set -CONFIG_L2TP=m -CONFIG_L2TP_DEBUGFS=m -CONFIG_L2TP_V3=y -CONFIG_L2TP_IP=m -CONFIG_L2TP_ETH=m -CONFIG_STP=m -CONFIG_GARP=m -CONFIG_MRP=m -CONFIG_BRIDGE=m -CONFIG_BRIDGE_IGMP_SNOOPING=y -CONFIG_BRIDGE_VLAN_FILTERING=y -CONFIG_HAVE_NET_DSA=y -CONFIG_NET_DSA=m -CONFIG_NET_DSA_LEGACY=y -CONFIG_NET_DSA_TAG_BRCM=y -CONFIG_NET_DSA_TAG_BRCM_PREPEND=y -CONFIG_NET_DSA_TAG_DSA=y -CONFIG_NET_DSA_TAG_EDSA=y -CONFIG_NET_DSA_TAG_TRAILER=y -CONFIG_NET_DSA_TAG_QCA=y -CONFIG_VLAN_8021Q=m -CONFIG_VLAN_8021Q_GVRP=y -CONFIG_VLAN_8021Q_MVRP=y -# CONFIG_DECNET is not set -CONFIG_LLC=m -# CONFIG_LLC2 is not set -CONFIG_ATALK=m -CONFIG_DEV_APPLETALK=m -CONFIG_IPDDP=m -CONFIG_IPDDP_ENCAP=y -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_PHONET is not set -CONFIG_6LOWPAN=m -# CONFIG_6LOWPAN_DEBUGFS is not set -CONFIG_6LOWPAN_NHC=m -CONFIG_6LOWPAN_NHC_DEST=m -CONFIG_6LOWPAN_NHC_FRAGMENT=m -CONFIG_6LOWPAN_NHC_HOP=m -CONFIG_6LOWPAN_NHC_IPV6=m -CONFIG_6LOWPAN_NHC_MOBILITY=m -CONFIG_6LOWPAN_NHC_ROUTING=m -CONFIG_6LOWPAN_NHC_UDP=m -# CONFIG_6LOWPAN_GHC_EXT_HDR_HOP is not set -# CONFIG_6LOWPAN_GHC_UDP is not set -# CONFIG_6LOWPAN_GHC_ICMPV6 is not set -# CONFIG_6LOWPAN_GHC_EXT_HDR_DEST is not set -# CONFIG_6LOWPAN_GHC_EXT_HDR_FRAG is not set -# CONFIG_6LOWPAN_GHC_EXT_HDR_ROUTE is not set -CONFIG_IEEE802154=m -# CONFIG_IEEE802154_NL802154_EXPERIMENTAL is not set -CONFIG_IEEE802154_SOCKET=m -CONFIG_IEEE802154_6LOWPAN=m -CONFIG_MAC802154=m -CONFIG_NET_SCHED=y - -# -# Queueing/Scheduling -# -CONFIG_NET_SCH_CBQ=m -CONFIG_NET_SCH_HTB=m -CONFIG_NET_SCH_HFSC=m -CONFIG_NET_SCH_ATM=m -CONFIG_NET_SCH_PRIO=m -CONFIG_NET_SCH_MULTIQ=m -CONFIG_NET_SCH_RED=m -CONFIG_NET_SCH_SFB=m -CONFIG_NET_SCH_SFQ=m -CONFIG_NET_SCH_TEQL=m -CONFIG_NET_SCH_TBF=m -# CONFIG_NET_SCH_CBS is not set -# CONFIG_NET_SCH_ETF is not set -CONFIG_NET_SCH_GRED=m -CONFIG_NET_SCH_DSMARK=m -CONFIG_NET_SCH_NETEM=m -CONFIG_NET_SCH_DRR=m -CONFIG_NET_SCH_MQPRIO=m -# CONFIG_NET_SCH_SKBPRIO is not set -CONFIG_NET_SCH_CHOKE=m -CONFIG_NET_SCH_QFQ=m -CONFIG_NET_SCH_CODEL=m -CONFIG_NET_SCH_FQ_CODEL=m -# CONFIG_NET_SCH_CAKE is not set -# CONFIG_NET_SCH_FQ is not set -CONFIG_NET_SCH_HHF=m -CONFIG_NET_SCH_PIE=m -CONFIG_NET_SCH_INGRESS=m -CONFIG_NET_SCH_PLUG=m -# CONFIG_NET_SCH_DEFAULT is not set - -# -# Classification -# -CONFIG_NET_CLS=y -CONFIG_NET_CLS_BASIC=m -CONFIG_NET_CLS_TCINDEX=m -CONFIG_NET_CLS_ROUTE4=m -CONFIG_NET_CLS_FW=m -CONFIG_NET_CLS_U32=m -CONFIG_CLS_U32_PERF=y -CONFIG_CLS_U32_MARK=y -CONFIG_NET_CLS_RSVP=m -CONFIG_NET_CLS_RSVP6=m -CONFIG_NET_CLS_FLOW=m -CONFIG_NET_CLS_CGROUP=y -CONFIG_NET_CLS_BPF=m -# CONFIG_NET_CLS_FLOWER is not set -CONFIG_NET_CLS_MATCHALL=m -CONFIG_NET_EMATCH=y -CONFIG_NET_EMATCH_STACK=32 -CONFIG_NET_EMATCH_CMP=m -CONFIG_NET_EMATCH_NBYTE=m -CONFIG_NET_EMATCH_U32=m -CONFIG_NET_EMATCH_META=m -CONFIG_NET_EMATCH_TEXT=m -CONFIG_NET_EMATCH_IPSET=m -# CONFIG_NET_EMATCH_IPT is not set -CONFIG_NET_CLS_ACT=y -CONFIG_NET_ACT_POLICE=m -CONFIG_NET_ACT_GACT=m -CONFIG_GACT_PROB=y -CONFIG_NET_ACT_MIRRED=m -# CONFIG_NET_ACT_SAMPLE is not set -CONFIG_NET_ACT_IPT=m -CONFIG_NET_ACT_NAT=m -CONFIG_NET_ACT_PEDIT=m -CONFIG_NET_ACT_SIMP=m -CONFIG_NET_ACT_SKBEDIT=m -CONFIG_NET_ACT_CSUM=m -# CONFIG_NET_ACT_VLAN is not set -CONFIG_NET_ACT_BPF=m -CONFIG_NET_ACT_CONNMARK=m -# CONFIG_NET_ACT_SKBMOD is not set -# CONFIG_NET_ACT_IFE is not set -# CONFIG_NET_ACT_TUNNEL_KEY is not set -CONFIG_NET_CLS_IND=y -CONFIG_NET_SCH_FIFO=y -CONFIG_DCB=y -CONFIG_DNS_RESOLVER=y -CONFIG_BATMAN_ADV=m -# CONFIG_BATMAN_ADV_BATMAN_V is not set -CONFIG_BATMAN_ADV_BLA=y -CONFIG_BATMAN_ADV_DAT=y -# CONFIG_BATMAN_ADV_NC is not set -# CONFIG_BATMAN_ADV_MCAST is not set -CONFIG_BATMAN_ADV_DEBUGFS=y -# CONFIG_BATMAN_ADV_DEBUG is not set -CONFIG_OPENVSWITCH=m -CONFIG_OPENVSWITCH_GRE=m -CONFIG_OPENVSWITCH_VXLAN=m -CONFIG_OPENVSWITCH_GENEVE=m -CONFIG_VSOCKETS=m -CONFIG_VSOCKETS_DIAG=m -CONFIG_VMWARE_VMCI_VSOCKETS=m -CONFIG_VIRTIO_VSOCKETS=m -CONFIG_VIRTIO_VSOCKETS_COMMON=m -# CONFIG_HYPERV_VSOCKETS is not set -CONFIG_NETLINK_DIAG=m -CONFIG_MPLS=y -CONFIG_NET_MPLS_GSO=m -CONFIG_MPLS_ROUTING=m -CONFIG_MPLS_IPTUNNEL=m -CONFIG_NET_NSH=m -CONFIG_HSR=m -CONFIG_NET_SWITCHDEV=y -CONFIG_NET_L3_MASTER_DEV=y -# CONFIG_NET_NCSI is not set -CONFIG_RPS=y -CONFIG_RFS_ACCEL=y -CONFIG_XPS=y -CONFIG_CGROUP_NET_PRIO=y -CONFIG_CGROUP_NET_CLASSID=y -CONFIG_NET_RX_BUSY_POLL=y -CONFIG_BQL=y -CONFIG_BPF_JIT=y -# CONFIG_BPF_STREAM_PARSER is not set -CONFIG_NET_FLOW_LIMIT=y - -# -# Network testing -# -CONFIG_NET_PKTGEN=m -CONFIG_NET_DROP_MONITOR=y -CONFIG_HAMRADIO=y - -# -# Packet Radio protocols -# -CONFIG_AX25=m -CONFIG_AX25_DAMA_SLAVE=y -CONFIG_NETROM=m -CONFIG_ROSE=m - -# -# AX.25 network device drivers -# -CONFIG_MKISS=m -CONFIG_6PACK=m -CONFIG_BPQETHER=m -CONFIG_BAYCOM_SER_FDX=m -CONFIG_BAYCOM_SER_HDX=m -CONFIG_BAYCOM_PAR=m -CONFIG_YAM=m -# CONFIG_CAN is not set -CONFIG_BT=m -CONFIG_BT_BREDR=y -CONFIG_BT_RFCOMM=m -CONFIG_BT_RFCOMM_TTY=y -CONFIG_BT_BNEP=m -CONFIG_BT_BNEP_MC_FILTER=y -CONFIG_BT_BNEP_PROTO_FILTER=y -CONFIG_BT_CMTP=m -CONFIG_BT_HIDP=m -CONFIG_BT_HS=y -CONFIG_BT_LE=y -CONFIG_BT_6LOWPAN=m -# CONFIG_BT_LEDS is not set -CONFIG_BT_DEBUGFS=y - -# -# Bluetooth device drivers -# -CONFIG_BT_INTEL=m -CONFIG_BT_BCM=m -CONFIG_BT_RTL=m -CONFIG_BT_HCIBTUSB=m -# CONFIG_BT_HCIBTUSB_AUTOSUSPEND is not set -CONFIG_BT_HCIBTUSB_BCM=y -CONFIG_BT_HCIBTUSB_RTL=y -CONFIG_BT_HCIBTSDIO=m -CONFIG_BT_HCIUART=m -CONFIG_BT_HCIUART_H4=y -CONFIG_BT_HCIUART_BCSP=y -CONFIG_BT_HCIUART_ATH3K=y -CONFIG_BT_HCIUART_INTEL=y -# CONFIG_BT_HCIUART_AG6XX is not set -# CONFIG_BT_HCIUART_MRVL is not set -CONFIG_BT_HCIBCM203X=m -CONFIG_BT_HCIBPA10X=m -CONFIG_BT_HCIBFUSB=m -CONFIG_BT_HCIDTL1=m -CONFIG_BT_HCIBT3C=m -CONFIG_BT_HCIBLUECARD=m -CONFIG_BT_HCIVHCI=m -CONFIG_BT_MRVL=m -CONFIG_BT_MRVL_SDIO=m -CONFIG_BT_ATH3K=m -CONFIG_BT_WILINK=m -CONFIG_BT_HCIRSI=m -# CONFIG_AF_RXRPC is not set -# CONFIG_AF_KCM is not set -CONFIG_FIB_RULES=y -CONFIG_WIRELESS=y -CONFIG_WIRELESS_EXT=y -CONFIG_WEXT_CORE=y -CONFIG_WEXT_PROC=y -CONFIG_WEXT_SPY=y -CONFIG_WEXT_PRIV=y -CONFIG_CFG80211=m -# CONFIG_NL80211_TESTMODE is not set -# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set -CONFIG_CFG80211_REQUIRE_SIGNED_REGDB=y -CONFIG_CFG80211_USE_KERNEL_REGDB_KEYS=y -# CONFIG_CFG80211_DEFAULT_PS is not set -CONFIG_CFG80211_DEBUGFS=y -CONFIG_CFG80211_CRDA_SUPPORT=y -CONFIG_CFG80211_WEXT=y -CONFIG_CFG80211_WEXT_EXPORT=y -CONFIG_LIB80211=m -CONFIG_LIB80211_CRYPT_WEP=m -CONFIG_LIB80211_CRYPT_CCMP=m -CONFIG_LIB80211_CRYPT_TKIP=m -# CONFIG_LIB80211_DEBUG is not set -CONFIG_MAC80211=m -CONFIG_MAC80211_HAS_RC=y -CONFIG_MAC80211_RC_MINSTREL=y -CONFIG_MAC80211_RC_MINSTREL_HT=y -CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y -CONFIG_MAC80211_RC_DEFAULT="minstrel_ht" -CONFIG_MAC80211_MESH=y -CONFIG_MAC80211_LEDS=y -CONFIG_MAC80211_DEBUGFS=y -CONFIG_MAC80211_MESSAGE_TRACING=y -# CONFIG_MAC80211_DEBUG_MENU is not set -CONFIG_MAC80211_STA_HASH_MAX_SIZE=0 -CONFIG_WIMAX=m -CONFIG_WIMAX_DEBUG_LEVEL=8 -CONFIG_RFKILL=m -CONFIG_RFKILL_LEDS=y -CONFIG_RFKILL_INPUT=y -CONFIG_RFKILL_GPIO=m -CONFIG_NET_9P=m -CONFIG_NET_9P_VIRTIO=m -# CONFIG_NET_9P_XEN is not set -CONFIG_NET_9P_RDMA=m -# CONFIG_NET_9P_DEBUG is not set -# CONFIG_CAIF is not set -CONFIG_CEPH_LIB=m -# CONFIG_CEPH_LIB_PRETTYDEBUG is not set -# CONFIG_CEPH_LIB_USE_DNS_RESOLVER is not set -CONFIG_NFC=m -CONFIG_NFC_DIGITAL=m -CONFIG_NFC_NCI=m -# CONFIG_NFC_NCI_UART is not set -CONFIG_NFC_HCI=m -CONFIG_NFC_SHDLC=y - -# -# Near Field Communication (NFC) devices -# -CONFIG_NFC_MEI_PHY=m -# CONFIG_NFC_SIM is not set -CONFIG_NFC_PORT100=m -CONFIG_NFC_FDP=m -CONFIG_NFC_FDP_I2C=m -CONFIG_NFC_PN544=m -CONFIG_NFC_PN544_I2C=m -CONFIG_NFC_PN544_MEI=m -# CONFIG_NFC_PN533_USB is not set -# CONFIG_NFC_PN533_I2C is not set -CONFIG_NFC_MICROREAD=m -CONFIG_NFC_MICROREAD_I2C=m -CONFIG_NFC_MICROREAD_MEI=m -CONFIG_NFC_MRVL=m -CONFIG_NFC_MRVL_USB=m -CONFIG_NFC_MRVL_I2C=m -CONFIG_NFC_ST21NFCA=m -CONFIG_NFC_ST21NFCA_I2C=m -# CONFIG_NFC_ST_NCI_I2C is not set -# CONFIG_NFC_NXP_NCI is not set -CONFIG_NFC_S3FWRN5=m -CONFIG_NFC_S3FWRN5_I2C=m -# CONFIG_PSAMPLE is not set -# CONFIG_NET_IFE is not set -CONFIG_LWTUNNEL=y -CONFIG_LWTUNNEL_BPF=y -CONFIG_DST_CACHE=y -CONFIG_GRO_CELLS=y -# CONFIG_NET_DEVLINK is not set -CONFIG_MAY_USE_DEVLINK=y -CONFIG_FAILOVER=m -CONFIG_HAVE_EBPF_JIT=y - -# -# Device Drivers -# - -# -# Generic Driver Options -# -CONFIG_UEVENT_HELPER=y -CONFIG_UEVENT_HELPER_PATH="" -CONFIG_DEVTMPFS=y -CONFIG_DEVTMPFS_MOUNT=y -CONFIG_STANDALONE=y -CONFIG_PREVENT_FIRMWARE_BUILD=y - -# -# Firmware loader -# -CONFIG_FW_LOADER=y -CONFIG_EXTRA_FIRMWARE="" -CONFIG_FW_LOADER_USER_HELPER=y -CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y -CONFIG_WANT_DEV_COREDUMP=y -CONFIG_ALLOW_DEV_COREDUMP=y -CONFIG_DEV_COREDUMP=y -# CONFIG_TEST_ASYNC_DRIVER_PROBE is not set -CONFIG_SYS_HYPERVISOR=y -CONFIG_GENERIC_CPU_AUTOPROBE=y -CONFIG_GENERIC_CPU_VULNERABILITIES=y -CONFIG_REGMAP=y -CONFIG_REGMAP_I2C=m -CONFIG_REGMAP_MMIO=y -CONFIG_REGMAP_IRQ=y -CONFIG_DMA_SHARED_BUFFER=y -# CONFIG_DMA_FENCE_TRACE is not set - -# -# Bus devices -# -CONFIG_CONNECTOR=y -CONFIG_PROC_EVENTS=y -# CONFIG_GNSS is not set -CONFIG_MTD=m -# CONFIG_MTD_TESTS is not set -# CONFIG_MTD_REDBOOT_PARTS is not set -# CONFIG_MTD_CMDLINE_PARTS is not set -# CONFIG_MTD_AR7_PARTS is not set - -# -# Partition parsers -# - -# -# User Modules And Translation Layers -# -# CONFIG_MTD_BLOCK is not set -# CONFIG_MTD_BLOCK_RO is not set -# CONFIG_FTL is not set -# CONFIG_NFTL is not set -# CONFIG_INFTL is not set -# CONFIG_RFD_FTL is not set -# CONFIG_SSFDC is not set -# CONFIG_SM_FTL is not set -# CONFIG_MTD_OOPS is not set -# CONFIG_MTD_SWAP is not set -CONFIG_MTD_PARTITIONED_MASTER=y - -# -# RAM/ROM/Flash chip drivers -# -# CONFIG_MTD_CFI is not set -# CONFIG_MTD_JEDECPROBE is not set -CONFIG_MTD_MAP_BANK_WIDTH_1=y -CONFIG_MTD_MAP_BANK_WIDTH_2=y -CONFIG_MTD_MAP_BANK_WIDTH_4=y -CONFIG_MTD_CFI_I1=y -CONFIG_MTD_CFI_I2=y -# CONFIG_MTD_RAM is not set -# CONFIG_MTD_ROM is not set -# CONFIG_MTD_ABSENT is not set - -# -# Mapping drivers for chip access -# -# CONFIG_MTD_COMPLEX_MAPPINGS is not set -# CONFIG_MTD_INTEL_VR_NOR is not set -# CONFIG_MTD_PLATRAM is not set - -# -# Self-contained MTD device drivers -# -# CONFIG_MTD_PMC551 is not set -# CONFIG_MTD_SLRAM is not set -# CONFIG_MTD_PHRAM is not set -# CONFIG_MTD_MTDRAM is not set -# CONFIG_MTD_BLOCK2MTD is not set - -# -# Disk-On-Chip Device Drivers -# -# CONFIG_MTD_DOCG3 is not set -# CONFIG_MTD_ONENAND is not set -# CONFIG_MTD_NAND is not set - -# -# LPDDR & LPDDR2 PCM memory drivers -# -# CONFIG_MTD_LPDDR is not set -CONFIG_MTD_SPI_NOR=m -# CONFIG_MTD_MT81xx_NOR is not set -CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y -# CONFIG_SPI_INTEL_SPI_PCI is not set -# CONFIG_SPI_INTEL_SPI_PLATFORM is not set -CONFIG_MTD_UBI=m -CONFIG_MTD_UBI_WL_THRESHOLD=4096 -CONFIG_MTD_UBI_BEB_LIMIT=20 -# CONFIG_MTD_UBI_FASTMAP is not set -# CONFIG_MTD_UBI_GLUEBI is not set -# CONFIG_MTD_UBI_BLOCK is not set -# CONFIG_OF is not set -CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y -CONFIG_PARPORT=m -CONFIG_PARPORT_PC=m -CONFIG_PARPORT_SERIAL=m -# CONFIG_PARPORT_PC_FIFO is not set -# CONFIG_PARPORT_PC_SUPERIO is not set -CONFIG_PARPORT_PC_PCMCIA=m -# CONFIG_PARPORT_AX88796 is not set -CONFIG_PARPORT_1284=y -CONFIG_PARPORT_NOT_PC=y -CONFIG_PNP=y -# CONFIG_PNP_DEBUG_MESSAGES is not set - -# -# Protocols -# -CONFIG_PNPACPI=y -CONFIG_BLK_DEV=y -# CONFIG_BLK_DEV_NULL_BLK is not set -CONFIG_BLK_DEV_FD=m -CONFIG_CDROM=y -# CONFIG_PARIDE is not set -CONFIG_BLK_DEV_PCIESSD_MTIP32XX=m -CONFIG_BLK_DEV_DAC960=m -CONFIG_BLK_DEV_UMEM=m -CONFIG_BLK_DEV_LOOP=y -CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 -CONFIG_BLK_DEV_CRYPTOLOOP=m -CONFIG_BLK_DEV_DRBD=m -# CONFIG_DRBD_FAULT_INJECTION is not set -CONFIG_BLK_DEV_NBD=m -CONFIG_BLK_DEV_SKD=m -CONFIG_BLK_DEV_SX8=m -CONFIG_BLK_DEV_RAM=m -CONFIG_BLK_DEV_RAM_COUNT=16 -CONFIG_BLK_DEV_RAM_SIZE=16384 -CONFIG_CDROM_PKTCDVD=m -CONFIG_CDROM_PKTCDVD_BUFFERS=8 -# CONFIG_CDROM_PKTCDVD_WCACHE is not set -CONFIG_ATA_OVER_ETH=m -CONFIG_XEN_BLKDEV_FRONTEND=m -CONFIG_XEN_BLKDEV_BACKEND=m -CONFIG_VIRTIO_BLK=m -# CONFIG_VIRTIO_BLK_SCSI is not set -CONFIG_BLK_DEV_RBD=m -CONFIG_BLK_DEV_RSXX=m - -# -# NVME Support -# -CONFIG_NVME_CORE=m -CONFIG_BLK_DEV_NVME=m -# CONFIG_NVME_MULTIPATH is not set -CONFIG_NVME_FABRICS=m -CONFIG_NVME_RDMA=m -# CONFIG_NVME_FC is not set -CONFIG_NVME_TARGET=m -CONFIG_NVME_TARGET_LOOP=m -CONFIG_NVME_TARGET_RDMA=m -# CONFIG_NVME_TARGET_FC is not set - -# -# Misc devices -# -CONFIG_SENSORS_LIS3LV02D=m -# CONFIG_AD525X_DPOT is not set -CONFIG_DUMMY_IRQ=m -# CONFIG_IBM_ASM is not set -# CONFIG_PHANTOM is not set -CONFIG_SGI_IOC4=m -CONFIG_TIFM_CORE=m -CONFIG_TIFM_7XX1=m -# CONFIG_ICS932S401 is not set -CONFIG_ENCLOSURE_SERVICES=m -CONFIG_HP_ILO=m -CONFIG_APDS9802ALS=m -CONFIG_ISL29003=m -CONFIG_ISL29020=m -CONFIG_SENSORS_TSL2550=m -CONFIG_SENSORS_BH1770=m -CONFIG_SENSORS_APDS990X=m -# CONFIG_HMC6352 is not set -# CONFIG_DS1682 is not set -CONFIG_VMWARE_BALLOON=m -# CONFIG_USB_SWITCH_FSA9480 is not set -# CONFIG_SRAM is not set -# CONFIG_PCI_ENDPOINT_TEST is not set -# CONFIG_C2PORT is not set - -# -# EEPROM support -# -CONFIG_EEPROM_AT24=m -CONFIG_EEPROM_LEGACY=m -CONFIG_EEPROM_MAX6875=m -CONFIG_EEPROM_93CX6=m -# CONFIG_EEPROM_IDT_89HPESX is not set -CONFIG_CB710_CORE=m -# CONFIG_CB710_DEBUG is not set -CONFIG_CB710_DEBUG_ASSUMPTIONS=y - -# -# Texas Instruments shared transport line discipline -# -CONFIG_TI_ST=m -CONFIG_SENSORS_LIS3_I2C=m - -# -# Altera FPGA firmware download module (requires I2C) -# -CONFIG_ALTERA_STAPL=m -CONFIG_INTEL_MEI=y -CONFIG_INTEL_MEI_ME=m -CONFIG_INTEL_MEI_TXE=m -CONFIG_VMWARE_VMCI=m - -# -# Intel MIC & related support -# - -# -# Intel MIC Bus Driver -# -CONFIG_INTEL_MIC_BUS=m - -# -# SCIF Bus Driver -# -# CONFIG_SCIF_BUS is not set - -# -# VOP Bus Driver -# -# CONFIG_VOP_BUS is not set - -# -# Intel MIC Host Driver -# - -# -# Intel MIC Card Driver -# - -# -# SCIF Driver -# - -# -# Intel MIC Coprocessor State Management (COSM) Drivers -# - -# -# VOP Driver -# -CONFIG_GENWQE=m -CONFIG_GENWQE_PLATFORM_ERROR_RECOVERY=1 -# CONFIG_ECHO is not set -# CONFIG_MISC_RTSX_PCI is not set -# CONFIG_MISC_RTSX_USB is not set -CONFIG_HAVE_IDE=y -# CONFIG_IDE is not set - -# -# SCSI device support -# -CONFIG_SCSI_MOD=y -CONFIG_RAID_ATTRS=m -CONFIG_SCSI=y -CONFIG_SCSI_DMA=y -CONFIG_SCSI_NETLINK=y -# CONFIG_SCSI_MQ_DEFAULT is not set -CONFIG_SCSI_PROC_FS=y - -# -# SCSI support type (disk, tape, CD-ROM) -# -CONFIG_BLK_DEV_SD=y -CONFIG_CHR_DEV_ST=m -CONFIG_CHR_DEV_OSST=m -CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y -CONFIG_CHR_DEV_SG=y -CONFIG_CHR_DEV_SCH=m -CONFIG_SCSI_ENCLOSURE=m -CONFIG_SCSI_CONSTANTS=y -CONFIG_SCSI_LOGGING=y -CONFIG_SCSI_SCAN_ASYNC=y - -# -# SCSI Transports -# -CONFIG_SCSI_SPI_ATTRS=m -CONFIG_SCSI_FC_ATTRS=m -CONFIG_SCSI_ISCSI_ATTRS=m -CONFIG_SCSI_SAS_ATTRS=m -CONFIG_SCSI_SAS_LIBSAS=m -CONFIG_SCSI_SAS_ATA=y -CONFIG_SCSI_SAS_HOST_SMP=y -CONFIG_SCSI_SRP_ATTRS=m -CONFIG_SCSI_LOWLEVEL=y -CONFIG_ISCSI_TCP=m -CONFIG_ISCSI_BOOT_SYSFS=m -CONFIG_SCSI_CXGB3_ISCSI=m -CONFIG_SCSI_CXGB4_ISCSI=m -CONFIG_SCSI_BNX2_ISCSI=m -CONFIG_SCSI_BNX2X_FCOE=m -CONFIG_BE2ISCSI=m -CONFIG_BLK_DEV_3W_XXXX_RAID=m -CONFIG_SCSI_HPSA=m -CONFIG_SCSI_3W_9XXX=m -CONFIG_SCSI_3W_SAS=m -CONFIG_SCSI_ACARD=m -CONFIG_SCSI_AACRAID=m -CONFIG_SCSI_AIC7XXX=m -CONFIG_AIC7XXX_CMDS_PER_DEVICE=4 -CONFIG_AIC7XXX_RESET_DELAY_MS=15000 -# CONFIG_AIC7XXX_DEBUG_ENABLE is not set -CONFIG_AIC7XXX_DEBUG_MASK=0 -# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set -CONFIG_SCSI_AIC79XX=m -CONFIG_AIC79XX_CMDS_PER_DEVICE=4 -CONFIG_AIC79XX_RESET_DELAY_MS=15000 -# CONFIG_AIC79XX_DEBUG_ENABLE is not set -CONFIG_AIC79XX_DEBUG_MASK=0 -# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set -CONFIG_SCSI_AIC94XX=m -# CONFIG_AIC94XX_DEBUG is not set -CONFIG_SCSI_MVSAS=m -# CONFIG_SCSI_MVSAS_DEBUG is not set -CONFIG_SCSI_MVSAS_TASKLET=y -CONFIG_SCSI_MVUMI=m -# CONFIG_SCSI_DPT_I2O is not set -CONFIG_SCSI_ADVANSYS=m -CONFIG_SCSI_ARCMSR=m -# CONFIG_SCSI_ESAS2R is not set -CONFIG_MEGARAID_NEWGEN=y -CONFIG_MEGARAID_MM=m -CONFIG_MEGARAID_MAILBOX=m -CONFIG_MEGARAID_LEGACY=m -CONFIG_MEGARAID_SAS=m -CONFIG_SCSI_MPT3SAS=m -CONFIG_SCSI_MPT2SAS_MAX_SGE=128 -CONFIG_SCSI_MPT3SAS_MAX_SGE=128 -CONFIG_SCSI_MPT2SAS=m -# CONFIG_SCSI_SMARTPQI is not set -CONFIG_SCSI_UFSHCD=m -CONFIG_SCSI_UFSHCD_PCI=m -CONFIG_SCSI_UFS_DWC_TC_PCI=m -CONFIG_SCSI_UFSHCD_PLATFORM=m -CONFIG_SCSI_UFS_DWC_TC_PLATFORM=m -CONFIG_SCSI_HPTIOP=m -CONFIG_SCSI_BUSLOGIC=m -# CONFIG_SCSI_FLASHPOINT is not set -CONFIG_VMWARE_PVSCSI=m -# CONFIG_XEN_SCSI_FRONTEND is not set -CONFIG_HYPERV_STORAGE=m -CONFIG_LIBFC=m -CONFIG_LIBFCOE=m -CONFIG_FCOE=m -CONFIG_FCOE_FNIC=m -# CONFIG_SCSI_SNIC is not set -# CONFIG_SCSI_DMX3191D is not set -CONFIG_SCSI_GDTH=m -CONFIG_SCSI_ISCI=m -CONFIG_SCSI_IPS=m -CONFIG_SCSI_INITIO=m -CONFIG_SCSI_INIA100=m -# CONFIG_SCSI_PPA is not set -# CONFIG_SCSI_IMM is not set -CONFIG_SCSI_STEX=m -CONFIG_SCSI_SYM53C8XX_2=m -CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 -CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 -CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 -CONFIG_SCSI_SYM53C8XX_MMIO=y -# CONFIG_SCSI_IPR is not set -CONFIG_SCSI_QLOGIC_1280=m -CONFIG_SCSI_QLA_FC=m -CONFIG_TCM_QLA2XXX=m -# CONFIG_TCM_QLA2XXX_DEBUG is not set -CONFIG_SCSI_QLA_ISCSI=m -# CONFIG_QEDI is not set -# CONFIG_QEDF is not set -CONFIG_SCSI_LPFC=m -# CONFIG_SCSI_LPFC_DEBUG_FS is not set -CONFIG_SCSI_DC395x=m -# CONFIG_SCSI_AM53C974 is not set -# CONFIG_SCSI_WD719X is not set -CONFIG_SCSI_DEBUG=m -CONFIG_SCSI_PMCRAID=m -CONFIG_SCSI_PM8001=m -CONFIG_SCSI_BFA_FC=m -CONFIG_SCSI_VIRTIO=m -CONFIG_SCSI_CHELSIO_FCOE=m -# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set -CONFIG_SCSI_DH=y -CONFIG_SCSI_DH_RDAC=m -CONFIG_SCSI_DH_HP_SW=m -CONFIG_SCSI_DH_EMC=m -CONFIG_SCSI_DH_ALUA=m -CONFIG_SCSI_OSD_INITIATOR=m -CONFIG_SCSI_OSD_ULD=m -CONFIG_SCSI_OSD_DPRINT_SENSE=1 -# CONFIG_SCSI_OSD_DEBUG is not set -CONFIG_ATA=y -CONFIG_ATA_VERBOSE_ERROR=y -CONFIG_ATA_ACPI=y -CONFIG_SATA_ZPODD=y -CONFIG_SATA_PMP=y - -# -# Controllers with non-SFF native interface -# -CONFIG_SATA_AHCI=y -CONFIG_SATA_MOBILE_LPM_POLICY=0 -CONFIG_SATA_AHCI_PLATFORM=m -CONFIG_SATA_INIC162X=m -CONFIG_SATA_ACARD_AHCI=m -CONFIG_SATA_SIL24=m -CONFIG_ATA_SFF=y - -# -# SFF controllers with custom DMA interface -# -CONFIG_PDC_ADMA=m -CONFIG_SATA_QSTOR=m -CONFIG_SATA_SX4=m -CONFIG_ATA_BMDMA=y - -# -# SATA SFF controllers with BMDMA -# -CONFIG_ATA_PIIX=y -# CONFIG_SATA_DWC is not set -CONFIG_SATA_MV=m -CONFIG_SATA_NV=m -CONFIG_SATA_PROMISE=m -CONFIG_SATA_SIL=m -CONFIG_SATA_SIS=m -CONFIG_SATA_SVW=m -CONFIG_SATA_ULI=m -CONFIG_SATA_VIA=m -CONFIG_SATA_VITESSE=m - -# -# PATA SFF controllers with BMDMA -# -CONFIG_PATA_ALI=m -CONFIG_PATA_AMD=m -CONFIG_PATA_ARTOP=m -CONFIG_PATA_ATIIXP=m -CONFIG_PATA_ATP867X=m -CONFIG_PATA_CMD64X=m -CONFIG_PATA_CYPRESS=m -CONFIG_PATA_EFAR=m -CONFIG_PATA_HPT366=m -CONFIG_PATA_HPT37X=m -CONFIG_PATA_HPT3X2N=m -CONFIG_PATA_HPT3X3=m -# CONFIG_PATA_HPT3X3_DMA is not set -CONFIG_PATA_IT8213=m -CONFIG_PATA_IT821X=m -CONFIG_PATA_JMICRON=m -CONFIG_PATA_MARVELL=m -CONFIG_PATA_NETCELL=m -CONFIG_PATA_NINJA32=m -CONFIG_PATA_NS87415=m -CONFIG_PATA_OLDPIIX=m -CONFIG_PATA_OPTIDMA=m -CONFIG_PATA_PDC2027X=m -CONFIG_PATA_PDC_OLD=m -# CONFIG_PATA_RADISYS is not set -CONFIG_PATA_RDC=m -CONFIG_PATA_SCH=m -CONFIG_PATA_SERVERWORKS=m -CONFIG_PATA_SIL680=m -CONFIG_PATA_SIS=m -CONFIG_PATA_TOSHIBA=m -CONFIG_PATA_TRIFLEX=m -CONFIG_PATA_VIA=m -CONFIG_PATA_WINBOND=m - -# -# PIO-only SFF controllers -# -CONFIG_PATA_CMD640_PCI=m -CONFIG_PATA_MPIIX=m -CONFIG_PATA_NS87410=m -CONFIG_PATA_OPTI=m -CONFIG_PATA_PCMCIA=m -# CONFIG_PATA_RZ1000 is not set - -# -# Generic fallback / legacy drivers -# -CONFIG_PATA_ACPI=m -CONFIG_ATA_GENERIC=m -# CONFIG_PATA_LEGACY is not set -CONFIG_MD=y -CONFIG_BLK_DEV_MD=y -CONFIG_MD_AUTODETECT=y -CONFIG_MD_LINEAR=m -CONFIG_MD_RAID0=m -CONFIG_MD_RAID1=m -CONFIG_MD_RAID10=m -CONFIG_MD_RAID456=m -CONFIG_MD_MULTIPATH=m -CONFIG_MD_FAULTY=m -CONFIG_MD_CLUSTER=m -CONFIG_BCACHE=m -# CONFIG_BCACHE_DEBUG is not set -# CONFIG_BCACHE_CLOSURES_DEBUG is not set -CONFIG_BLK_DEV_DM_BUILTIN=y -CONFIG_BLK_DEV_DM=y -CONFIG_DM_MQ_DEFAULT=y -CONFIG_DM_DEBUG=y -CONFIG_DM_BUFIO=y -# CONFIG_DM_DEBUG_BLOCK_MANAGER_LOCKING is not set -CONFIG_DM_BIO_PRISON=m -CONFIG_DM_PERSISTENT_DATA=m -# CONFIG_DM_UNSTRIPED is not set -CONFIG_DM_CRYPT=m -CONFIG_DM_SNAPSHOT=y -CONFIG_DM_THIN_PROVISIONING=m -CONFIG_DM_CACHE=m -CONFIG_DM_CACHE_SMQ=m -# CONFIG_DM_WRITECACHE is not set -CONFIG_DM_ERA=m -CONFIG_DM_MIRROR=y -CONFIG_DM_LOG_USERSPACE=m -CONFIG_DM_RAID=m -CONFIG_DM_ZERO=y -CONFIG_DM_MULTIPATH=m -CONFIG_DM_MULTIPATH_QL=m -CONFIG_DM_MULTIPATH_ST=m -# CONFIG_DM_DELAY is not set -CONFIG_DM_UEVENT=y -CONFIG_DM_FLAKEY=m -CONFIG_DM_VERITY=m -# CONFIG_DM_VERITY_FEC is not set -# CONFIG_DM_SWITCH is not set -CONFIG_DM_LOG_WRITES=m -# CONFIG_DM_INTEGRITY is not set -CONFIG_TARGET_CORE=m -CONFIG_TCM_IBLOCK=m -CONFIG_TCM_FILEIO=m -CONFIG_TCM_PSCSI=m -CONFIG_TCM_USER2=m -CONFIG_LOOPBACK_TARGET=m -CONFIG_TCM_FC=m -CONFIG_ISCSI_TARGET=m -# CONFIG_ISCSI_TARGET_CXGB4 is not set -CONFIG_SBP_TARGET=m -CONFIG_FUSION=y -CONFIG_FUSION_SPI=m -CONFIG_FUSION_FC=m -CONFIG_FUSION_SAS=m -CONFIG_FUSION_MAX_SGE=40 -CONFIG_FUSION_CTL=m -CONFIG_FUSION_LAN=m -CONFIG_FUSION_LOGGING=y - -# -# IEEE 1394 (FireWire) support -# -CONFIG_FIREWIRE=m -CONFIG_FIREWIRE_OHCI=m -CONFIG_FIREWIRE_SBP2=m -CONFIG_FIREWIRE_NET=m -CONFIG_FIREWIRE_NOSY=m -CONFIG_MACINTOSH_DRIVERS=y -CONFIG_MAC_EMUMOUSEBTN=y -CONFIG_NETDEVICES=y -CONFIG_MII=m -CONFIG_NET_CORE=y -CONFIG_BONDING=m -CONFIG_DUMMY=m -CONFIG_EQUALIZER=m -CONFIG_NET_FC=y -CONFIG_IFB=m -CONFIG_NET_TEAM=m -CONFIG_NET_TEAM_MODE_BROADCAST=m -CONFIG_NET_TEAM_MODE_ROUNDROBIN=m -CONFIG_NET_TEAM_MODE_RANDOM=m -CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m -CONFIG_NET_TEAM_MODE_LOADBALANCE=m -CONFIG_MACVLAN=m -CONFIG_MACVTAP=m -CONFIG_IPVLAN=y -# CONFIG_IPVTAP is not set -CONFIG_VXLAN=m -CONFIG_GENEVE=m -# CONFIG_GTP is not set -# CONFIG_MACSEC is not set -CONFIG_NETCONSOLE=m -CONFIG_NETCONSOLE_DYNAMIC=y -CONFIG_NETPOLL=y -CONFIG_NET_POLL_CONTROLLER=y -CONFIG_TUN=m -CONFIG_TAP=m -# CONFIG_TUN_VNET_CROSS_LE is not set -CONFIG_VETH=m -CONFIG_VIRTIO_NET=m -# CONFIG_NLMON is not set -# CONFIG_NET_VRF is not set -# CONFIG_VSOCKMON is not set -CONFIG_SUNGEM_PHY=m -# CONFIG_ARCNET is not set -CONFIG_ATM_DRIVERS=y -# CONFIG_ATM_DUMMY is not set -CONFIG_ATM_TCP=m -# CONFIG_ATM_LANAI is not set -CONFIG_ATM_ENI=m -# CONFIG_ATM_ENI_DEBUG is not set -# CONFIG_ATM_ENI_TUNE_BURST is not set -CONFIG_ATM_FIRESTREAM=m -# CONFIG_ATM_ZATM is not set -CONFIG_ATM_NICSTAR=m -# CONFIG_ATM_NICSTAR_USE_SUNI is not set -# CONFIG_ATM_NICSTAR_USE_IDT77105 is not set -# CONFIG_ATM_IDT77252 is not set -# CONFIG_ATM_AMBASSADOR is not set -# CONFIG_ATM_HORIZON is not set -# CONFIG_ATM_IA is not set -# CONFIG_ATM_FORE200E is not set -CONFIG_ATM_HE=m -# CONFIG_ATM_HE_USE_SUNI is not set -CONFIG_ATM_SOLOS=m - -# -# CAIF transport drivers -# - -# -# Distributed Switch Architecture drivers -# -CONFIG_B53=m -CONFIG_B53_MDIO_DRIVER=m -CONFIG_B53_MMAP_DRIVER=m -CONFIG_B53_SRAB_DRIVER=m -# CONFIG_NET_DSA_BCM_SF2 is not set -# CONFIG_NET_DSA_LOOP is not set -# CONFIG_NET_DSA_MT7530 is not set -CONFIG_NET_DSA_MV88E6060=m -# CONFIG_MICROCHIP_KSZ is not set -CONFIG_NET_DSA_MV88E6XXX=m -CONFIG_NET_DSA_MV88E6XXX_GLOBAL2=y -# CONFIG_NET_DSA_MV88E6XXX_PTP is not set -CONFIG_NET_DSA_QCA8K=m -# CONFIG_NET_DSA_REALTEK_SMI is not set -# CONFIG_NET_DSA_SMSC_LAN9303_I2C is not set -# CONFIG_NET_DSA_SMSC_LAN9303_MDIO is not set -CONFIG_ETHERNET=y -CONFIG_MDIO=m -CONFIG_NET_VENDOR_3COM=y -CONFIG_PCMCIA_3C574=m -CONFIG_PCMCIA_3C589=m -CONFIG_VORTEX=m -CONFIG_TYPHOON=m -CONFIG_NET_VENDOR_ADAPTEC=y -CONFIG_ADAPTEC_STARFIRE=m -CONFIG_NET_VENDOR_AGERE=y -# CONFIG_ET131X is not set -CONFIG_NET_VENDOR_ALACRITECH=y -# CONFIG_SLICOSS is not set -CONFIG_NET_VENDOR_ALTEON=y -CONFIG_ACENIC=m -# CONFIG_ACENIC_OMIT_TIGON_I is not set -CONFIG_ALTERA_TSE=m -CONFIG_NET_VENDOR_AMAZON=y -CONFIG_ENA_ETHERNET=m -CONFIG_NET_VENDOR_AMD=y -CONFIG_AMD8111_ETH=m -CONFIG_PCNET32=m -CONFIG_PCMCIA_NMCLAN=m -# CONFIG_AMD_XGBE is not set -CONFIG_NET_VENDOR_AQUANTIA=y -# CONFIG_AQTION is not set -CONFIG_NET_VENDOR_ARC=y -CONFIG_NET_VENDOR_ATHEROS=y -CONFIG_ATL2=m -CONFIG_ATL1=m -CONFIG_ATL1E=m -CONFIG_ATL1C=m -CONFIG_ALX=m -# CONFIG_NET_VENDOR_AURORA is not set -CONFIG_NET_VENDOR_BROADCOM=y -CONFIG_B44=m -CONFIG_B44_PCI_AUTOSELECT=y -CONFIG_B44_PCICORE_AUTOSELECT=y -CONFIG_B44_PCI=y -# CONFIG_BCMGENET is not set -CONFIG_BNX2=m -CONFIG_CNIC=m -CONFIG_TIGON3=m -CONFIG_TIGON3_HWMON=y -CONFIG_BNX2X=m -CONFIG_BNX2X_SRIOV=y -# CONFIG_SYSTEMPORT is not set -CONFIG_BNXT=m -CONFIG_BNXT_SRIOV=y -CONFIG_BNXT_FLOWER_OFFLOAD=y -# CONFIG_BNXT_DCB is not set -CONFIG_BNXT_HWMON=y -CONFIG_NET_VENDOR_BROCADE=y -CONFIG_BNA=m -CONFIG_NET_VENDOR_CADENCE=y -CONFIG_MACB=m -CONFIG_MACB_USE_HWSTAMP=y -# CONFIG_MACB_PCI is not set -CONFIG_NET_VENDOR_CAVIUM=y -# CONFIG_THUNDER_NIC_PF is not set -# CONFIG_THUNDER_NIC_VF is not set -# CONFIG_THUNDER_NIC_BGX is not set -CONFIG_THUNDER_NIC_RGX=m -CONFIG_CAVIUM_PTP=y -# CONFIG_LIQUIDIO is not set -# CONFIG_LIQUIDIO_VF is not set -CONFIG_NET_VENDOR_CHELSIO=y -CONFIG_CHELSIO_T1=m -CONFIG_CHELSIO_T1_1G=y -CONFIG_CHELSIO_T3=m -CONFIG_CHELSIO_T4=m -CONFIG_CHELSIO_T4_DCB=y -CONFIG_CHELSIO_T4_FCOE=y -CONFIG_CHELSIO_T4VF=m -CONFIG_CHELSIO_LIB=m -CONFIG_NET_VENDOR_CISCO=y -CONFIG_ENIC=m -CONFIG_NET_VENDOR_CORTINA=y -CONFIG_CX_ECAT=m -CONFIG_DNET=m -CONFIG_NET_VENDOR_DEC=y -CONFIG_NET_TULIP=y -CONFIG_DE2104X=m -CONFIG_DE2104X_DSL=0 -CONFIG_TULIP=m -# CONFIG_TULIP_MWI is not set -CONFIG_TULIP_MMIO=y -# CONFIG_TULIP_NAPI is not set -CONFIG_DE4X5=m -CONFIG_WINBOND_840=m -CONFIG_DM9102=m -CONFIG_ULI526X=m -CONFIG_PCMCIA_XIRCOM=m -CONFIG_NET_VENDOR_DLINK=y -CONFIG_DL2K=m -CONFIG_SUNDANCE=m -# CONFIG_SUNDANCE_MMIO is not set -CONFIG_NET_VENDOR_EMULEX=y -CONFIG_BE2NET=m -CONFIG_BE2NET_HWMON=y -CONFIG_BE2NET_BE2=y -CONFIG_BE2NET_BE3=y -CONFIG_BE2NET_LANCER=y -CONFIG_BE2NET_SKYHAWK=y -CONFIG_NET_VENDOR_EZCHIP=y -# CONFIG_NET_VENDOR_FUJITSU is not set -# CONFIG_NET_VENDOR_HP is not set -CONFIG_NET_VENDOR_HUAWEI=y -# CONFIG_HINIC is not set -# CONFIG_NET_VENDOR_I825XX is not set -CONFIG_NET_VENDOR_INTEL=y -CONFIG_E100=m -CONFIG_E1000=m -CONFIG_E1000E=m -CONFIG_E1000E_HWTS=y -CONFIG_IGB=m -CONFIG_IGB_HWMON=y -CONFIG_IGB_DCA=y -CONFIG_IGBVF=m -CONFIG_IXGB=m -CONFIG_IXGBE=m -CONFIG_IXGBE_HWMON=y -CONFIG_IXGBE_DCA=y -CONFIG_IXGBE_DCB=y -CONFIG_IXGBEVF=m -CONFIG_I40E=m -CONFIG_I40E_DCB=y -CONFIG_I40EVF=m -# CONFIG_ICE is not set -# CONFIG_FM10K is not set -CONFIG_JME=m -CONFIG_NET_VENDOR_MARVELL=y -CONFIG_MVMDIO=m -CONFIG_SKGE=m -# CONFIG_SKGE_DEBUG is not set -CONFIG_SKGE_GENESIS=y -CONFIG_SKY2=m -# CONFIG_SKY2_DEBUG is not set -CONFIG_NET_VENDOR_MELLANOX=y -CONFIG_MLX4_EN=m -CONFIG_MLX4_EN_DCB=y -CONFIG_MLX4_CORE=m -CONFIG_MLX4_DEBUG=y -CONFIG_MLX4_CORE_GEN2=y -# CONFIG_MLX5_CORE is not set -CONFIG_MLXSW_CORE=m -CONFIG_MLXSW_CORE_HWMON=y -CONFIG_MLXSW_CORE_THERMAL=y -CONFIG_MLXSW_PCI=m -CONFIG_MLXSW_I2C=m -CONFIG_MLXSW_SWITCHIB=m -CONFIG_MLXSW_SWITCHX2=m -CONFIG_MLXSW_SPECTRUM=m -CONFIG_MLXSW_SPECTRUM_DCB=y -CONFIG_MLXSW_MINIMAL=m -CONFIG_MLXFW=m -CONFIG_NET_VENDOR_MICREL=y -# CONFIG_KS8842 is not set -# CONFIG_KS8851_MLL is not set -CONFIG_KSZ884X_PCI=m -CONFIG_NET_VENDOR_MICROSEMI=y -# CONFIG_MSCC_OCELOT_SWITCH is not set -CONFIG_NET_VENDOR_MYRI=y -CONFIG_MYRI10GE=m -CONFIG_MYRI10GE_DCA=y -CONFIG_FEALNX=m -CONFIG_NET_VENDOR_NATSEMI=y -CONFIG_NATSEMI=m -CONFIG_NS83820=m -CONFIG_NET_VENDOR_NETERION=y -CONFIG_S2IO=m -CONFIG_VXGE=m -# CONFIG_VXGE_DEBUG_TRACE_ALL is not set -CONFIG_NET_VENDOR_NETRONOME=y -# CONFIG_NFP is not set -CONFIG_NET_VENDOR_NI=y -CONFIG_NET_VENDOR_8390=y -CONFIG_PCMCIA_AXNET=m -CONFIG_NE2K_PCI=m -CONFIG_PCMCIA_PCNET=m -CONFIG_NET_VENDOR_NVIDIA=y -CONFIG_FORCEDETH=m -CONFIG_NET_VENDOR_OKI=y -CONFIG_ETHOC=m -CONFIG_NET_VENDOR_PACKET_ENGINES=y -CONFIG_HAMACHI=m -CONFIG_YELLOWFIN=m -CONFIG_NET_VENDOR_QLOGIC=y -CONFIG_QLA3XXX=m -CONFIG_QLCNIC=m -CONFIG_QLCNIC_SRIOV=y -CONFIG_QLCNIC_DCB=y -CONFIG_QLCNIC_HWMON=y -CONFIG_QLGE=m -CONFIG_NETXEN_NIC=m -CONFIG_QED=m -CONFIG_QED_LL2=y -CONFIG_QED_SRIOV=y -CONFIG_QEDE=m -CONFIG_QED_RDMA=y -CONFIG_QED_OOO=y -CONFIG_NET_VENDOR_QUALCOMM=y -CONFIG_QCOM_EMAC=m -# CONFIG_RMNET is not set -CONFIG_NET_VENDOR_RDC=y -CONFIG_R6040=m -CONFIG_NET_VENDOR_REALTEK=y -CONFIG_ATP=m -CONFIG_8139CP=m -CONFIG_8139TOO=m -# CONFIG_8139TOO_PIO is not set -# CONFIG_8139TOO_TUNE_TWISTER is not set -CONFIG_8139TOO_8129=y -# CONFIG_8139_OLD_RX_RESET is not set -CONFIG_R8169=m -CONFIG_NET_VENDOR_RENESAS=y -CONFIG_NET_VENDOR_ROCKER=y -CONFIG_ROCKER=m -CONFIG_NET_VENDOR_SAMSUNG=y -CONFIG_SXGBE_ETH=m -# CONFIG_NET_VENDOR_SEEQ is not set -CONFIG_NET_VENDOR_SOLARFLARE=y -CONFIG_SFC=m -# CONFIG_SFC_MTD is not set -CONFIG_SFC_MCDI_MON=y -CONFIG_SFC_SRIOV=y -CONFIG_SFC_MCDI_LOGGING=y -# CONFIG_SFC_FALCON is not set -CONFIG_NET_VENDOR_SILAN=y -CONFIG_SC92031=m -CONFIG_NET_VENDOR_SIS=y -CONFIG_SIS900=m -CONFIG_SIS190=m -CONFIG_NET_VENDOR_SMSC=y -CONFIG_PCMCIA_SMC91C92=m -CONFIG_EPIC100=m -CONFIG_SMSC911X=m -CONFIG_SMSC9420=m -CONFIG_NET_VENDOR_SOCIONEXT=y -CONFIG_NET_VENDOR_STMICRO=y -CONFIG_STMMAC_ETH=m -# CONFIG_STMMAC_PLATFORM is not set -# CONFIG_STMMAC_PCI is not set -CONFIG_NET_VENDOR_SUN=y -CONFIG_HAPPYMEAL=m -CONFIG_SUNGEM=m -CONFIG_CASSINI=m -CONFIG_NIU=m -CONFIG_NET_VENDOR_SYNOPSYS=y -# CONFIG_DWC_XLGMAC is not set -CONFIG_NET_VENDOR_TEHUTI=y -CONFIG_TEHUTI=m -CONFIG_NET_VENDOR_TI=y -CONFIG_TI_CPSW_ALE=m -CONFIG_TLAN=m -CONFIG_NET_VENDOR_VIA=y -CONFIG_VIA_RHINE=m -CONFIG_VIA_RHINE_MMIO=y -CONFIG_VIA_VELOCITY=m -CONFIG_NET_VENDOR_WIZNET=y -CONFIG_WIZNET_W5100=m -CONFIG_WIZNET_W5300=m -# CONFIG_WIZNET_BUS_DIRECT is not set -# CONFIG_WIZNET_BUS_INDIRECT is not set -CONFIG_WIZNET_BUS_ANY=y -CONFIG_NET_VENDOR_XIRCOM=y -CONFIG_PCMCIA_XIRC2PS=m -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_NET_SB1000 is not set -CONFIG_MDIO_DEVICE=y -CONFIG_MDIO_BUS=y -# CONFIG_MDIO_BCM_UNIMAC is not set -CONFIG_MDIO_BITBANG=m -CONFIG_MDIO_CAVIUM=m -CONFIG_MDIO_GPIO=m -# CONFIG_MDIO_MSCC_MIIM is not set -CONFIG_MDIO_THUNDER=m -CONFIG_PHYLINK=m -CONFIG_PHYLIB=y -CONFIG_SWPHY=y -# CONFIG_LED_TRIGGER_PHY is not set - -# -# MII PHY device drivers -# -# CONFIG_SFP is not set -CONFIG_AMD_PHY=m -CONFIG_AQUANTIA_PHY=m -# CONFIG_ASIX_PHY is not set -CONFIG_AT803X_PHY=m -CONFIG_BCM7XXX_PHY=m -CONFIG_BCM87XX_PHY=m -CONFIG_BCM_NET_PHYLIB=m -CONFIG_BROADCOM_PHY=m -CONFIG_CICADA_PHY=m -# CONFIG_CORTINA_PHY is not set -CONFIG_DAVICOM_PHY=m -# CONFIG_DP83822_PHY is not set -# CONFIG_DP83TC811_PHY is not set -CONFIG_DP83848_PHY=m -# CONFIG_DP83867_PHY is not set -CONFIG_FIXED_PHY=y -CONFIG_ICPLUS_PHY=m -CONFIG_INTEL_XWAY_PHY=m -CONFIG_LSI_ET1011C_PHY=m -CONFIG_LXT_PHY=m -CONFIG_MARVELL_PHY=m -# CONFIG_MARVELL_10G_PHY is not set -CONFIG_MICREL_PHY=m -CONFIG_MICROCHIP_PHY=m -# CONFIG_MICROCHIP_T1_PHY is not set -CONFIG_MICROSEMI_PHY=m -CONFIG_NATIONAL_PHY=m -CONFIG_QSEMI_PHY=m -CONFIG_REALTEK_PHY=m -# CONFIG_RENESAS_PHY is not set -# CONFIG_ROCKCHIP_PHY is not set -CONFIG_SMSC_PHY=m -CONFIG_STE10XP=m -CONFIG_TERANETICS_PHY=m -CONFIG_VITESSE_PHY=m -CONFIG_XILINX_GMII2RGMII=m -# CONFIG_PLIP is not set -CONFIG_PPP=m -CONFIG_PPP_BSDCOMP=m -CONFIG_PPP_DEFLATE=m -CONFIG_PPP_FILTER=y -CONFIG_PPP_MPPE=m -CONFIG_PPP_MULTILINK=y -CONFIG_PPPOATM=m -CONFIG_PPPOE=m -CONFIG_PPTP=m -CONFIG_PPPOL2TP=m -CONFIG_PPP_ASYNC=m -CONFIG_PPP_SYNC_TTY=m -CONFIG_SLIP=m -CONFIG_SLHC=m -CONFIG_SLIP_COMPRESSED=y -CONFIG_SLIP_SMART=y -# CONFIG_SLIP_MODE_SLIP6 is not set -CONFIG_USB_NET_DRIVERS=m -CONFIG_USB_CATC=m -CONFIG_USB_KAWETH=m -CONFIG_USB_PEGASUS=m -CONFIG_USB_RTL8150=m -CONFIG_USB_RTL8152=m -CONFIG_USB_LAN78XX=m -CONFIG_USB_USBNET=m -CONFIG_USB_NET_AX8817X=m -CONFIG_USB_NET_AX88179_178A=m -CONFIG_USB_NET_CDCETHER=m -CONFIG_USB_NET_CDC_EEM=m -CONFIG_USB_NET_CDC_NCM=m -CONFIG_USB_NET_HUAWEI_CDC_NCM=m -CONFIG_USB_NET_CDC_MBIM=m -CONFIG_USB_NET_DM9601=m -CONFIG_USB_NET_SR9700=m -CONFIG_USB_NET_SR9800=m -CONFIG_USB_NET_SMSC75XX=m -CONFIG_USB_NET_SMSC95XX=m -CONFIG_USB_NET_GL620A=m -CONFIG_USB_NET_NET1080=m -CONFIG_USB_NET_PLUSB=m -CONFIG_USB_NET_MCS7830=m -CONFIG_USB_NET_RNDIS_HOST=m -CONFIG_USB_NET_CDC_SUBSET_ENABLE=m -CONFIG_USB_NET_CDC_SUBSET=m -CONFIG_USB_ALI_M5632=y -CONFIG_USB_AN2720=y -CONFIG_USB_BELKIN=y -CONFIG_USB_ARMLINUX=y -CONFIG_USB_EPSON2888=y -CONFIG_USB_KC2190=y -CONFIG_USB_NET_ZAURUS=m -CONFIG_USB_NET_CX82310_ETH=m -CONFIG_USB_NET_KALMIA=m -CONFIG_USB_NET_QMI_WWAN=m -CONFIG_USB_HSO=m -CONFIG_USB_NET_INT51X1=m -CONFIG_USB_IPHETH=m -CONFIG_USB_SIERRA_NET=m -CONFIG_USB_VL600=m -CONFIG_USB_NET_CH9200=m -CONFIG_WLAN=y -CONFIG_WLAN_VENDOR_ADMTEK=y -# CONFIG_ADM8211 is not set -CONFIG_ATH_COMMON=m -CONFIG_WLAN_VENDOR_ATH=y -# CONFIG_ATH_DEBUG is not set -CONFIG_ATH5K=m -CONFIG_ATH5K_DEBUG=y -# CONFIG_ATH5K_TRACER is not set -CONFIG_ATH5K_PCI=y -CONFIG_ATH9K_HW=m -CONFIG_ATH9K_COMMON=m -CONFIG_ATH9K_COMMON_DEBUG=y -CONFIG_ATH9K_BTCOEX_SUPPORT=y -CONFIG_ATH9K=m -CONFIG_ATH9K_PCI=y -CONFIG_ATH9K_AHB=y -CONFIG_ATH9K_DEBUGFS=y -# CONFIG_ATH9K_STATION_STATISTICS is not set -# CONFIG_ATH9K_DYNACK is not set -CONFIG_ATH9K_WOW=y -CONFIG_ATH9K_RFKILL=y -# CONFIG_ATH9K_CHANNEL_CONTEXT is not set -CONFIG_ATH9K_PCOEM=y -CONFIG_ATH9K_HTC=m -# CONFIG_ATH9K_HTC_DEBUGFS is not set -CONFIG_ATH9K_HWRNG=y -# CONFIG_ATH9K_COMMON_SPECTRAL is not set -CONFIG_CARL9170=m -CONFIG_CARL9170_LEDS=y -# CONFIG_CARL9170_DEBUGFS is not set -CONFIG_CARL9170_WPC=y -CONFIG_CARL9170_HWRNG=y -CONFIG_ATH6KL=m -CONFIG_ATH6KL_SDIO=m -CONFIG_ATH6KL_USB=m -# CONFIG_ATH6KL_DEBUG is not set -# CONFIG_ATH6KL_TRACING is not set -CONFIG_AR5523=m -CONFIG_WIL6210=m -CONFIG_WIL6210_ISR_COR=y -CONFIG_WIL6210_TRACING=y -CONFIG_WIL6210_DEBUGFS=y -CONFIG_ATH10K=m -CONFIG_ATH10K_CE=y -CONFIG_ATH10K_PCI=m -# CONFIG_ATH10K_SDIO is not set -# CONFIG_ATH10K_USB is not set -CONFIG_ATH10K_DEBUG=y -# CONFIG_ATH10K_DEBUGFS is not set -# CONFIG_ATH10K_TRACING is not set -CONFIG_WCN36XX=m -# CONFIG_WCN36XX_DEBUGFS is not set -CONFIG_WLAN_VENDOR_ATMEL=y -# CONFIG_ATMEL is not set -CONFIG_AT76C50X_USB=m -CONFIG_WLAN_VENDOR_BROADCOM=y -CONFIG_B43=m -CONFIG_B43_BCMA=y -CONFIG_B43_SSB=y -CONFIG_B43_BUSES_BCMA_AND_SSB=y -# CONFIG_B43_BUSES_BCMA is not set -# CONFIG_B43_BUSES_SSB is not set -CONFIG_B43_PCI_AUTOSELECT=y -CONFIG_B43_PCICORE_AUTOSELECT=y -CONFIG_B43_SDIO=y -CONFIG_B43_BCMA_PIO=y -CONFIG_B43_PIO=y -CONFIG_B43_PHY_G=y -CONFIG_B43_PHY_N=y -CONFIG_B43_PHY_LP=y -CONFIG_B43_PHY_HT=y -CONFIG_B43_LEDS=y -CONFIG_B43_HWRNG=y -CONFIG_B43_DEBUG=y -CONFIG_B43LEGACY=m -CONFIG_B43LEGACY_PCI_AUTOSELECT=y -CONFIG_B43LEGACY_PCICORE_AUTOSELECT=y -CONFIG_B43LEGACY_LEDS=y -CONFIG_B43LEGACY_HWRNG=y -CONFIG_B43LEGACY_DEBUG=y -CONFIG_B43LEGACY_DMA=y -CONFIG_B43LEGACY_PIO=y -CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y -# CONFIG_B43LEGACY_DMA_MODE is not set -# CONFIG_B43LEGACY_PIO_MODE is not set -CONFIG_BRCMUTIL=m -CONFIG_BRCMSMAC=m -CONFIG_BRCMFMAC=m -CONFIG_BRCMFMAC_PROTO_BCDC=y -CONFIG_BRCMFMAC_PROTO_MSGBUF=y -CONFIG_BRCMFMAC_SDIO=y -CONFIG_BRCMFMAC_USB=y -CONFIG_BRCMFMAC_PCIE=y -# CONFIG_BRCM_TRACING is not set -# CONFIG_BRCMDBG is not set -CONFIG_WLAN_VENDOR_CISCO=y -# CONFIG_AIRO is not set -# CONFIG_AIRO_CS is not set -CONFIG_WLAN_VENDOR_INTEL=y -CONFIG_IPW2100=m -CONFIG_IPW2100_MONITOR=y -# CONFIG_IPW2100_DEBUG is not set -CONFIG_IPW2200=m -CONFIG_IPW2200_MONITOR=y -CONFIG_IPW2200_RADIOTAP=y -CONFIG_IPW2200_PROMISCUOUS=y -CONFIG_IPW2200_QOS=y -# CONFIG_IPW2200_DEBUG is not set -CONFIG_LIBIPW=m -# CONFIG_LIBIPW_DEBUG is not set -CONFIG_IWLEGACY=m -CONFIG_IWL4965=m -CONFIG_IWL3945=m - -# -# iwl3945 / iwl4965 Debugging Options -# -CONFIG_IWLEGACY_DEBUG=y -CONFIG_IWLEGACY_DEBUGFS=y -CONFIG_IWLWIFI=m -CONFIG_IWLWIFI_LEDS=y -CONFIG_IWLDVM=m -CONFIG_IWLMVM=m -CONFIG_IWLWIFI_OPMODE_MODULAR=y -# CONFIG_IWLWIFI_BCAST_FILTERING is not set - -# -# Debugging Options -# -CONFIG_IWLWIFI_DEBUG=y -CONFIG_IWLWIFI_DEBUGFS=y -CONFIG_IWLWIFI_DEVICE_TRACING=y -CONFIG_WLAN_VENDOR_INTERSIL=y -# CONFIG_HOSTAP is not set -# CONFIG_HERMES is not set -CONFIG_P54_COMMON=m -CONFIG_P54_USB=m -CONFIG_P54_PCI=m -CONFIG_P54_LEDS=y -# CONFIG_PRISM54 is not set -CONFIG_WLAN_VENDOR_MARVELL=y -CONFIG_LIBERTAS=m -CONFIG_LIBERTAS_USB=m -CONFIG_LIBERTAS_CS=m -CONFIG_LIBERTAS_SDIO=m -# CONFIG_LIBERTAS_DEBUG is not set -CONFIG_LIBERTAS_MESH=y -# CONFIG_LIBERTAS_THINFIRM is not set -CONFIG_MWIFIEX=m -CONFIG_MWIFIEX_SDIO=m -CONFIG_MWIFIEX_PCIE=m -CONFIG_MWIFIEX_USB=m -CONFIG_MWL8K=m -CONFIG_WLAN_VENDOR_MEDIATEK=y -CONFIG_MT7601U=m -# CONFIG_MT76x0U is not set -# CONFIG_MT76x2E is not set -# CONFIG_MT76x2U is not set -CONFIG_WLAN_VENDOR_RALINK=y -CONFIG_RT2X00=m -CONFIG_RT2400PCI=m -CONFIG_RT2500PCI=m -CONFIG_RT61PCI=m -CONFIG_RT2800PCI=m -CONFIG_RT2800PCI_RT33XX=y -CONFIG_RT2800PCI_RT35XX=y -CONFIG_RT2800PCI_RT53XX=y -CONFIG_RT2800PCI_RT3290=y -CONFIG_RT2500USB=m -CONFIG_RT73USB=m -CONFIG_RT2800USB=m -CONFIG_RT2800USB_RT33XX=y -CONFIG_RT2800USB_RT35XX=y -# CONFIG_RT2800USB_RT3573 is not set -CONFIG_RT2800USB_RT53XX=y -CONFIG_RT2800USB_RT55XX=y -CONFIG_RT2800USB_UNKNOWN=y -CONFIG_RT2800_LIB=m -CONFIG_RT2800_LIB_MMIO=m -CONFIG_RT2X00_LIB_MMIO=m -CONFIG_RT2X00_LIB_PCI=m -CONFIG_RT2X00_LIB_USB=m -CONFIG_RT2X00_LIB=m -CONFIG_RT2X00_LIB_FIRMWARE=y -CONFIG_RT2X00_LIB_CRYPTO=y -CONFIG_RT2X00_LIB_LEDS=y -CONFIG_RT2X00_LIB_DEBUGFS=y -# CONFIG_RT2X00_DEBUG is not set -CONFIG_WLAN_VENDOR_REALTEK=y -CONFIG_RTL8180=m -CONFIG_RTL8187=m -CONFIG_RTL8187_LEDS=y -CONFIG_RTL_CARDS=m -CONFIG_RTL8192CE=m -CONFIG_RTL8192SE=m -CONFIG_RTL8192DE=m -CONFIG_RTL8723AE=m -CONFIG_RTL8723BE=m -CONFIG_RTL8188EE=m -CONFIG_RTL8192EE=m -CONFIG_RTL8821AE=m -CONFIG_RTL8192CU=m -CONFIG_RTLWIFI=m -CONFIG_RTLWIFI_PCI=m -CONFIG_RTLWIFI_USB=m -# CONFIG_RTLWIFI_DEBUG is not set -CONFIG_RTL8192C_COMMON=m -CONFIG_RTL8723_COMMON=m -CONFIG_RTLBTCOEXIST=m -CONFIG_RTL8XXXU=m -# CONFIG_RTL8XXXU_UNTESTED is not set -CONFIG_WLAN_VENDOR_RSI=y -CONFIG_RSI_91X=m -CONFIG_RSI_DEBUGFS=y -CONFIG_RSI_SDIO=m -CONFIG_RSI_USB=m -CONFIG_RSI_COEX=y -CONFIG_WLAN_VENDOR_ST=y -CONFIG_CW1200=m -CONFIG_CW1200_WLAN_SDIO=m -CONFIG_WLAN_VENDOR_TI=y -# CONFIG_WL1251 is not set -# CONFIG_WL12XX is not set -# CONFIG_WL18XX is not set -# CONFIG_WLCORE is not set -CONFIG_WLAN_VENDOR_ZYDAS=y -# CONFIG_USB_ZD1201 is not set -CONFIG_ZD1211RW=m -# CONFIG_ZD1211RW_DEBUG is not set -CONFIG_WLAN_VENDOR_QUANTENNA=y -# CONFIG_QTNFMAC_PEARL_PCIE is not set -# CONFIG_PCMCIA_RAYCS is not set -# CONFIG_PCMCIA_WL3501 is not set -CONFIG_MAC80211_HWSIM=m -CONFIG_USB_NET_RNDIS_WLAN=m - -# -# WiMAX Wireless Broadband devices -# -CONFIG_WIMAX_I2400M=m -CONFIG_WIMAX_I2400M_USB=m -CONFIG_WIMAX_I2400M_DEBUG_LEVEL=8 -# CONFIG_WAN is not set -CONFIG_IEEE802154_DRIVERS=m -CONFIG_IEEE802154_FAKELB=m -# CONFIG_IEEE802154_ATUSB is not set -# CONFIG_IEEE802154_HWSIM is not set -CONFIG_XEN_NETDEV_FRONTEND=m -CONFIG_XEN_NETDEV_BACKEND=m -CONFIG_VMXNET3=m -CONFIG_FUJITSU_ES=m -# CONFIG_THUNDERBOLT_NET is not set -CONFIG_HYPERV_NET=m -# CONFIG_NETDEVSIM is not set -CONFIG_NET_FAILOVER=m -CONFIG_ISDN=y -CONFIG_ISDN_I4L=m -CONFIG_ISDN_PPP=y -CONFIG_ISDN_PPP_VJ=y -CONFIG_ISDN_MPP=y -CONFIG_IPPP_FILTER=y -# CONFIG_ISDN_PPP_BSDCOMP is not set -CONFIG_ISDN_AUDIO=y -CONFIG_ISDN_TTY_FAX=y - -# -# ISDN feature submodules -# -CONFIG_ISDN_DIVERSION=m - -# -# ISDN4Linux hardware drivers -# - -# -# Passive cards -# -CONFIG_ISDN_DRV_HISAX=m - -# -# D-channel protocol features -# -CONFIG_HISAX_EURO=y -CONFIG_DE_AOC=y -CONFIG_HISAX_NO_SENDCOMPLETE=y -CONFIG_HISAX_NO_LLC=y -CONFIG_HISAX_NO_KEYPAD=y -CONFIG_HISAX_1TR6=y -CONFIG_HISAX_NI1=y -CONFIG_HISAX_MAX_CARDS=8 - -# -# HiSax supported cards -# -CONFIG_HISAX_16_3=y -CONFIG_HISAX_TELESPCI=y -CONFIG_HISAX_S0BOX=y -CONFIG_HISAX_FRITZPCI=y -CONFIG_HISAX_AVM_A1_PCMCIA=y -CONFIG_HISAX_ELSA=y -CONFIG_HISAX_DIEHLDIVA=y -CONFIG_HISAX_SEDLBAUER=y -CONFIG_HISAX_NETJET=y -CONFIG_HISAX_NETJET_U=y -CONFIG_HISAX_NICCY=y -CONFIG_HISAX_BKM_A4T=y -CONFIG_HISAX_SCT_QUADRO=y -CONFIG_HISAX_GAZEL=y -CONFIG_HISAX_HFC_PCI=y -CONFIG_HISAX_W6692=y -CONFIG_HISAX_HFC_SX=y -CONFIG_HISAX_ENTERNOW_PCI=y -# CONFIG_HISAX_DEBUG is not set - -# -# HiSax PCMCIA card service modules -# -CONFIG_HISAX_SEDLBAUER_CS=m -CONFIG_HISAX_ELSA_CS=m -CONFIG_HISAX_AVM_A1_CS=m -CONFIG_HISAX_TELES_CS=m - -# -# HiSax sub driver modules -# -CONFIG_HISAX_ST5481=m -# CONFIG_HISAX_HFCUSB is not set -CONFIG_HISAX_HFC4S8S=m -CONFIG_HISAX_FRITZ_PCIPNP=m -CONFIG_ISDN_CAPI=m -# CONFIG_CAPI_TRACE is not set -CONFIG_ISDN_CAPI_CAPI20=m -CONFIG_ISDN_CAPI_MIDDLEWARE=y -CONFIG_ISDN_CAPI_CAPIDRV=m -# CONFIG_ISDN_CAPI_CAPIDRV_VERBOSE is not set - -# -# CAPI hardware drivers -# -CONFIG_CAPI_AVM=y -CONFIG_ISDN_DRV_AVMB1_B1PCI=m -CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y -CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m -CONFIG_ISDN_DRV_AVMB1_AVM_CS=m -CONFIG_ISDN_DRV_AVMB1_T1PCI=m -CONFIG_ISDN_DRV_AVMB1_C4=m -CONFIG_CAPI_EICON=y -CONFIG_ISDN_DIVAS=m -CONFIG_ISDN_DIVAS_BRIPCI=y -CONFIG_ISDN_DIVAS_PRIPCI=y -CONFIG_ISDN_DIVAS_DIVACAPI=m -CONFIG_ISDN_DIVAS_USERIDI=m -CONFIG_ISDN_DIVAS_MAINT=m -CONFIG_ISDN_DRV_GIGASET=m -CONFIG_GIGASET_CAPI=y -CONFIG_GIGASET_BASE=m -CONFIG_GIGASET_M105=m -CONFIG_GIGASET_M101=m -# CONFIG_GIGASET_DEBUG is not set -CONFIG_HYSDN=m -CONFIG_HYSDN_CAPI=y -CONFIG_MISDN=m -CONFIG_MISDN_DSP=m -CONFIG_MISDN_L1OIP=m - -# -# mISDN hardware drivers -# -CONFIG_MISDN_HFCPCI=m -CONFIG_MISDN_HFCMULTI=m -CONFIG_MISDN_HFCUSB=m -CONFIG_MISDN_AVMFRITZ=m -CONFIG_MISDN_SPEEDFAX=m -CONFIG_MISDN_INFINEON=m -CONFIG_MISDN_W6692=m -CONFIG_MISDN_NETJET=m -CONFIG_MISDN_IPAC=m -CONFIG_MISDN_ISAR=m -CONFIG_ISDN_HDLC=m -# CONFIG_NVM is not set - -# -# Input device support -# -CONFIG_INPUT=y -CONFIG_INPUT_LEDS=y -CONFIG_INPUT_FF_MEMLESS=y -CONFIG_INPUT_POLLDEV=m -CONFIG_INPUT_SPARSEKMAP=m -CONFIG_INPUT_MATRIXKMAP=m - -# -# Userland interfaces -# -CONFIG_INPUT_MOUSEDEV=y -# CONFIG_INPUT_MOUSEDEV_PSAUX is not set -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -CONFIG_INPUT_JOYDEV=m -CONFIG_INPUT_EVDEV=y -# CONFIG_INPUT_EVBUG is not set - -# -# Input Device Drivers -# -CONFIG_INPUT_KEYBOARD=y -# CONFIG_KEYBOARD_ADP5588 is not set -# CONFIG_KEYBOARD_ADP5589 is not set -CONFIG_KEYBOARD_ATKBD=y -# CONFIG_KEYBOARD_QT1070 is not set -# CONFIG_KEYBOARD_QT2160 is not set -# CONFIG_KEYBOARD_DLINK_DIR685 is not set -# CONFIG_KEYBOARD_LKKBD is not set -CONFIG_KEYBOARD_GPIO=m -CONFIG_KEYBOARD_GPIO_POLLED=m -# CONFIG_KEYBOARD_TCA6416 is not set -# CONFIG_KEYBOARD_TCA8418 is not set -CONFIG_KEYBOARD_MATRIX=m -# CONFIG_KEYBOARD_LM8323 is not set -# CONFIG_KEYBOARD_LM8333 is not set -# CONFIG_KEYBOARD_MAX7359 is not set -# CONFIG_KEYBOARD_MCS is not set -# CONFIG_KEYBOARD_MPR121 is not set -# CONFIG_KEYBOARD_NEWTON is not set -# CONFIG_KEYBOARD_OPENCORES is not set -CONFIG_KEYBOARD_SAMSUNG=m -# CONFIG_KEYBOARD_STOWAWAY is not set -# CONFIG_KEYBOARD_SUNKBD is not set -# CONFIG_KEYBOARD_TM2_TOUCHKEY is not set -# CONFIG_KEYBOARD_XTKBD is not set -CONFIG_KEYBOARD_CROS_EC=m -# CONFIG_KEYBOARD_MTK_PMIC is not set -CONFIG_INPUT_MOUSE=y -CONFIG_MOUSE_PS2=y -CONFIG_MOUSE_PS2_ALPS=y -CONFIG_MOUSE_PS2_BYD=y -CONFIG_MOUSE_PS2_LOGIPS2PP=y -CONFIG_MOUSE_PS2_SYNAPTICS=y -CONFIG_MOUSE_PS2_CYPRESS=y -CONFIG_MOUSE_PS2_LIFEBOOK=y -CONFIG_MOUSE_PS2_TRACKPOINT=y -CONFIG_MOUSE_PS2_ELANTECH=y -CONFIG_MOUSE_PS2_SENTELIC=y -# CONFIG_MOUSE_PS2_TOUCHKIT is not set -CONFIG_MOUSE_PS2_FOCALTECH=y -CONFIG_MOUSE_PS2_VMMOUSE=y -CONFIG_MOUSE_SERIAL=m -CONFIG_MOUSE_APPLETOUCH=m -CONFIG_MOUSE_BCM5974=m -CONFIG_MOUSE_CYAPA=m -# CONFIG_MOUSE_ELAN_I2C is not set -CONFIG_MOUSE_VSXXXAA=m -CONFIG_MOUSE_GPIO=m -CONFIG_MOUSE_SYNAPTICS_I2C=m -CONFIG_MOUSE_SYNAPTICS_USB=m -CONFIG_INPUT_JOYSTICK=y -CONFIG_JOYSTICK_ANALOG=m -CONFIG_JOYSTICK_A3D=m -CONFIG_JOYSTICK_ADI=m -CONFIG_JOYSTICK_COBRA=m -CONFIG_JOYSTICK_GF2K=m -CONFIG_JOYSTICK_GRIP=m -CONFIG_JOYSTICK_GRIP_MP=m -CONFIG_JOYSTICK_GUILLEMOT=m -CONFIG_JOYSTICK_INTERACT=m -CONFIG_JOYSTICK_SIDEWINDER=m -CONFIG_JOYSTICK_TMDC=m -CONFIG_JOYSTICK_IFORCE=m -CONFIG_JOYSTICK_IFORCE_USB=y -CONFIG_JOYSTICK_IFORCE_232=y -CONFIG_JOYSTICK_WARRIOR=m -CONFIG_JOYSTICK_MAGELLAN=m -CONFIG_JOYSTICK_SPACEORB=m -CONFIG_JOYSTICK_SPACEBALL=m -CONFIG_JOYSTICK_STINGER=m -CONFIG_JOYSTICK_TWIDJOY=m -CONFIG_JOYSTICK_ZHENHUA=m -CONFIG_JOYSTICK_DB9=m -CONFIG_JOYSTICK_GAMECON=m -CONFIG_JOYSTICK_TURBOGRAFX=m -# CONFIG_JOYSTICK_AS5011 is not set -CONFIG_JOYSTICK_JOYDUMP=m -CONFIG_JOYSTICK_XPAD=m -CONFIG_JOYSTICK_XPAD_FF=y -CONFIG_JOYSTICK_XPAD_LEDS=y -CONFIG_JOYSTICK_WALKERA0701=m -# CONFIG_JOYSTICK_PXRC is not set -CONFIG_INPUT_TABLET=y -CONFIG_TABLET_USB_ACECAD=m -CONFIG_TABLET_USB_AIPTEK=m -CONFIG_TABLET_USB_GTCO=m -CONFIG_TABLET_USB_HANWANG=m -CONFIG_TABLET_USB_KBTAB=m -CONFIG_TABLET_USB_PEGASUS=m -CONFIG_TABLET_SERIAL_WACOM4=m -CONFIG_INPUT_TOUCHSCREEN=y -CONFIG_TOUCHSCREEN_PROPERTIES=y -CONFIG_TOUCHSCREEN_AD7879=m -CONFIG_TOUCHSCREEN_AD7879_I2C=m -CONFIG_TOUCHSCREEN_ATMEL_MXT=m -CONFIG_TOUCHSCREEN_ATMEL_MXT_T37=y -CONFIG_TOUCHSCREEN_AUO_PIXCIR=m -CONFIG_TOUCHSCREEN_BU21013=m -# CONFIG_TOUCHSCREEN_BU21029 is not set -# CONFIG_TOUCHSCREEN_CHIPONE_ICN8505 is not set -CONFIG_TOUCHSCREEN_CY8CTMG110=m -CONFIG_TOUCHSCREEN_CYTTSP_CORE=m -CONFIG_TOUCHSCREEN_CYTTSP_I2C=m -CONFIG_TOUCHSCREEN_CYTTSP4_CORE=m -CONFIG_TOUCHSCREEN_CYTTSP4_I2C=m -CONFIG_TOUCHSCREEN_DYNAPRO=m -CONFIG_TOUCHSCREEN_HAMPSHIRE=m -CONFIG_TOUCHSCREEN_EETI=m -# CONFIG_TOUCHSCREEN_EGALAX_SERIAL is not set -# CONFIG_TOUCHSCREEN_EXC3000 is not set -CONFIG_TOUCHSCREEN_FUJITSU=m -# CONFIG_TOUCHSCREEN_GOODIX is not set -# CONFIG_TOUCHSCREEN_HIDEEP is not set -CONFIG_TOUCHSCREEN_ILI210X=m -# CONFIG_TOUCHSCREEN_S6SY761 is not set -CONFIG_TOUCHSCREEN_GUNZE=m -CONFIG_TOUCHSCREEN_EKTF2127=m -# CONFIG_TOUCHSCREEN_ELAN is not set -CONFIG_TOUCHSCREEN_ELO=m -CONFIG_TOUCHSCREEN_WACOM_W8001=m -CONFIG_TOUCHSCREEN_WACOM_I2C=m -CONFIG_TOUCHSCREEN_MAX11801=m -CONFIG_TOUCHSCREEN_MCS5000=m -CONFIG_TOUCHSCREEN_MMS114=m -# CONFIG_TOUCHSCREEN_MELFAS_MIP4 is not set -CONFIG_TOUCHSCREEN_MTOUCH=m -CONFIG_TOUCHSCREEN_INEXIO=m -CONFIG_TOUCHSCREEN_MK712=m -CONFIG_TOUCHSCREEN_PENMOUNT=m -CONFIG_TOUCHSCREEN_EDT_FT5X06=m -CONFIG_TOUCHSCREEN_TOUCHRIGHT=m -CONFIG_TOUCHSCREEN_TOUCHWIN=m -CONFIG_TOUCHSCREEN_TI_AM335X_TSC=m -CONFIG_TOUCHSCREEN_UCB1400=m -CONFIG_TOUCHSCREEN_PIXCIR=m -# CONFIG_TOUCHSCREEN_WDT87XX_I2C is not set -CONFIG_TOUCHSCREEN_WM97XX=m -CONFIG_TOUCHSCREEN_WM9705=y -CONFIG_TOUCHSCREEN_WM9712=y -CONFIG_TOUCHSCREEN_WM9713=y -CONFIG_TOUCHSCREEN_USB_COMPOSITE=m -CONFIG_TOUCHSCREEN_USB_EGALAX=y -CONFIG_TOUCHSCREEN_USB_PANJIT=y -CONFIG_TOUCHSCREEN_USB_3M=y -CONFIG_TOUCHSCREEN_USB_ITM=y -CONFIG_TOUCHSCREEN_USB_ETURBO=y -CONFIG_TOUCHSCREEN_USB_GUNZE=y -CONFIG_TOUCHSCREEN_USB_DMC_TSC10=y -CONFIG_TOUCHSCREEN_USB_IRTOUCH=y -CONFIG_TOUCHSCREEN_USB_IDEALTEK=y -CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH=y -CONFIG_TOUCHSCREEN_USB_GOTOP=y -CONFIG_TOUCHSCREEN_USB_JASTEC=y -CONFIG_TOUCHSCREEN_USB_ELO=y -CONFIG_TOUCHSCREEN_USB_E2I=y -CONFIG_TOUCHSCREEN_USB_ZYTRONIC=y -CONFIG_TOUCHSCREEN_USB_ETT_TC45USB=y -CONFIG_TOUCHSCREEN_USB_NEXIO=y -CONFIG_TOUCHSCREEN_USB_EASYTOUCH=y -CONFIG_TOUCHSCREEN_TOUCHIT213=m -CONFIG_TOUCHSCREEN_TSC_SERIO=m -CONFIG_TOUCHSCREEN_TSC200X_CORE=m -CONFIG_TOUCHSCREEN_TSC2004=m -CONFIG_TOUCHSCREEN_TSC2007=m -CONFIG_TOUCHSCREEN_RM_TS=m -CONFIG_TOUCHSCREEN_SILEAD=m -CONFIG_TOUCHSCREEN_SIS_I2C=m -CONFIG_TOUCHSCREEN_ST1232=m -# CONFIG_TOUCHSCREEN_STMFTS is not set -CONFIG_TOUCHSCREEN_SUR40=m -CONFIG_TOUCHSCREEN_SX8654=m -CONFIG_TOUCHSCREEN_TPS6507X=m -# CONFIG_TOUCHSCREEN_ZET6223 is not set -CONFIG_TOUCHSCREEN_ZFORCE=m -CONFIG_TOUCHSCREEN_ROHM_BU21023=m -CONFIG_INPUT_MISC=y -# CONFIG_INPUT_AD714X is not set -# CONFIG_INPUT_BMA150 is not set -CONFIG_INPUT_E3X0_BUTTON=m -CONFIG_INPUT_PCSPKR=m -CONFIG_INPUT_MMA8450=m -CONFIG_INPUT_APANEL=m -CONFIG_INPUT_GP2A=m -CONFIG_INPUT_GPIO_BEEPER=m -CONFIG_INPUT_GPIO_DECODER=m -CONFIG_INPUT_ATLAS_BTNS=m -CONFIG_INPUT_ATI_REMOTE2=m -CONFIG_INPUT_KEYSPAN_REMOTE=m -CONFIG_INPUT_KXTJ9=m -# CONFIG_INPUT_KXTJ9_POLLED_MODE is not set -CONFIG_INPUT_POWERMATE=m -CONFIG_INPUT_YEALINK=m -CONFIG_INPUT_CM109=m -CONFIG_INPUT_RETU_PWRBUTTON=m -CONFIG_INPUT_UINPUT=m -# CONFIG_INPUT_PCF8574 is not set -CONFIG_INPUT_PWM_BEEPER=m -# CONFIG_INPUT_PWM_VIBRA is not set -CONFIG_INPUT_GPIO_ROTARY_ENCODER=m -# CONFIG_INPUT_ADXL34X is not set -CONFIG_INPUT_IMS_PCU=m -CONFIG_INPUT_CMA3000=m -CONFIG_INPUT_CMA3000_I2C=m -CONFIG_INPUT_XEN_KBDDEV_FRONTEND=y -CONFIG_INPUT_IDEAPAD_SLIDEBAR=m -CONFIG_INPUT_SOC_BUTTON_ARRAY=m -CONFIG_INPUT_DRV260X_HAPTICS=m -# CONFIG_INPUT_DRV2665_HAPTICS is not set -# CONFIG_INPUT_DRV2667_HAPTICS is not set -CONFIG_RMI4_CORE=m -# CONFIG_RMI4_I2C is not set -# CONFIG_RMI4_SMB is not set -CONFIG_RMI4_F03=y -CONFIG_RMI4_F03_SERIO=m -CONFIG_RMI4_2D_SENSOR=y -CONFIG_RMI4_F11=y -CONFIG_RMI4_F12=y -CONFIG_RMI4_F30=y -# CONFIG_RMI4_F34 is not set -# CONFIG_RMI4_F54 is not set -# CONFIG_RMI4_F55 is not set - -# -# Hardware I/O ports -# -CONFIG_SERIO=y -CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y -CONFIG_SERIO_I8042=y -CONFIG_SERIO_SERPORT=y -CONFIG_SERIO_CT82C710=m -CONFIG_SERIO_PARKBD=m -CONFIG_SERIO_PCIPS2=m -CONFIG_SERIO_LIBPS2=y -CONFIG_SERIO_RAW=m -CONFIG_SERIO_ALTERA_PS2=m -CONFIG_SERIO_PS2MULT=m -CONFIG_SERIO_ARC_PS2=m -CONFIG_HYPERV_KEYBOARD=m -# CONFIG_SERIO_GPIO_PS2 is not set -CONFIG_USERIO=m -CONFIG_GAMEPORT=m -CONFIG_GAMEPORT_NS558=m -CONFIG_GAMEPORT_L4=m -CONFIG_GAMEPORT_EMU10K1=m -CONFIG_GAMEPORT_FM801=m - -# -# Character devices -# -CONFIG_TTY=y -CONFIG_VT=y -CONFIG_CONSOLE_TRANSLATIONS=y -CONFIG_VT_CONSOLE=y -CONFIG_VT_CONSOLE_SLEEP=y -CONFIG_HW_CONSOLE=y -CONFIG_VT_HW_CONSOLE_BINDING=y -CONFIG_UNIX98_PTYS=y -# CONFIG_LEGACY_PTYS is not set -CONFIG_SERIAL_NONSTANDARD=y -CONFIG_ROCKETPORT=m -CONFIG_CYCLADES=m -# CONFIG_CYZ_INTR is not set -# CONFIG_MOXA_INTELLIO is not set -# CONFIG_MOXA_SMARTIO is not set -CONFIG_SYNCLINK=m -CONFIG_SYNCLINKMP=m -CONFIG_SYNCLINK_GT=m -CONFIG_NOZOMI=m -# CONFIG_ISI is not set -CONFIG_N_HDLC=m -CONFIG_N_GSM=m -# CONFIG_TRACE_SINK is not set -CONFIG_LDISC_AUTOLOAD=y -CONFIG_DEVMEM=y -# CONFIG_DEVKMEM is not set - -# -# Serial drivers -# -CONFIG_SERIAL_EARLYCON=y -CONFIG_SERIAL_8250=y -# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set -CONFIG_SERIAL_8250_PNP=y -# CONFIG_SERIAL_8250_FINTEK is not set -CONFIG_SERIAL_8250_CONSOLE=y -CONFIG_SERIAL_8250_DMA=y -CONFIG_SERIAL_8250_PCI=y -CONFIG_SERIAL_8250_EXAR=y -CONFIG_SERIAL_8250_CS=m -CONFIG_SERIAL_8250_NR_UARTS=32 -CONFIG_SERIAL_8250_RUNTIME_UARTS=4 -CONFIG_SERIAL_8250_EXTENDED=y -CONFIG_SERIAL_8250_MANY_PORTS=y -CONFIG_SERIAL_8250_SHARE_IRQ=y -# CONFIG_SERIAL_8250_DETECT_IRQ is not set -CONFIG_SERIAL_8250_RSA=y -CONFIG_SERIAL_8250_DW=m -# CONFIG_SERIAL_8250_RT288X is not set -CONFIG_SERIAL_8250_LPSS=y -CONFIG_SERIAL_8250_MID=y -# CONFIG_SERIAL_8250_MOXA is not set - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_UARTLITE=m -CONFIG_SERIAL_UARTLITE_NR_UARTS=1 -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -CONFIG_SERIAL_JSM=m -CONFIG_SERIAL_SCCNXP=m -CONFIG_SERIAL_SC16IS7XX_CORE=m -CONFIG_SERIAL_SC16IS7XX=m -CONFIG_SERIAL_SC16IS7XX_I2C=y -CONFIG_SERIAL_ALTERA_JTAGUART=m -CONFIG_SERIAL_ALTERA_UART=m -CONFIG_SERIAL_ALTERA_UART_MAXPORTS=4 -CONFIG_SERIAL_ALTERA_UART_BAUDRATE=115200 -CONFIG_SERIAL_ARC=m -CONFIG_SERIAL_ARC_NR_PORTS=1 -CONFIG_SERIAL_RP2=m -CONFIG_SERIAL_RP2_NR_UARTS=32 -CONFIG_SERIAL_FSL_LPUART=m -# CONFIG_SERIAL_DEV_BUS is not set -CONFIG_PRINTER=m -CONFIG_LP_CONSOLE=y -CONFIG_PPDEV=m -CONFIG_HVC_DRIVER=y -CONFIG_HVC_IRQ=y -CONFIG_HVC_XEN=y -CONFIG_HVC_XEN_FRONTEND=y -CONFIG_VIRTIO_CONSOLE=y -CONFIG_IPMI_HANDLER=m -CONFIG_IPMI_DMI_DECODE=y -# CONFIG_IPMI_PANIC_EVENT is not set -CONFIG_IPMI_DEVICE_INTERFACE=m -CONFIG_IPMI_SI=m -# CONFIG_IPMI_SSIF is not set -CONFIG_IPMI_WATCHDOG=m -CONFIG_IPMI_POWEROFF=m -CONFIG_HW_RANDOM=y -CONFIG_HW_RANDOM_TIMERIOMEM=m -CONFIG_HW_RANDOM_INTEL=m -CONFIG_HW_RANDOM_AMD=m -CONFIG_HW_RANDOM_VIA=m -CONFIG_HW_RANDOM_VIRTIO=m -CONFIG_NVRAM=y -# CONFIG_APPLICOM is not set - -# -# PCMCIA character devices -# -# CONFIG_SYNCLINK_CS is not set -CONFIG_CARDMAN_4000=m -CONFIG_CARDMAN_4040=m -# CONFIG_SCR24X is not set -CONFIG_IPWIRELESS=m -CONFIG_MWAVE=m -CONFIG_RAW_DRIVER=y -CONFIG_MAX_RAW_DEVS=8192 -CONFIG_HPET=y -# CONFIG_HPET_MMAP is not set -CONFIG_HANGCHECK_TIMER=m -CONFIG_TCG_TPM=m -CONFIG_HW_RANDOM_TPM=y -CONFIG_TCG_TIS_CORE=m -CONFIG_TCG_TIS=m -CONFIG_TCG_TIS_I2C_ATMEL=m -CONFIG_TCG_TIS_I2C_INFINEON=m -CONFIG_TCG_TIS_I2C_NUVOTON=m -CONFIG_TCG_NSC=m -CONFIG_TCG_ATMEL=m -CONFIG_TCG_INFINEON=m -CONFIG_TCG_XEN=m -CONFIG_TCG_CRB=m -CONFIG_TCG_VTPM_PROXY=m -CONFIG_TCG_TIS_ST33ZP24=m -CONFIG_TCG_TIS_ST33ZP24_I2C=m -CONFIG_TELCLOCK=m -CONFIG_DEVPORT=y -CONFIG_XILLYBUS=m -# CONFIG_XILLYBUS_PCIE is not set -# CONFIG_RANDOM_TRUST_CPU is not set - -# -# I2C support -# -CONFIG_I2C=m -CONFIG_I2C_BOARDINFO=y -CONFIG_I2C_COMPAT=y -CONFIG_I2C_CHARDEV=m -CONFIG_I2C_MUX=m - -# -# Multiplexer I2C Chip support -# -CONFIG_I2C_MUX_GPIO=m -# CONFIG_I2C_MUX_LTC4306 is not set -CONFIG_I2C_MUX_PCA9541=m -CONFIG_I2C_MUX_PCA954x=m -CONFIG_I2C_MUX_REG=m -# CONFIG_I2C_MUX_MLXCPLD is not set -CONFIG_I2C_HELPER_AUTO=y -CONFIG_I2C_SMBUS=m -CONFIG_I2C_ALGOBIT=m -CONFIG_I2C_ALGOPCA=m - -# -# I2C Hardware Bus support -# - -# -# PC SMBus host controller drivers -# -# CONFIG_I2C_ALI1535 is not set -# CONFIG_I2C_ALI1563 is not set -# CONFIG_I2C_ALI15X3 is not set -CONFIG_I2C_AMD756=m -CONFIG_I2C_AMD756_S4882=m -CONFIG_I2C_AMD8111=m -CONFIG_I2C_I801=m -CONFIG_I2C_ISCH=m -CONFIG_I2C_ISMT=m -CONFIG_I2C_PIIX4=m -CONFIG_I2C_NFORCE2=m -CONFIG_I2C_NFORCE2_S4985=m -# CONFIG_I2C_SIS5595 is not set -# CONFIG_I2C_SIS630 is not set -CONFIG_I2C_SIS96X=m -CONFIG_I2C_VIA=m -CONFIG_I2C_VIAPRO=m - -# -# ACPI drivers -# -CONFIG_I2C_SCMI=m - -# -# I2C system bus drivers (mostly embedded / system-on-chip) -# -CONFIG_I2C_CBUS_GPIO=m -CONFIG_I2C_DESIGNWARE_CORE=m -CONFIG_I2C_DESIGNWARE_PLATFORM=m -# CONFIG_I2C_DESIGNWARE_SLAVE is not set -# CONFIG_I2C_DESIGNWARE_PCI is not set -# CONFIG_I2C_DESIGNWARE_BAYTRAIL is not set -CONFIG_I2C_EMEV2=m -CONFIG_I2C_GPIO=m -# CONFIG_I2C_GPIO_FAULT_INJECTOR is not set -# CONFIG_I2C_OCORES is not set -CONFIG_I2C_PCA_PLATFORM=m -CONFIG_I2C_SIMTEC=m -# CONFIG_I2C_XILINX is not set - -# -# External I2C/SMBus adapter drivers -# -CONFIG_I2C_DIOLAN_U2C=m -CONFIG_I2C_PARPORT=m -CONFIG_I2C_PARPORT_LIGHT=m -CONFIG_I2C_ROBOTFUZZ_OSIF=m -# CONFIG_I2C_TAOS_EVM is not set -CONFIG_I2C_TINY_USB=m -CONFIG_I2C_VIPERBOARD=m - -# -# Other I2C/SMBus bus drivers -# -# CONFIG_I2C_MLXCPLD is not set -CONFIG_I2C_CROS_EC_TUNNEL=m -CONFIG_I2C_STUB=m -CONFIG_I2C_SLAVE=y -# CONFIG_I2C_SLAVE_EEPROM is not set -# CONFIG_I2C_DEBUG_CORE is not set -# CONFIG_I2C_DEBUG_ALGO is not set -# CONFIG_I2C_DEBUG_BUS is not set -# CONFIG_SPI is not set -CONFIG_SPMI=m -# CONFIG_HSI is not set -CONFIG_PPS=y -# CONFIG_PPS_DEBUG is not set - -# -# PPS clients support -# -# CONFIG_PPS_CLIENT_KTIMER is not set -CONFIG_PPS_CLIENT_LDISC=m -CONFIG_PPS_CLIENT_PARPORT=m -CONFIG_PPS_CLIENT_GPIO=m - -# -# PPS generators support -# - -# -# PTP clock support -# -CONFIG_PTP_1588_CLOCK=y -CONFIG_DP83640_PHY=m -CONFIG_PTP_1588_CLOCK_KVM=m -CONFIG_PINCTRL=y -CONFIG_PINMUX=y -CONFIG_PINCONF=y -CONFIG_GENERIC_PINCONF=y -CONFIG_PINCTRL_AMD=y -# CONFIG_PINCTRL_MCP23S08 is not set -CONFIG_PINCTRL_BAYTRAIL=y -CONFIG_PINCTRL_CHERRYVIEW=m -CONFIG_PINCTRL_INTEL=m -CONFIG_PINCTRL_BROXTON=m -# CONFIG_PINCTRL_CANNONLAKE is not set -# CONFIG_PINCTRL_CEDARFORK is not set -# CONFIG_PINCTRL_DENVERTON is not set -# CONFIG_PINCTRL_GEMINILAKE is not set -# CONFIG_PINCTRL_ICELAKE is not set -# CONFIG_PINCTRL_LEWISBURG is not set -CONFIG_PINCTRL_SUNRISEPOINT=m -CONFIG_GPIOLIB=y -CONFIG_GPIOLIB_FASTPATH_LIMIT=512 -CONFIG_GPIO_ACPI=y -CONFIG_GPIOLIB_IRQCHIP=y -CONFIG_GPIO_SYSFS=y -CONFIG_GPIO_GENERIC=y -CONFIG_GPIO_MAX730X=m - -# -# Memory mapped GPIO drivers -# -CONFIG_GPIO_AMDPT=m -CONFIG_GPIO_DWAPB=m -# CONFIG_GPIO_EXAR is not set -CONFIG_GPIO_GENERIC_PLATFORM=y -CONFIG_GPIO_ICH=m -CONFIG_GPIO_LYNXPOINT=m -# CONFIG_GPIO_MB86S7X is not set -CONFIG_GPIO_MOCKUP=m -CONFIG_GPIO_VX855=m - -# -# Port-mapped I/O GPIO drivers -# -CONFIG_GPIO_F7188X=m -CONFIG_GPIO_IT87=m -CONFIG_GPIO_SCH=m -CONFIG_GPIO_SCH311X=m -# CONFIG_GPIO_WINBOND is not set -# CONFIG_GPIO_WS16C48 is not set - -# -# I2C GPIO expanders -# -CONFIG_GPIO_ADP5588=m -CONFIG_GPIO_MAX7300=m -CONFIG_GPIO_MAX732X=m -CONFIG_GPIO_PCA953X=m -CONFIG_GPIO_PCF857X=m -# CONFIG_GPIO_TPIC2810 is not set - -# -# MFD GPIO expanders -# -CONFIG_GPIO_LP3943=m -CONFIG_GPIO_LP873X=m -CONFIG_GPIO_UCB1400=m - -# -# PCI GPIO expanders -# -CONFIG_GPIO_AMD8111=m -CONFIG_GPIO_ML_IOH=m -# CONFIG_GPIO_PCI_IDIO_16 is not set -# CONFIG_GPIO_PCIE_IDIO_24 is not set -CONFIG_GPIO_RDC321X=m - -# -# USB GPIO expanders -# -CONFIG_GPIO_VIPERBOARD=m -CONFIG_W1=m -CONFIG_W1_CON=y - -# -# 1-wire Bus Masters -# -# CONFIG_W1_MASTER_MATROX is not set -CONFIG_W1_MASTER_DS2490=m -CONFIG_W1_MASTER_DS2482=m -CONFIG_W1_MASTER_DS1WM=m -CONFIG_W1_MASTER_GPIO=m - -# -# 1-wire Slaves -# -CONFIG_W1_SLAVE_THERM=m -CONFIG_W1_SLAVE_SMEM=m -# CONFIG_W1_SLAVE_DS2405 is not set -CONFIG_W1_SLAVE_DS2408=m -CONFIG_W1_SLAVE_DS2408_READBACK=y -CONFIG_W1_SLAVE_DS2413=m -CONFIG_W1_SLAVE_DS2406=m -CONFIG_W1_SLAVE_DS2423=m -# CONFIG_W1_SLAVE_DS2805 is not set -CONFIG_W1_SLAVE_DS2431=m -CONFIG_W1_SLAVE_DS2433=m -CONFIG_W1_SLAVE_DS2433_CRC=y -# CONFIG_W1_SLAVE_DS2438 is not set -CONFIG_W1_SLAVE_DS2780=m -CONFIG_W1_SLAVE_DS2781=m -CONFIG_W1_SLAVE_DS28E04=m -# CONFIG_W1_SLAVE_DS28E17 is not set -CONFIG_POWER_AVS=y -# CONFIG_POWER_RESET is not set -CONFIG_POWER_SUPPLY=y -# CONFIG_POWER_SUPPLY_DEBUG is not set -# CONFIG_PDA_POWER is not set -# CONFIG_TEST_POWER is not set -# CONFIG_CHARGER_ADP5061 is not set -# CONFIG_BATTERY_DS2760 is not set -# CONFIG_BATTERY_DS2780 is not set -# CONFIG_BATTERY_DS2781 is not set -# CONFIG_BATTERY_DS2782 is not set -# CONFIG_BATTERY_SBS is not set -# CONFIG_CHARGER_SBS is not set -# CONFIG_MANAGER_SBS is not set -CONFIG_BATTERY_BQ27XXX=m -CONFIG_BATTERY_BQ27XXX_I2C=m -CONFIG_BATTERY_BQ27XXX_HDQ=m -# CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVM is not set -# CONFIG_BATTERY_MAX17040 is not set -# CONFIG_BATTERY_MAX17042 is not set -# CONFIG_BATTERY_MAX1721X is not set -# CONFIG_CHARGER_ISP1704 is not set -# CONFIG_CHARGER_MAX8903 is not set -# CONFIG_CHARGER_LP8727 is not set -CONFIG_CHARGER_GPIO=m -# CONFIG_CHARGER_LTC3651 is not set -CONFIG_CHARGER_MAX14577=m -CONFIG_CHARGER_BQ2415X=m -CONFIG_CHARGER_BQ24190=m -# CONFIG_CHARGER_BQ24257 is not set -CONFIG_CHARGER_BQ24735=m -# CONFIG_CHARGER_BQ25890 is not set -CONFIG_CHARGER_SMB347=m -CONFIG_BATTERY_GAUGE_LTC2941=m -# CONFIG_CHARGER_RT9455 is not set -# CONFIG_CHARGER_CROS_USBPD is not set -CONFIG_HWMON=y -CONFIG_HWMON_VID=m -# CONFIG_HWMON_DEBUG_CHIP is not set - -# -# Native drivers -# -CONFIG_SENSORS_ABITUGURU=m -CONFIG_SENSORS_ABITUGURU3=m -CONFIG_SENSORS_AD7414=m -CONFIG_SENSORS_AD7418=m -CONFIG_SENSORS_ADM1021=m -CONFIG_SENSORS_ADM1025=m -CONFIG_SENSORS_ADM1026=m -CONFIG_SENSORS_ADM1029=m -CONFIG_SENSORS_ADM1031=m -CONFIG_SENSORS_ADM9240=m -CONFIG_SENSORS_ADT7X10=m -CONFIG_SENSORS_ADT7410=m -CONFIG_SENSORS_ADT7411=m -CONFIG_SENSORS_ADT7462=m -CONFIG_SENSORS_ADT7470=m -CONFIG_SENSORS_ADT7475=m -CONFIG_SENSORS_ASC7621=m -CONFIG_SENSORS_K8TEMP=m -CONFIG_SENSORS_K10TEMP=m -CONFIG_SENSORS_FAM15H_POWER=m -CONFIG_SENSORS_APPLESMC=m -CONFIG_SENSORS_ASB100=m -# CONFIG_SENSORS_ASPEED is not set -CONFIG_SENSORS_ATXP1=m -CONFIG_SENSORS_DS620=m -CONFIG_SENSORS_DS1621=m -CONFIG_SENSORS_DELL_SMM=m -CONFIG_SENSORS_I5K_AMB=m -CONFIG_SENSORS_F71805F=m -CONFIG_SENSORS_F71882FG=m -CONFIG_SENSORS_F75375S=m -CONFIG_SENSORS_FSCHMD=m -CONFIG_SENSORS_FTSTEUTATES=m -CONFIG_SENSORS_GL518SM=m -CONFIG_SENSORS_GL520SM=m -CONFIG_SENSORS_G760A=m -CONFIG_SENSORS_G762=m -CONFIG_SENSORS_HIH6130=m -CONFIG_SENSORS_IBMAEM=m -CONFIG_SENSORS_IBMPEX=m -# CONFIG_SENSORS_I5500 is not set -CONFIG_SENSORS_CORETEMP=m -CONFIG_SENSORS_IT87=m -# CONFIG_SENSORS_JC42 is not set -CONFIG_SENSORS_POWR1220=m -CONFIG_SENSORS_LINEAGE=m -CONFIG_SENSORS_LTC2945=m -# CONFIG_SENSORS_LTC2990 is not set -CONFIG_SENSORS_LTC4151=m -CONFIG_SENSORS_LTC4215=m -CONFIG_SENSORS_LTC4222=m -CONFIG_SENSORS_LTC4245=m -CONFIG_SENSORS_LTC4260=m -CONFIG_SENSORS_LTC4261=m -CONFIG_SENSORS_MAX16065=m -CONFIG_SENSORS_MAX1619=m -CONFIG_SENSORS_MAX1668=m -CONFIG_SENSORS_MAX197=m -# CONFIG_SENSORS_MAX6621 is not set -CONFIG_SENSORS_MAX6639=m -CONFIG_SENSORS_MAX6642=m -CONFIG_SENSORS_MAX6650=m -CONFIG_SENSORS_MAX6697=m -CONFIG_SENSORS_MAX31790=m -CONFIG_SENSORS_MCP3021=m -# CONFIG_SENSORS_TC654 is not set -CONFIG_SENSORS_LM63=m -CONFIG_SENSORS_LM73=m -CONFIG_SENSORS_LM75=m -CONFIG_SENSORS_LM77=m -CONFIG_SENSORS_LM78=m -CONFIG_SENSORS_LM80=m -CONFIG_SENSORS_LM83=m -CONFIG_SENSORS_LM85=m -CONFIG_SENSORS_LM87=m -CONFIG_SENSORS_LM90=m -CONFIG_SENSORS_LM92=m -CONFIG_SENSORS_LM93=m -CONFIG_SENSORS_LM95234=m -CONFIG_SENSORS_LM95241=m -CONFIG_SENSORS_LM95245=m -CONFIG_SENSORS_PC87360=m -CONFIG_SENSORS_PC87427=m -CONFIG_SENSORS_NTC_THERMISTOR=m -CONFIG_SENSORS_NCT6683=m -CONFIG_SENSORS_NCT6775=m -# CONFIG_SENSORS_NCT7802 is not set -CONFIG_SENSORS_NCT7904=m -# CONFIG_SENSORS_NPCM7XX is not set -CONFIG_SENSORS_PCF8591=m -CONFIG_PMBUS=m -CONFIG_SENSORS_PMBUS=m -CONFIG_SENSORS_ADM1275=m -# CONFIG_SENSORS_IBM_CFFPS is not set -# CONFIG_SENSORS_IR35221 is not set -CONFIG_SENSORS_LM25066=m -CONFIG_SENSORS_LTC2978=m -# CONFIG_SENSORS_LTC3815 is not set -CONFIG_SENSORS_MAX16064=m -CONFIG_SENSORS_MAX20751=m -# CONFIG_SENSORS_MAX31785 is not set -CONFIG_SENSORS_MAX34440=m -CONFIG_SENSORS_MAX8688=m -CONFIG_SENSORS_TPS40422=m -# CONFIG_SENSORS_TPS53679 is not set -CONFIG_SENSORS_UCD9000=m -CONFIG_SENSORS_UCD9200=m -CONFIG_SENSORS_ZL6100=m -CONFIG_SENSORS_SHT15=m -CONFIG_SENSORS_SHT21=m -CONFIG_SENSORS_SHT3x=m -CONFIG_SENSORS_SHTC1=m -CONFIG_SENSORS_SIS5595=m -CONFIG_SENSORS_DME1737=m -CONFIG_SENSORS_EMC1403=m -# CONFIG_SENSORS_EMC2103 is not set -CONFIG_SENSORS_EMC6W201=m -CONFIG_SENSORS_SMSC47M1=m -CONFIG_SENSORS_SMSC47M192=m -CONFIG_SENSORS_SMSC47B397=m -CONFIG_SENSORS_SCH56XX_COMMON=m -CONFIG_SENSORS_SCH5627=m -CONFIG_SENSORS_SCH5636=m -# CONFIG_SENSORS_STTS751 is not set -# CONFIG_SENSORS_SMM665 is not set -CONFIG_SENSORS_ADC128D818=m -CONFIG_SENSORS_ADS1015=m -CONFIG_SENSORS_ADS7828=m -CONFIG_SENSORS_AMC6821=m -CONFIG_SENSORS_INA209=m -CONFIG_SENSORS_INA2XX=m -CONFIG_SENSORS_INA3221=m -# CONFIG_SENSORS_TC74 is not set -CONFIG_SENSORS_THMC50=m -CONFIG_SENSORS_TMP102=m -CONFIG_SENSORS_TMP103=m -# CONFIG_SENSORS_TMP108 is not set -CONFIG_SENSORS_TMP401=m -CONFIG_SENSORS_TMP421=m -CONFIG_SENSORS_VIA_CPUTEMP=m -CONFIG_SENSORS_VIA686A=m -CONFIG_SENSORS_VT1211=m -CONFIG_SENSORS_VT8231=m -# CONFIG_SENSORS_W83773G is not set -CONFIG_SENSORS_W83781D=m -CONFIG_SENSORS_W83791D=m -CONFIG_SENSORS_W83792D=m -CONFIG_SENSORS_W83793=m -CONFIG_SENSORS_W83795=m -# CONFIG_SENSORS_W83795_FANCTRL is not set -CONFIG_SENSORS_W83L785TS=m -CONFIG_SENSORS_W83L786NG=m -CONFIG_SENSORS_W83627HF=m -CONFIG_SENSORS_W83627EHF=m -# CONFIG_SENSORS_XGENE is not set - -# -# ACPI drivers -# -CONFIG_SENSORS_ACPI_POWER=m -CONFIG_SENSORS_ATK0110=m -CONFIG_THERMAL=y -# CONFIG_THERMAL_STATISTICS is not set -CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 -CONFIG_THERMAL_HWMON=y -CONFIG_THERMAL_WRITABLE_TRIPS=y -CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y -# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set -# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set -# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set -CONFIG_THERMAL_GOV_FAIR_SHARE=y -CONFIG_THERMAL_GOV_STEP_WISE=y -CONFIG_THERMAL_GOV_BANG_BANG=y -CONFIG_THERMAL_GOV_USER_SPACE=y -# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set -# CONFIG_CLOCK_THERMAL is not set -# CONFIG_DEVFREQ_THERMAL is not set -# CONFIG_THERMAL_EMULATION is not set -# CONFIG_INTEL_POWERCLAMP is not set -CONFIG_X86_PKG_TEMP_THERMAL=m -CONFIG_INTEL_SOC_DTS_IOSF_CORE=m -CONFIG_INTEL_SOC_DTS_THERMAL=m - -# -# ACPI INT340X thermal drivers -# -# CONFIG_INT340X_THERMAL is not set -CONFIG_INTEL_PCH_THERMAL=m -CONFIG_WATCHDOG=y -CONFIG_WATCHDOG_CORE=y -# CONFIG_WATCHDOG_NOWAYOUT is not set -CONFIG_WATCHDOG_HANDLE_BOOT_ENABLED=y -# CONFIG_WATCHDOG_SYSFS is not set - -# -# Watchdog Device Drivers -# -CONFIG_SOFT_WATCHDOG=m -# CONFIG_SOFT_WATCHDOG_PRETIMEOUT is not set -CONFIG_WDAT_WDT=m -# CONFIG_XILINX_WATCHDOG is not set -# CONFIG_ZIIRAVE_WATCHDOG is not set -CONFIG_CADENCE_WATCHDOG=m -CONFIG_DW_WATCHDOG=m -# CONFIG_MAX63XX_WATCHDOG is not set -CONFIG_RETU_WATCHDOG=m -# CONFIG_ACQUIRE_WDT is not set -# CONFIG_ADVANTECH_WDT is not set -CONFIG_ALIM1535_WDT=m -CONFIG_ALIM7101_WDT=m -# CONFIG_EBC_C384_WDT is not set -CONFIG_F71808E_WDT=m -# CONFIG_SP5100_TCO is not set -CONFIG_SBC_FITPC2_WATCHDOG=m -# CONFIG_EUROTECH_WDT is not set -CONFIG_IB700_WDT=m -CONFIG_IBMASR=m -# CONFIG_WAFER_WDT is not set -CONFIG_I6300ESB_WDT=m -CONFIG_IE6XX_WDT=m -CONFIG_ITCO_WDT=m -CONFIG_ITCO_VENDOR_SUPPORT=y -CONFIG_IT8712F_WDT=m -CONFIG_IT87_WDT=m -CONFIG_HP_WATCHDOG=m -CONFIG_HPWDT_NMI_DECODING=y -# CONFIG_SC1200_WDT is not set -# CONFIG_PC87413_WDT is not set -CONFIG_NV_TCO=m -# CONFIG_60XX_WDT is not set -# CONFIG_CPU5_WDT is not set -CONFIG_SMSC_SCH311X_WDT=m -# CONFIG_SMSC37B787_WDT is not set -CONFIG_VIA_WDT=m -CONFIG_W83627HF_WDT=m -CONFIG_W83877F_WDT=m -CONFIG_W83977F_WDT=m -CONFIG_MACHZ_WDT=m -# CONFIG_SBC_EPX_C3_WATCHDOG is not set -# CONFIG_INTEL_MEI_WDT is not set -# CONFIG_NI903X_WDT is not set -# CONFIG_NIC7018_WDT is not set -CONFIG_MEN_A21_WDT=m -CONFIG_XEN_WDT=m - -# -# PCI-based Watchdog Cards -# -CONFIG_PCIPCWATCHDOG=m -CONFIG_WDTPCI=m - -# -# USB-based Watchdog Cards -# -CONFIG_USBPCWATCHDOG=m - -# -# Watchdog Pretimeout Governors -# -CONFIG_WATCHDOG_PRETIMEOUT_GOV=y -# CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_NOOP is not set -CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_PANIC=y -CONFIG_WATCHDOG_PRETIMEOUT_GOV_NOOP=m -CONFIG_WATCHDOG_PRETIMEOUT_GOV_PANIC=y -CONFIG_SSB_POSSIBLE=y -CONFIG_SSB=m -CONFIG_SSB_SPROM=y -CONFIG_SSB_BLOCKIO=y -CONFIG_SSB_PCIHOST_POSSIBLE=y -CONFIG_SSB_PCIHOST=y -CONFIG_SSB_B43_PCI_BRIDGE=y -CONFIG_SSB_PCMCIAHOST_POSSIBLE=y -CONFIG_SSB_PCMCIAHOST=y -CONFIG_SSB_SDIOHOST_POSSIBLE=y -CONFIG_SSB_SDIOHOST=y -CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y -CONFIG_SSB_DRIVER_PCICORE=y -CONFIG_SSB_DRIVER_GPIO=y -CONFIG_BCMA_POSSIBLE=y -CONFIG_BCMA=m -CONFIG_BCMA_BLOCKIO=y -CONFIG_BCMA_HOST_PCI_POSSIBLE=y -CONFIG_BCMA_HOST_PCI=y -# CONFIG_BCMA_HOST_SOC is not set -CONFIG_BCMA_DRIVER_PCI=y -CONFIG_BCMA_DRIVER_GMAC_CMN=y -CONFIG_BCMA_DRIVER_GPIO=y -# CONFIG_BCMA_DEBUG is not set - -# -# Multifunction device drivers -# -CONFIG_MFD_CORE=m -CONFIG_MFD_BCM590XX=m -# CONFIG_MFD_BD9571MWV is not set -# CONFIG_MFD_AXP20X_I2C is not set -CONFIG_MFD_CROS_EC=m -# CONFIG_MFD_CROS_EC_CHARDEV is not set -# CONFIG_MFD_MADERA is not set -# CONFIG_MFD_DA9062 is not set -# CONFIG_MFD_DA9063 is not set -# CONFIG_MFD_DA9150 is not set -# CONFIG_MFD_DLN2 is not set -# CONFIG_MFD_MC13XXX_I2C is not set -# CONFIG_HTC_PASIC3 is not set -CONFIG_MFD_INTEL_QUARK_I2C_GPIO=m -CONFIG_LPC_ICH=m -CONFIG_LPC_SCH=m -# CONFIG_INTEL_SOC_PMIC_CHTDC_TI is not set -CONFIG_MFD_INTEL_LPSS=m -CONFIG_MFD_INTEL_LPSS_ACPI=m -CONFIG_MFD_INTEL_LPSS_PCI=m -# CONFIG_MFD_JANZ_CMODIO is not set -# CONFIG_MFD_KEMPLD is not set -# CONFIG_MFD_88PM800 is not set -# CONFIG_MFD_88PM805 is not set -CONFIG_MFD_MAX14577=m -# CONFIG_MFD_MAX77693 is not set -# CONFIG_MFD_MAX8907 is not set -CONFIG_MFD_MT6397=m -# CONFIG_MFD_MENF21BMC is not set -CONFIG_MFD_VIPERBOARD=m -CONFIG_MFD_RETU=m -# CONFIG_MFD_PCF50633 is not set -CONFIG_UCB1400_CORE=m -CONFIG_MFD_RDC321X=m -# CONFIG_MFD_RT5033 is not set -CONFIG_MFD_SI476X_CORE=m -CONFIG_MFD_SM501=m -CONFIG_MFD_SM501_GPIO=y -CONFIG_MFD_SKY81452=m -# CONFIG_ABX500_CORE is not set -CONFIG_MFD_SYSCON=y -CONFIG_MFD_TI_AM335X_TSCADC=m -CONFIG_MFD_LP3943=m -# CONFIG_MFD_TI_LMU is not set -# CONFIG_TPS6105X is not set -CONFIG_TPS65010=m -# CONFIG_TPS6507X is not set -# CONFIG_MFD_TPS65086 is not set -CONFIG_MFD_TI_LP873X=m -# CONFIG_MFD_TPS65912_I2C is not set -CONFIG_MFD_WL1273_CORE=m -# CONFIG_MFD_LM3533 is not set -CONFIG_MFD_VX855=m -# CONFIG_MFD_ARIZONA_I2C is not set -# CONFIG_MFD_WM8994 is not set -# CONFIG_REGULATOR is not set -CONFIG_RC_CORE=m -CONFIG_RC_MAP=m -# CONFIG_LIRC is not set -CONFIG_RC_DECODERS=y -CONFIG_IR_NEC_DECODER=m -CONFIG_IR_RC5_DECODER=m -CONFIG_IR_RC6_DECODER=m -CONFIG_IR_JVC_DECODER=m -CONFIG_IR_SONY_DECODER=m -CONFIG_IR_SANYO_DECODER=m -CONFIG_IR_SHARP_DECODER=m -CONFIG_IR_MCE_KBD_DECODER=m -CONFIG_IR_XMP_DECODER=m -# CONFIG_IR_IMON_DECODER is not set -CONFIG_RC_DEVICES=y -CONFIG_RC_ATI_REMOTE=m -CONFIG_IR_ENE=m -CONFIG_IR_IMON=m -# CONFIG_IR_IMON_RAW is not set -CONFIG_IR_MCEUSB=m -CONFIG_IR_ITE_CIR=m -CONFIG_IR_FINTEK=m -CONFIG_IR_NUVOTON=m -CONFIG_IR_REDRAT3=m -CONFIG_IR_STREAMZAP=m -CONFIG_IR_WINBOND_CIR=m -# CONFIG_IR_IGORPLUGUSB is not set -CONFIG_IR_IGUANA=m -CONFIG_IR_TTUSBIR=m -CONFIG_RC_LOOPBACK=m -# CONFIG_IR_SERIAL is not set -# CONFIG_IR_SIR is not set -CONFIG_MEDIA_SUPPORT=m - -# -# Multimedia core support -# -CONFIG_MEDIA_CAMERA_SUPPORT=y -CONFIG_MEDIA_ANALOG_TV_SUPPORT=y -CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y -CONFIG_MEDIA_RADIO_SUPPORT=y -CONFIG_MEDIA_SDR_SUPPORT=y -# CONFIG_MEDIA_CEC_SUPPORT is not set -CONFIG_MEDIA_CONTROLLER=y -# CONFIG_MEDIA_CONTROLLER_DVB is not set -CONFIG_VIDEO_DEV=m -CONFIG_VIDEO_V4L2_SUBDEV_API=y -CONFIG_VIDEO_V4L2=m -# CONFIG_VIDEO_ADV_DEBUG is not set -# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set -CONFIG_VIDEO_PCI_SKELETON=m -CONFIG_VIDEO_TUNER=m -CONFIG_V4L2_MEM2MEM_DEV=m -# CONFIG_V4L2_FLASH_LED_CLASS is not set -CONFIG_V4L2_FWNODE=m -CONFIG_VIDEOBUF_GEN=m -CONFIG_VIDEOBUF_DMA_SG=m -CONFIG_VIDEOBUF_VMALLOC=m -CONFIG_DVB_CORE=m -# CONFIG_DVB_MMAP is not set -CONFIG_DVB_NET=y -CONFIG_TTPCI_EEPROM=m -CONFIG_DVB_MAX_ADAPTERS=8 -CONFIG_DVB_DYNAMIC_MINORS=y -# CONFIG_DVB_DEMUX_SECTION_LOSS_LOG is not set -# CONFIG_DVB_ULE_DEBUG is not set - -# -# Media drivers -# -CONFIG_MEDIA_USB_SUPPORT=y - -# -# Webcam devices -# -CONFIG_USB_VIDEO_CLASS=m -CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y -CONFIG_USB_GSPCA=m -CONFIG_USB_M5602=m -CONFIG_USB_STV06XX=m -CONFIG_USB_GL860=m -CONFIG_USB_GSPCA_BENQ=m -CONFIG_USB_GSPCA_CONEX=m -CONFIG_USB_GSPCA_CPIA1=m -CONFIG_USB_GSPCA_DTCS033=m -CONFIG_USB_GSPCA_ETOMS=m -CONFIG_USB_GSPCA_FINEPIX=m -CONFIG_USB_GSPCA_JEILINJ=m -CONFIG_USB_GSPCA_JL2005BCD=m -CONFIG_USB_GSPCA_KINECT=m -CONFIG_USB_GSPCA_KONICA=m -CONFIG_USB_GSPCA_MARS=m -CONFIG_USB_GSPCA_MR97310A=m -CONFIG_USB_GSPCA_NW80X=m -CONFIG_USB_GSPCA_OV519=m -CONFIG_USB_GSPCA_OV534=m -CONFIG_USB_GSPCA_OV534_9=m -CONFIG_USB_GSPCA_PAC207=m -CONFIG_USB_GSPCA_PAC7302=m -CONFIG_USB_GSPCA_PAC7311=m -CONFIG_USB_GSPCA_SE401=m -CONFIG_USB_GSPCA_SN9C2028=m -CONFIG_USB_GSPCA_SN9C20X=m -CONFIG_USB_GSPCA_SONIXB=m -CONFIG_USB_GSPCA_SONIXJ=m -CONFIG_USB_GSPCA_SPCA500=m -CONFIG_USB_GSPCA_SPCA501=m -CONFIG_USB_GSPCA_SPCA505=m -CONFIG_USB_GSPCA_SPCA506=m -CONFIG_USB_GSPCA_SPCA508=m -CONFIG_USB_GSPCA_SPCA561=m -CONFIG_USB_GSPCA_SPCA1528=m -CONFIG_USB_GSPCA_SQ905=m -CONFIG_USB_GSPCA_SQ905C=m -CONFIG_USB_GSPCA_SQ930X=m -CONFIG_USB_GSPCA_STK014=m -CONFIG_USB_GSPCA_STK1135=m -CONFIG_USB_GSPCA_STV0680=m -CONFIG_USB_GSPCA_SUNPLUS=m -CONFIG_USB_GSPCA_T613=m -CONFIG_USB_GSPCA_TOPRO=m -CONFIG_USB_GSPCA_TOUPTEK=m -CONFIG_USB_GSPCA_TV8532=m -CONFIG_USB_GSPCA_VC032X=m -CONFIG_USB_GSPCA_VICAM=m -CONFIG_USB_GSPCA_XIRLINK_CIT=m -CONFIG_USB_GSPCA_ZC3XX=m -CONFIG_USB_PWC=m -# CONFIG_USB_PWC_DEBUG is not set -CONFIG_USB_PWC_INPUT_EVDEV=y -CONFIG_VIDEO_CPIA2=m -CONFIG_USB_ZR364XX=m -CONFIG_USB_STKWEBCAM=m -CONFIG_USB_S2255=m -CONFIG_VIDEO_USBTV=m - -# -# Analog TV USB devices -# -CONFIG_VIDEO_PVRUSB2=m -CONFIG_VIDEO_PVRUSB2_SYSFS=y -CONFIG_VIDEO_PVRUSB2_DVB=y -# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set -CONFIG_VIDEO_HDPVR=m -CONFIG_VIDEO_USBVISION=m -CONFIG_VIDEO_STK1160_COMMON=m -CONFIG_VIDEO_STK1160=m -# CONFIG_VIDEO_GO7007 is not set - -# -# Analog/digital TV USB devices -# -CONFIG_VIDEO_AU0828=m -CONFIG_VIDEO_AU0828_V4L2=y -CONFIG_VIDEO_AU0828_RC=y -CONFIG_VIDEO_CX231XX=m -CONFIG_VIDEO_CX231XX_RC=y -CONFIG_VIDEO_CX231XX_ALSA=m -CONFIG_VIDEO_CX231XX_DVB=m -CONFIG_VIDEO_TM6000=m -CONFIG_VIDEO_TM6000_ALSA=m -CONFIG_VIDEO_TM6000_DVB=m - -# -# Digital TV USB devices -# -CONFIG_DVB_USB=m -# CONFIG_DVB_USB_DEBUG is not set -CONFIG_DVB_USB_DIB3000MC=m -CONFIG_DVB_USB_A800=m -CONFIG_DVB_USB_DIBUSB_MB=m -# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set -CONFIG_DVB_USB_DIBUSB_MC=m -CONFIG_DVB_USB_DIB0700=m -CONFIG_DVB_USB_UMT_010=m -CONFIG_DVB_USB_CXUSB=m -CONFIG_DVB_USB_M920X=m -CONFIG_DVB_USB_DIGITV=m -CONFIG_DVB_USB_VP7045=m -CONFIG_DVB_USB_VP702X=m -CONFIG_DVB_USB_GP8PSK=m -CONFIG_DVB_USB_NOVA_T_USB2=m -CONFIG_DVB_USB_TTUSB2=m -CONFIG_DVB_USB_DTT200U=m -CONFIG_DVB_USB_OPERA1=m -CONFIG_DVB_USB_AF9005=m -CONFIG_DVB_USB_AF9005_REMOTE=m -CONFIG_DVB_USB_PCTV452E=m -CONFIG_DVB_USB_DW2102=m -CONFIG_DVB_USB_CINERGY_T2=m -CONFIG_DVB_USB_DTV5100=m -CONFIG_DVB_USB_AZ6027=m -CONFIG_DVB_USB_TECHNISAT_USB2=m -CONFIG_DVB_USB_V2=m -CONFIG_DVB_USB_AF9015=m -CONFIG_DVB_USB_AF9035=m -CONFIG_DVB_USB_ANYSEE=m -CONFIG_DVB_USB_AU6610=m -CONFIG_DVB_USB_AZ6007=m -CONFIG_DVB_USB_CE6230=m -CONFIG_DVB_USB_EC168=m -CONFIG_DVB_USB_GL861=m -CONFIG_DVB_USB_LME2510=m -CONFIG_DVB_USB_MXL111SF=m -CONFIG_DVB_USB_RTL28XXU=m -# CONFIG_DVB_USB_DVBSKY is not set -# CONFIG_DVB_USB_ZD1301 is not set -CONFIG_DVB_TTUSB_BUDGET=m -CONFIG_DVB_TTUSB_DEC=m -CONFIG_SMS_USB_DRV=m -CONFIG_DVB_B2C2_FLEXCOP_USB=m -# CONFIG_DVB_B2C2_FLEXCOP_USB_DEBUG is not set -# CONFIG_DVB_AS102 is not set - -# -# Webcam, TV (analog/digital) USB devices -# -CONFIG_VIDEO_EM28XX=m -CONFIG_VIDEO_EM28XX_V4L2=m -CONFIG_VIDEO_EM28XX_ALSA=m -CONFIG_VIDEO_EM28XX_DVB=m -CONFIG_VIDEO_EM28XX_RC=m - -# -# Software defined radio USB devices -# -CONFIG_USB_AIRSPY=m -# CONFIG_USB_HACKRF is not set -CONFIG_MEDIA_PCI_SUPPORT=y - -# -# Media capture support -# -CONFIG_VIDEO_MEYE=m -CONFIG_VIDEO_SOLO6X10=m -CONFIG_VIDEO_TW5864=m -# CONFIG_VIDEO_TW68 is not set -# CONFIG_VIDEO_TW686X is not set - -# -# Media capture/analog TV support -# -CONFIG_VIDEO_IVTV=m -# CONFIG_VIDEO_IVTV_DEPRECATED_IOCTLS is not set -CONFIG_VIDEO_IVTV_ALSA=m -CONFIG_VIDEO_FB_IVTV=m -CONFIG_VIDEO_HEXIUM_GEMINI=m -CONFIG_VIDEO_HEXIUM_ORION=m -CONFIG_VIDEO_MXB=m -# CONFIG_VIDEO_DT3155 is not set - -# -# Media capture/analog/hybrid TV support -# -CONFIG_VIDEO_CX18=m -CONFIG_VIDEO_CX18_ALSA=m -CONFIG_VIDEO_CX23885=m -CONFIG_MEDIA_ALTERA_CI=m -# CONFIG_VIDEO_CX25821 is not set -CONFIG_VIDEO_CX88=m -CONFIG_VIDEO_CX88_ALSA=m -CONFIG_VIDEO_CX88_BLACKBIRD=m -CONFIG_VIDEO_CX88_DVB=m -CONFIG_VIDEO_CX88_ENABLE_VP3054=y -CONFIG_VIDEO_CX88_VP3054=m -CONFIG_VIDEO_CX88_MPEG=m -CONFIG_VIDEO_BT848=m -CONFIG_DVB_BT8XX=m -CONFIG_VIDEO_SAA7134=m -CONFIG_VIDEO_SAA7134_ALSA=m -CONFIG_VIDEO_SAA7134_RC=y -CONFIG_VIDEO_SAA7134_DVB=m -CONFIG_VIDEO_SAA7164=m - -# -# Media digital TV PCI Adapters -# -CONFIG_DVB_AV7110_IR=y -CONFIG_DVB_AV7110=m -CONFIG_DVB_AV7110_OSD=y -CONFIG_DVB_BUDGET_CORE=m -CONFIG_DVB_BUDGET=m -CONFIG_DVB_BUDGET_CI=m -CONFIG_DVB_BUDGET_AV=m -CONFIG_DVB_BUDGET_PATCH=m -CONFIG_DVB_B2C2_FLEXCOP_PCI=m -# CONFIG_DVB_B2C2_FLEXCOP_PCI_DEBUG is not set -CONFIG_DVB_PLUTO2=m -CONFIG_DVB_DM1105=m -CONFIG_DVB_PT1=m -# CONFIG_DVB_PT3 is not set -CONFIG_MANTIS_CORE=m -CONFIG_DVB_MANTIS=m -CONFIG_DVB_HOPPER=m -CONFIG_DVB_NGENE=m -CONFIG_DVB_DDBRIDGE=m -# CONFIG_DVB_DDBRIDGE_MSIENABLE is not set -# CONFIG_DVB_SMIPCIE is not set -# CONFIG_VIDEO_IPU3_CIO2 is not set -# CONFIG_V4L_PLATFORM_DRIVERS is not set -CONFIG_V4L_MEM2MEM_DRIVERS=y -CONFIG_VIDEO_MEM2MEM_DEINTERLACE=m -CONFIG_VIDEO_SH_VEU=m -CONFIG_V4L_TEST_DRIVERS=y -# CONFIG_VIDEO_VIMC is not set -# CONFIG_VIDEO_VIVID is not set -# CONFIG_VIDEO_VIM2M is not set -# CONFIG_VIDEO_VICODEC is not set -CONFIG_DVB_PLATFORM_DRIVERS=y -# CONFIG_SDR_PLATFORM_DRIVERS is not set - -# -# Supported MMC/SDIO adapters -# -CONFIG_SMS_SDIO_DRV=m -CONFIG_RADIO_ADAPTERS=y -CONFIG_RADIO_TEA575X=m -CONFIG_RADIO_SI470X=m -CONFIG_USB_SI470X=m -CONFIG_I2C_SI470X=m -CONFIG_RADIO_SI4713=m -CONFIG_USB_SI4713=m -CONFIG_PLATFORM_SI4713=m -CONFIG_I2C_SI4713=m -CONFIG_USB_MR800=m -CONFIG_USB_DSBR=m -CONFIG_RADIO_MAXIRADIO=m -CONFIG_RADIO_SHARK=m -CONFIG_RADIO_SHARK2=m -CONFIG_USB_KEENE=m -CONFIG_USB_RAREMONO=m -CONFIG_USB_MA901=m -CONFIG_RADIO_TEA5764=m -CONFIG_RADIO_SAA7706H=m -# CONFIG_RADIO_TEF6862 is not set -CONFIG_RADIO_WL1273=m - -# -# Texas Instruments WL128x FM driver (ST based) -# -CONFIG_RADIO_WL128X=m - -# -# Supported FireWire (IEEE 1394) Adapters -# -CONFIG_DVB_FIREDTV=m -CONFIG_DVB_FIREDTV_INPUT=y -CONFIG_MEDIA_COMMON_OPTIONS=y - -# -# common driver options -# -CONFIG_VIDEO_CX2341X=m -CONFIG_VIDEO_TVEEPROM=m -CONFIG_CYPRESS_FIRMWARE=m -CONFIG_VIDEOBUF2_CORE=m -CONFIG_VIDEOBUF2_V4L2=m -CONFIG_VIDEOBUF2_MEMOPS=m -CONFIG_VIDEOBUF2_DMA_CONTIG=m -CONFIG_VIDEOBUF2_VMALLOC=m -CONFIG_VIDEOBUF2_DMA_SG=m -CONFIG_VIDEOBUF2_DVB=m -CONFIG_DVB_B2C2_FLEXCOP=m -CONFIG_VIDEO_SAA7146=m -CONFIG_VIDEO_SAA7146_VV=m -CONFIG_SMS_SIANO_MDTV=m -CONFIG_SMS_SIANO_RC=y -# CONFIG_SMS_SIANO_DEBUGFS is not set - -# -# Media ancillary drivers (tuners, sensors, i2c, spi, frontends) -# -CONFIG_MEDIA_SUBDRV_AUTOSELECT=y -CONFIG_MEDIA_ATTACH=y -CONFIG_VIDEO_IR_I2C=m - -# -# Audio decoders, processors and mixers -# -CONFIG_VIDEO_TVAUDIO=m -CONFIG_VIDEO_TDA7432=m -CONFIG_VIDEO_TDA9840=m -CONFIG_VIDEO_TEA6415C=m -CONFIG_VIDEO_TEA6420=m -CONFIG_VIDEO_MSP3400=m -CONFIG_VIDEO_CS3308=m -CONFIG_VIDEO_CS5345=m -CONFIG_VIDEO_CS53L32A=m -CONFIG_VIDEO_WM8775=m -CONFIG_VIDEO_WM8739=m -CONFIG_VIDEO_VP27SMPX=m - -# -# RDS decoders -# -CONFIG_VIDEO_SAA6588=m - -# -# Video decoders -# -CONFIG_VIDEO_BT819=m -CONFIG_VIDEO_BT856=m -CONFIG_VIDEO_BT866=m -CONFIG_VIDEO_KS0127=m -CONFIG_VIDEO_SAA7110=m -CONFIG_VIDEO_SAA711X=m -CONFIG_VIDEO_TVP5150=m -CONFIG_VIDEO_VPX3220=m - -# -# Video and audio decoders -# -CONFIG_VIDEO_SAA717X=m -CONFIG_VIDEO_CX25840=m - -# -# Video encoders -# -CONFIG_VIDEO_SAA7127=m -CONFIG_VIDEO_SAA7185=m -CONFIG_VIDEO_ADV7170=m -CONFIG_VIDEO_ADV7175=m - -# -# Camera sensor devices -# -CONFIG_VIDEO_OV2640=m -CONFIG_VIDEO_MT9V011=m - -# -# Flash devices -# - -# -# Video improvement chips -# -CONFIG_VIDEO_UPD64031A=m -CONFIG_VIDEO_UPD64083=m - -# -# Audio/Video compression chips -# -CONFIG_VIDEO_SAA6752HS=m - -# -# SDR tuner chips -# - -# -# Miscellaneous helper chips -# -CONFIG_VIDEO_M52790=m - -# -# Sensors used on soc_camera driver -# -CONFIG_MEDIA_TUNER=m -CONFIG_MEDIA_TUNER_SIMPLE=m -CONFIG_MEDIA_TUNER_TDA18250=m -CONFIG_MEDIA_TUNER_TDA8290=m -CONFIG_MEDIA_TUNER_TDA827X=m -CONFIG_MEDIA_TUNER_TDA18271=m -CONFIG_MEDIA_TUNER_TDA9887=m -CONFIG_MEDIA_TUNER_TEA5761=m -CONFIG_MEDIA_TUNER_TEA5767=m -CONFIG_MEDIA_TUNER_MT20XX=m -CONFIG_MEDIA_TUNER_MT2060=m -CONFIG_MEDIA_TUNER_MT2063=m -CONFIG_MEDIA_TUNER_MT2266=m -CONFIG_MEDIA_TUNER_MT2131=m -CONFIG_MEDIA_TUNER_QT1010=m -CONFIG_MEDIA_TUNER_XC2028=m -CONFIG_MEDIA_TUNER_XC5000=m -CONFIG_MEDIA_TUNER_XC4000=m -CONFIG_MEDIA_TUNER_MXL5005S=m -CONFIG_MEDIA_TUNER_MXL5007T=m -CONFIG_MEDIA_TUNER_MC44S803=m -CONFIG_MEDIA_TUNER_MAX2165=m -CONFIG_MEDIA_TUNER_TDA18218=m -CONFIG_MEDIA_TUNER_FC0011=m -CONFIG_MEDIA_TUNER_FC0012=m -CONFIG_MEDIA_TUNER_FC0013=m -CONFIG_MEDIA_TUNER_TDA18212=m -CONFIG_MEDIA_TUNER_E4000=m -CONFIG_MEDIA_TUNER_FC2580=m -CONFIG_MEDIA_TUNER_M88RS6000T=m -CONFIG_MEDIA_TUNER_TUA9001=m -CONFIG_MEDIA_TUNER_SI2157=m -CONFIG_MEDIA_TUNER_IT913X=m -CONFIG_MEDIA_TUNER_R820T=m -CONFIG_MEDIA_TUNER_QM1D1C0042=m -CONFIG_MEDIA_TUNER_QM1D1B0004=m - -# -# Multistandard (satellite) frontends -# -CONFIG_DVB_STB0899=m -CONFIG_DVB_STB6100=m -CONFIG_DVB_STV090x=m -CONFIG_DVB_STV0910=m -CONFIG_DVB_STV6110x=m -CONFIG_DVB_STV6111=m -CONFIG_DVB_MXL5XX=m -CONFIG_DVB_M88DS3103=m - -# -# Multistandard (cable + terrestrial) frontends -# -CONFIG_DVB_DRXK=m -CONFIG_DVB_TDA18271C2DD=m -CONFIG_DVB_SI2165=m -CONFIG_DVB_MN88472=m -CONFIG_DVB_MN88473=m - -# -# DVB-S (satellite) frontends -# -CONFIG_DVB_CX24110=m -CONFIG_DVB_CX24123=m -CONFIG_DVB_MT312=m -CONFIG_DVB_ZL10036=m -CONFIG_DVB_ZL10039=m -CONFIG_DVB_S5H1420=m -CONFIG_DVB_STV0288=m -CONFIG_DVB_STB6000=m -CONFIG_DVB_STV0299=m -CONFIG_DVB_STV6110=m -CONFIG_DVB_STV0900=m -CONFIG_DVB_TDA8083=m -CONFIG_DVB_TDA10086=m -CONFIG_DVB_TDA8261=m -CONFIG_DVB_VES1X93=m -CONFIG_DVB_TUNER_ITD1000=m -CONFIG_DVB_TUNER_CX24113=m -CONFIG_DVB_TDA826X=m -CONFIG_DVB_TUA6100=m -CONFIG_DVB_CX24116=m -CONFIG_DVB_CX24117=m -CONFIG_DVB_CX24120=m -CONFIG_DVB_SI21XX=m -CONFIG_DVB_TS2020=m -CONFIG_DVB_DS3000=m -CONFIG_DVB_MB86A16=m -CONFIG_DVB_TDA10071=m - -# -# DVB-T (terrestrial) frontends -# -CONFIG_DVB_SP8870=m -CONFIG_DVB_SP887X=m -CONFIG_DVB_CX22700=m -CONFIG_DVB_CX22702=m -CONFIG_DVB_DRXD=m -CONFIG_DVB_L64781=m -CONFIG_DVB_TDA1004X=m -CONFIG_DVB_NXT6000=m -CONFIG_DVB_MT352=m -CONFIG_DVB_ZL10353=m -CONFIG_DVB_DIB3000MB=m -CONFIG_DVB_DIB3000MC=m -CONFIG_DVB_DIB7000M=m -CONFIG_DVB_DIB7000P=m -CONFIG_DVB_TDA10048=m -CONFIG_DVB_AF9013=m -CONFIG_DVB_EC100=m -CONFIG_DVB_STV0367=m -CONFIG_DVB_CXD2820R=m -CONFIG_DVB_CXD2841ER=m -CONFIG_DVB_RTL2830=m -CONFIG_DVB_RTL2832=m -CONFIG_DVB_RTL2832_SDR=m -CONFIG_DVB_SI2168=m -CONFIG_DVB_GP8PSK_FE=m - -# -# DVB-C (cable) frontends -# -CONFIG_DVB_VES1820=m -CONFIG_DVB_TDA10021=m -CONFIG_DVB_TDA10023=m -CONFIG_DVB_STV0297=m - -# -# ATSC (North American/Korean Terrestrial/Cable DTV) frontends -# -CONFIG_DVB_NXT200X=m -CONFIG_DVB_OR51211=m -CONFIG_DVB_OR51132=m -CONFIG_DVB_BCM3510=m -CONFIG_DVB_LGDT330X=m -CONFIG_DVB_LGDT3305=m -CONFIG_DVB_LGDT3306A=m -CONFIG_DVB_LG2160=m -CONFIG_DVB_S5H1409=m -CONFIG_DVB_AU8522=m -CONFIG_DVB_AU8522_DTV=m -CONFIG_DVB_AU8522_V4L=m -CONFIG_DVB_S5H1411=m - -# -# ISDB-T (terrestrial) frontends -# -CONFIG_DVB_S921=m -CONFIG_DVB_DIB8000=m -CONFIG_DVB_MB86A20S=m - -# -# ISDB-S (satellite) & ISDB-T (terrestrial) frontends -# -CONFIG_DVB_TC90522=m - -# -# Digital terrestrial only tuners/PLL -# -CONFIG_DVB_PLL=m -CONFIG_DVB_TUNER_DIB0070=m -CONFIG_DVB_TUNER_DIB0090=m - -# -# SEC control devices for DVB-S -# -CONFIG_DVB_DRX39XYJ=m -CONFIG_DVB_LNBH25=m -CONFIG_DVB_LNBP21=m -CONFIG_DVB_LNBP22=m -CONFIG_DVB_ISL6405=m -CONFIG_DVB_ISL6421=m -CONFIG_DVB_ISL6423=m -CONFIG_DVB_A8293=m -CONFIG_DVB_LGS8GXX=m -CONFIG_DVB_ATBM8830=m -CONFIG_DVB_TDA665x=m -CONFIG_DVB_IX2505V=m -CONFIG_DVB_M88RS2000=m -CONFIG_DVB_AF9033=m - -# -# Common Interface (EN50221) controller drivers -# -CONFIG_DVB_CXD2099=m - -# -# Tools to develop new frontends -# -CONFIG_DVB_DUMMY_FE=m - -# -# Graphics support -# -CONFIG_AGP=y -CONFIG_AGP_AMD64=y -CONFIG_AGP_INTEL=y -CONFIG_AGP_SIS=y -CONFIG_AGP_VIA=y -CONFIG_INTEL_GTT=y -CONFIG_VGA_ARB=y -CONFIG_VGA_ARB_MAX_GPUS=16 -CONFIG_VGA_SWITCHEROO=y -CONFIG_DRM=m -CONFIG_DRM_MIPI_DSI=y -# CONFIG_DRM_DP_AUX_CHARDEV is not set -CONFIG_DRM_KMS_HELPER=m -CONFIG_DRM_KMS_FB_HELPER=y -CONFIG_DRM_FBDEV_EMULATION=y -CONFIG_DRM_FBDEV_OVERALLOC=100 -CONFIG_DRM_LOAD_EDID_FIRMWARE=y -# CONFIG_DRM_DP_CEC is not set -CONFIG_DRM_TTM=m -CONFIG_DRM_VM=y - -# -# I2C encoder or helper chips -# -CONFIG_DRM_I2C_CH7006=m -CONFIG_DRM_I2C_SIL164=m -CONFIG_DRM_I2C_NXP_TDA998X=m -# CONFIG_DRM_I2C_NXP_TDA9950 is not set -CONFIG_DRM_RADEON=m -CONFIG_DRM_RADEON_USERPTR=y -# CONFIG_DRM_AMDGPU is not set - -# -# ACP (Audio CoProcessor) Configuration -# - -# -# AMD Library routines -# -CONFIG_DRM_NOUVEAU=m -CONFIG_NOUVEAU_LEGACY_CTX_SUPPORT=y -CONFIG_NOUVEAU_DEBUG=5 -CONFIG_NOUVEAU_DEBUG_DEFAULT=3 -# CONFIG_NOUVEAU_DEBUG_MMU is not set -CONFIG_DRM_NOUVEAU_BACKLIGHT=y -CONFIG_DRM_I915=m -# CONFIG_DRM_I915_ALPHA_SUPPORT is not set -CONFIG_DRM_I915_CAPTURE_ERROR=y -CONFIG_DRM_I915_COMPRESS_ERROR=y -CONFIG_DRM_I915_USERPTR=y -CONFIG_DRM_I915_GVT=y -CONFIG_DRM_VGEM=m -# CONFIG_DRM_VKMS is not set -CONFIG_DRM_VMWGFX=m -CONFIG_DRM_VMWGFX_FBCON=y -CONFIG_DRM_GMA500=m -CONFIG_DRM_GMA600=y -CONFIG_DRM_GMA3600=y -CONFIG_DRM_UDL=m -CONFIG_DRM_AST=m -CONFIG_DRM_MGAG200=m -CONFIG_DRM_CIRRUS_QEMU=m -CONFIG_DRM_QXL=m -CONFIG_DRM_BOCHS=m -# CONFIG_DRM_VIRTIO_GPU is not set -CONFIG_DRM_PANEL=y - -# -# Display Panels -# -# CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN is not set -CONFIG_DRM_BRIDGE=y -CONFIG_DRM_PANEL_BRIDGE=y - -# -# Display Interface Bridges -# -# CONFIG_DRM_ANALOGIX_ANX78XX is not set -# CONFIG_DRM_HISI_HIBMC is not set -# CONFIG_DRM_TINYDRM is not set -# CONFIG_DRM_XEN is not set -# CONFIG_DRM_LEGACY is not set -CONFIG_DRM_PANEL_ORIENTATION_QUIRKS=y - -# -# Frame buffer Devices -# -CONFIG_FB=y -# CONFIG_FIRMWARE_EDID is not set -CONFIG_FB_CMDLINE=y -CONFIG_FB_NOTIFY=y -CONFIG_FB_BOOT_VESA_SUPPORT=y -CONFIG_FB_CFB_FILLRECT=y -CONFIG_FB_CFB_COPYAREA=y -CONFIG_FB_CFB_IMAGEBLIT=y -CONFIG_FB_SYS_FILLRECT=y -CONFIG_FB_SYS_COPYAREA=y -CONFIG_FB_SYS_IMAGEBLIT=y -CONFIG_FB_FOREIGN_ENDIAN=y -CONFIG_FB_BOTH_ENDIAN=y -# CONFIG_FB_BIG_ENDIAN is not set -# CONFIG_FB_LITTLE_ENDIAN is not set -CONFIG_FB_SYS_FOPS=y -CONFIG_FB_DEFERRED_IO=y -CONFIG_FB_BACKLIGHT=y -CONFIG_FB_MODE_HELPERS=y -CONFIG_FB_TILEBLITTING=y - -# -# Frame buffer hardware drivers -# -# CONFIG_FB_CIRRUS is not set -# CONFIG_FB_PM2 is not set -# CONFIG_FB_CYBER2000 is not set -# CONFIG_FB_ARC is not set -# CONFIG_FB_ASILIANT is not set -# CONFIG_FB_IMSTT is not set -CONFIG_FB_VGA16=m -CONFIG_FB_UVESA=m -CONFIG_FB_VESA=y -CONFIG_FB_EFI=y -# CONFIG_FB_N411 is not set -# CONFIG_FB_HGA is not set -CONFIG_FB_OPENCORES=m -# CONFIG_FB_S1D13XXX is not set -# CONFIG_FB_NVIDIA is not set -# CONFIG_FB_RIVA is not set -# CONFIG_FB_I740 is not set -# CONFIG_FB_LE80578 is not set -# CONFIG_FB_MATROX is not set -# CONFIG_FB_RADEON is not set -# CONFIG_FB_ATY128 is not set -# CONFIG_FB_ATY is not set -# CONFIG_FB_S3 is not set -# CONFIG_FB_SAVAGE is not set -# CONFIG_FB_SIS is not set -# CONFIG_FB_VIA is not set -# CONFIG_FB_NEOMAGIC is not set -# CONFIG_FB_KYRO is not set -# CONFIG_FB_3DFX is not set -CONFIG_FB_VOODOO1=m -# CONFIG_FB_VT8623 is not set -# CONFIG_FB_TRIDENT is not set -# CONFIG_FB_ARK is not set -# CONFIG_FB_PM3 is not set -# CONFIG_FB_CARMINE is not set -# CONFIG_FB_SM501 is not set -# CONFIG_FB_SMSCUFX is not set -# CONFIG_FB_UDL is not set -CONFIG_FB_IBM_GXT4500=m -CONFIG_FB_VIRTUAL=m -CONFIG_XEN_FBDEV_FRONTEND=y -# CONFIG_FB_METRONOME is not set -# CONFIG_FB_MB862XX is not set -# CONFIG_FB_BROADSHEET is not set -CONFIG_FB_HYPERV=m -# CONFIG_FB_SIMPLE is not set -CONFIG_FB_SM712=m -CONFIG_BACKLIGHT_LCD_SUPPORT=y -CONFIG_LCD_CLASS_DEVICE=m -CONFIG_LCD_PLATFORM=m -CONFIG_BACKLIGHT_CLASS_DEVICE=y -# CONFIG_BACKLIGHT_GENERIC is not set -CONFIG_BACKLIGHT_PWM=m -CONFIG_BACKLIGHT_APPLE=m -CONFIG_BACKLIGHT_PM8941_WLED=m -# CONFIG_BACKLIGHT_SAHARA is not set -# CONFIG_BACKLIGHT_ADP8860 is not set -# CONFIG_BACKLIGHT_ADP8870 is not set -CONFIG_BACKLIGHT_LM3630A=m -CONFIG_BACKLIGHT_LM3639=m -CONFIG_BACKLIGHT_LP855X=m -CONFIG_BACKLIGHT_SKY81452=m -CONFIG_BACKLIGHT_GPIO=m -CONFIG_BACKLIGHT_LV5207LP=m -CONFIG_BACKLIGHT_BD6107=m -# CONFIG_BACKLIGHT_ARCXCNN is not set -CONFIG_VGASTATE=m -CONFIG_HDMI=y - -# -# Console display driver support -# -CONFIG_VGA_CONSOLE=y -CONFIG_VGACON_SOFT_SCROLLBACK=y -CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64 -# CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT is not set -CONFIG_DUMMY_CONSOLE=y -CONFIG_DUMMY_CONSOLE_COLUMNS=80 -CONFIG_DUMMY_CONSOLE_ROWS=25 -CONFIG_FRAMEBUFFER_CONSOLE=y -CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y -CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y -# CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER is not set -# CONFIG_LOGO is not set -CONFIG_SOUND=m -CONFIG_SOUND_OSS_CORE=y -CONFIG_SOUND_OSS_CORE_PRECLAIM=y -CONFIG_SND=m -CONFIG_SND_TIMER=m -CONFIG_SND_PCM=m -CONFIG_SND_HWDEP=m -CONFIG_SND_SEQ_DEVICE=m -CONFIG_SND_RAWMIDI=m -CONFIG_SND_JACK=y -CONFIG_SND_JACK_INPUT_DEV=y -CONFIG_SND_OSSEMUL=y -CONFIG_SND_MIXER_OSS=m -CONFIG_SND_PCM_OSS=m -CONFIG_SND_PCM_OSS_PLUGINS=y -CONFIG_SND_PCM_TIMER=y -CONFIG_SND_HRTIMER=m -CONFIG_SND_DYNAMIC_MINORS=y -CONFIG_SND_MAX_CARDS=32 -# CONFIG_SND_SUPPORT_OLD_API is not set -CONFIG_SND_PROC_FS=y -CONFIG_SND_VERBOSE_PROCFS=y -# CONFIG_SND_VERBOSE_PRINTK is not set -# CONFIG_SND_DEBUG is not set -CONFIG_SND_VMASTER=y -CONFIG_SND_DMA_SGBUF=y -CONFIG_SND_SEQUENCER=m -CONFIG_SND_SEQ_DUMMY=m -CONFIG_SND_SEQUENCER_OSS=m -CONFIG_SND_SEQ_HRTIMER_DEFAULT=y -CONFIG_SND_SEQ_MIDI_EVENT=m -CONFIG_SND_SEQ_MIDI=m -CONFIG_SND_SEQ_MIDI_EMUL=m -CONFIG_SND_SEQ_VIRMIDI=m -CONFIG_SND_MPU401_UART=m -CONFIG_SND_OPL3_LIB=m -CONFIG_SND_OPL3_LIB_SEQ=m -CONFIG_SND_VX_LIB=m -CONFIG_SND_AC97_CODEC=m -CONFIG_SND_DRIVERS=y -CONFIG_SND_PCSP=m -CONFIG_SND_DUMMY=m -CONFIG_SND_ALOOP=m -CONFIG_SND_VIRMIDI=m -CONFIG_SND_MTPAV=m -CONFIG_SND_MTS64=m -CONFIG_SND_SERIAL_U16550=m -CONFIG_SND_MPU401=m -CONFIG_SND_PORTMAN2X4=m -CONFIG_SND_AC97_POWER_SAVE=y -CONFIG_SND_AC97_POWER_SAVE_DEFAULT=0 -CONFIG_SND_SB_COMMON=m -CONFIG_SND_PCI=y -CONFIG_SND_AD1889=m -CONFIG_SND_ALS300=m -CONFIG_SND_ALS4000=m -CONFIG_SND_ALI5451=m -CONFIG_SND_ASIHPI=m -CONFIG_SND_ATIIXP=m -CONFIG_SND_ATIIXP_MODEM=m -CONFIG_SND_AU8810=m -CONFIG_SND_AU8820=m -CONFIG_SND_AU8830=m -# CONFIG_SND_AW2 is not set -CONFIG_SND_AZT3328=m -CONFIG_SND_BT87X=m -# CONFIG_SND_BT87X_OVERCLOCK is not set -CONFIG_SND_CA0106=m -CONFIG_SND_CMIPCI=m -CONFIG_SND_OXYGEN_LIB=m -CONFIG_SND_OXYGEN=m -CONFIG_SND_CS4281=m -CONFIG_SND_CS46XX=m -CONFIG_SND_CS46XX_NEW_DSP=y -CONFIG_SND_CTXFI=m -CONFIG_SND_DARLA20=m -CONFIG_SND_GINA20=m -CONFIG_SND_LAYLA20=m -CONFIG_SND_DARLA24=m -CONFIG_SND_GINA24=m -CONFIG_SND_LAYLA24=m -CONFIG_SND_MONA=m -CONFIG_SND_MIA=m -CONFIG_SND_ECHO3G=m -CONFIG_SND_INDIGO=m -CONFIG_SND_INDIGOIO=m -CONFIG_SND_INDIGODJ=m -CONFIG_SND_INDIGOIOX=m -CONFIG_SND_INDIGODJX=m -CONFIG_SND_EMU10K1=m -CONFIG_SND_EMU10K1_SEQ=m -CONFIG_SND_EMU10K1X=m -CONFIG_SND_ENS1370=m -CONFIG_SND_ENS1371=m -CONFIG_SND_ES1938=m -CONFIG_SND_ES1968=m -CONFIG_SND_ES1968_INPUT=y -CONFIG_SND_ES1968_RADIO=y -CONFIG_SND_FM801=m -CONFIG_SND_FM801_TEA575X_BOOL=y -CONFIG_SND_HDSP=m -CONFIG_SND_HDSPM=m -CONFIG_SND_ICE1712=m -CONFIG_SND_ICE1724=m -CONFIG_SND_INTEL8X0=m -CONFIG_SND_INTEL8X0M=m -CONFIG_SND_KORG1212=m -CONFIG_SND_LOLA=m -CONFIG_SND_LX6464ES=m -CONFIG_SND_MAESTRO3=m -CONFIG_SND_MAESTRO3_INPUT=y -CONFIG_SND_MIXART=m -CONFIG_SND_NM256=m -CONFIG_SND_PCXHR=m -CONFIG_SND_RIPTIDE=m -CONFIG_SND_RME32=m -CONFIG_SND_RME96=m -CONFIG_SND_RME9652=m -CONFIG_SND_SONICVIBES=m -CONFIG_SND_TRIDENT=m -CONFIG_SND_VIA82XX=m -CONFIG_SND_VIA82XX_MODEM=m -CONFIG_SND_VIRTUOSO=m -CONFIG_SND_VX222=m -CONFIG_SND_YMFPCI=m - -# -# HD-Audio -# -CONFIG_SND_HDA=m -CONFIG_SND_HDA_INTEL=m -CONFIG_SND_HDA_HWDEP=y -CONFIG_SND_HDA_RECONFIG=y -CONFIG_SND_HDA_INPUT_BEEP=y -CONFIG_SND_HDA_INPUT_BEEP_MODE=0 -CONFIG_SND_HDA_PATCH_LOADER=y -CONFIG_SND_HDA_CODEC_REALTEK=m -CONFIG_SND_HDA_CODEC_ANALOG=m -CONFIG_SND_HDA_CODEC_SIGMATEL=m -CONFIG_SND_HDA_CODEC_VIA=m -CONFIG_SND_HDA_CODEC_HDMI=m -CONFIG_SND_HDA_CODEC_CIRRUS=m -CONFIG_SND_HDA_CODEC_CONEXANT=m -CONFIG_SND_HDA_CODEC_CA0110=m -CONFIG_SND_HDA_CODEC_CA0132=m -CONFIG_SND_HDA_CODEC_CA0132_DSP=y -CONFIG_SND_HDA_CODEC_CMEDIA=m -CONFIG_SND_HDA_CODEC_SI3054=m -CONFIG_SND_HDA_GENERIC=m -CONFIG_SND_HDA_POWER_SAVE_DEFAULT=0 -CONFIG_SND_HDA_CORE=m -CONFIG_SND_HDA_DSP_LOADER=y -CONFIG_SND_HDA_COMPONENT=y -CONFIG_SND_HDA_I915=y -CONFIG_SND_HDA_PREALLOC_SIZE=4096 -CONFIG_SND_USB=y -CONFIG_SND_USB_AUDIO=m -CONFIG_SND_USB_UA101=m -CONFIG_SND_USB_USX2Y=m -CONFIG_SND_USB_CAIAQ=m -CONFIG_SND_USB_CAIAQ_INPUT=y -CONFIG_SND_USB_US122L=m -CONFIG_SND_USB_6FIRE=m -# CONFIG_SND_USB_HIFACE is not set -CONFIG_SND_BCD2000=m -CONFIG_SND_USB_LINE6=m -CONFIG_SND_USB_POD=m -CONFIG_SND_USB_PODHD=m -CONFIG_SND_USB_TONEPORT=m -CONFIG_SND_USB_VARIAX=m -CONFIG_SND_FIREWIRE=y -CONFIG_SND_FIREWIRE_LIB=m -CONFIG_SND_DICE=m -# CONFIG_SND_OXFW is not set -CONFIG_SND_ISIGHT=m -CONFIG_SND_FIREWORKS=m -CONFIG_SND_BEBOB=m -CONFIG_SND_FIREWIRE_DIGI00X=m -CONFIG_SND_FIREWIRE_TASCAM=m -# CONFIG_SND_FIREWIRE_MOTU is not set -# CONFIG_SND_FIREFACE is not set -# CONFIG_SND_PCMCIA is not set -# CONFIG_SND_SOC is not set -CONFIG_SND_X86=y -# CONFIG_HDMI_LPE_AUDIO is not set -CONFIG_SND_SYNTH_EMUX=m -# CONFIG_SND_XEN_FRONTEND is not set -CONFIG_AC97_BUS=m - -# -# HID support -# -CONFIG_HID=y -CONFIG_HID_BATTERY_STRENGTH=y -CONFIG_HIDRAW=y -CONFIG_UHID=y -CONFIG_HID_GENERIC=y - -# -# Special HID drivers -# -CONFIG_HID_A4TECH=y -# CONFIG_HID_ACCUTOUCH is not set -CONFIG_HID_ACRUX=m -CONFIG_HID_ACRUX_FF=y -CONFIG_HID_APPLE=y -CONFIG_HID_APPLEIR=m -# CONFIG_HID_ASUS is not set -CONFIG_HID_AUREAL=m -CONFIG_HID_BELKIN=y -CONFIG_HID_BETOP_FF=m -CONFIG_HID_CHERRY=y -CONFIG_HID_CHICONY=y -CONFIG_HID_CORSAIR=m -# CONFIG_HID_COUGAR is not set -CONFIG_HID_PRODIKEYS=m -# CONFIG_HID_CMEDIA is not set -CONFIG_HID_CP2112=m -CONFIG_HID_CYPRESS=y -CONFIG_HID_DRAGONRISE=m -CONFIG_DRAGONRISE_FF=y -CONFIG_HID_EMS_FF=m -# CONFIG_HID_ELAN is not set -CONFIG_HID_ELECOM=m -CONFIG_HID_ELO=m -CONFIG_HID_EZKEY=y -CONFIG_HID_GEMBIRD=m -CONFIG_HID_GFRM=m -CONFIG_HID_HOLTEK=m -CONFIG_HOLTEK_FF=y -# CONFIG_HID_GOOGLE_HAMMER is not set -CONFIG_HID_GT683R=m -CONFIG_HID_KEYTOUCH=m -CONFIG_HID_KYE=m -CONFIG_HID_UCLOGIC=m -CONFIG_HID_WALTOP=m -CONFIG_HID_GYRATION=m -CONFIG_HID_ICADE=m -CONFIG_HID_ITE=y -# CONFIG_HID_JABRA is not set -CONFIG_HID_TWINHAN=m -CONFIG_HID_KENSINGTON=y -CONFIG_HID_LCPOWER=m -CONFIG_HID_LED=m -CONFIG_HID_LENOVO=m -CONFIG_HID_LOGITECH=y -CONFIG_HID_LOGITECH_DJ=m -CONFIG_HID_LOGITECH_HIDPP=m -CONFIG_LOGITECH_FF=y -CONFIG_LOGIRUMBLEPAD2_FF=y -CONFIG_LOGIG940_FF=y -CONFIG_LOGIWHEELS_FF=y -CONFIG_HID_MAGICMOUSE=m -# CONFIG_HID_MAYFLASH is not set -CONFIG_HID_REDRAGON=y -CONFIG_HID_MICROSOFT=y -CONFIG_HID_MONTEREY=y -CONFIG_HID_MULTITOUCH=m -# CONFIG_HID_NTI is not set -CONFIG_HID_NTRIG=y -CONFIG_HID_ORTEK=m -CONFIG_HID_PANTHERLORD=m -CONFIG_PANTHERLORD_FF=y -# CONFIG_HID_PENMOUNT is not set -CONFIG_HID_PETALYNX=m -CONFIG_HID_PICOLCD=m -CONFIG_HID_PICOLCD_FB=y -CONFIG_HID_PICOLCD_BACKLIGHT=y -CONFIG_HID_PICOLCD_LCD=y -CONFIG_HID_PICOLCD_LEDS=y -CONFIG_HID_PICOLCD_CIR=y -CONFIG_HID_PLANTRONICS=y -CONFIG_HID_PRIMAX=m -# CONFIG_HID_RETRODE is not set -CONFIG_HID_ROCCAT=m -CONFIG_HID_SAITEK=m -CONFIG_HID_SAMSUNG=m -CONFIG_HID_SONY=m -CONFIG_SONY_FF=y -CONFIG_HID_SPEEDLINK=m -# CONFIG_HID_STEAM is not set -CONFIG_HID_STEELSERIES=m -CONFIG_HID_SUNPLUS=m -CONFIG_HID_RMI=m -CONFIG_HID_GREENASIA=m -CONFIG_GREENASIA_FF=y -CONFIG_HID_HYPERV_MOUSE=m -CONFIG_HID_SMARTJOYPLUS=m -CONFIG_SMARTJOYPLUS_FF=y -CONFIG_HID_TIVO=m -CONFIG_HID_TOPSEED=m -CONFIG_HID_THINGM=m -CONFIG_HID_THRUSTMASTER=m -CONFIG_THRUSTMASTER_FF=y -# CONFIG_HID_UDRAW_PS3 is not set -CONFIG_HID_WACOM=m -CONFIG_HID_WIIMOTE=m -CONFIG_HID_XINMO=m -CONFIG_HID_ZEROPLUS=m -CONFIG_ZEROPLUS_FF=y -CONFIG_HID_ZYDACRON=m -CONFIG_HID_SENSOR_HUB=m -CONFIG_HID_SENSOR_CUSTOM_SENSOR=m -CONFIG_HID_ALPS=m - -# -# USB HID support -# -CONFIG_USB_HID=y -CONFIG_HID_PID=y -CONFIG_USB_HIDDEV=y - -# -# I2C HID support -# -CONFIG_I2C_HID=m - -# -# Intel ISH HID support -# -CONFIG_INTEL_ISH_HID=m -CONFIG_USB_OHCI_LITTLE_ENDIAN=y -CONFIG_USB_SUPPORT=y -CONFIG_USB_COMMON=y -CONFIG_USB_ARCH_HAS_HCD=y -CONFIG_USB=y -CONFIG_USB_PCI=y -CONFIG_USB_ANNOUNCE_NEW_DEVICES=y - -# -# Miscellaneous USB options -# -CONFIG_USB_DEFAULT_PERSIST=y -# CONFIG_USB_DYNAMIC_MINORS is not set -CONFIG_USB_OTG=y -# CONFIG_USB_OTG_WHITELIST is not set -# CONFIG_USB_OTG_BLACKLIST_HUB is not set -CONFIG_USB_OTG_FSM=m -CONFIG_USB_LEDS_TRIGGER_USBPORT=m -CONFIG_USB_MON=y -CONFIG_USB_WUSB=m -CONFIG_USB_WUSB_CBAF=m -# CONFIG_USB_WUSB_CBAF_DEBUG is not set - -# -# USB Host Controller Drivers -# -# CONFIG_USB_C67X00_HCD is not set -CONFIG_USB_XHCI_HCD=y -# CONFIG_USB_XHCI_DBGCAP is not set -CONFIG_USB_XHCI_PCI=y -CONFIG_USB_XHCI_PLATFORM=m -CONFIG_USB_EHCI_HCD=y -CONFIG_USB_EHCI_ROOT_HUB_TT=y -CONFIG_USB_EHCI_TT_NEWSCHED=y -CONFIG_USB_EHCI_PCI=y -# CONFIG_USB_EHCI_HCD_PLATFORM is not set -# CONFIG_USB_OXU210HP_HCD is not set -# CONFIG_USB_ISP116X_HCD is not set -CONFIG_USB_FOTG210_HCD=m -CONFIG_USB_OHCI_HCD=y -CONFIG_USB_OHCI_HCD_PCI=y -# CONFIG_USB_OHCI_HCD_PLATFORM is not set -CONFIG_USB_UHCI_HCD=y -CONFIG_USB_U132_HCD=m -CONFIG_USB_SL811_HCD=m -CONFIG_USB_SL811_HCD_ISO=y -# CONFIG_USB_SL811_CS is not set -# CONFIG_USB_R8A66597_HCD is not set -CONFIG_USB_WHCI_HCD=m -CONFIG_USB_HWA_HCD=m -# CONFIG_USB_HCD_BCMA is not set -# CONFIG_USB_HCD_SSB is not set -# CONFIG_USB_HCD_TEST_MODE is not set - -# -# USB Device Class drivers -# -CONFIG_USB_ACM=m -CONFIG_USB_PRINTER=m -CONFIG_USB_WDM=m -CONFIG_USB_TMC=m - -# -# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may -# - -# -# also be needed; see USB_STORAGE Help for more info -# -CONFIG_USB_STORAGE=m -# CONFIG_USB_STORAGE_DEBUG is not set -CONFIG_USB_STORAGE_REALTEK=m -CONFIG_REALTEK_AUTOPM=y -CONFIG_USB_STORAGE_DATAFAB=m -CONFIG_USB_STORAGE_FREECOM=m -CONFIG_USB_STORAGE_ISD200=m -CONFIG_USB_STORAGE_USBAT=m -CONFIG_USB_STORAGE_SDDR09=m -CONFIG_USB_STORAGE_SDDR55=m -CONFIG_USB_STORAGE_JUMPSHOT=m -CONFIG_USB_STORAGE_ALAUDA=m -CONFIG_USB_STORAGE_ONETOUCH=m -CONFIG_USB_STORAGE_KARMA=m -CONFIG_USB_STORAGE_CYPRESS_ATACB=m -CONFIG_USB_STORAGE_ENE_UB6250=m -CONFIG_USB_UAS=m - -# -# USB Imaging devices -# -CONFIG_USB_MDC800=m -CONFIG_USB_MICROTEK=m -# CONFIG_USBIP_CORE is not set -CONFIG_USB_MUSB_HDRC=m -CONFIG_USB_MUSB_HOST=y - -# -# Platform Glue Layer -# - -# -# MUSB DMA mode -# -CONFIG_MUSB_PIO_ONLY=y -CONFIG_USB_DWC3=m -CONFIG_USB_DWC3_HOST=y - -# -# Platform Glue Driver Support -# -CONFIG_USB_DWC3_PCI=m -CONFIG_USB_DWC3_HAPS=m -CONFIG_USB_DWC2=y -CONFIG_USB_DWC2_HOST=y - -# -# Gadget/Dual-role mode requires USB Gadget support to be enabled -# -CONFIG_USB_DWC2_PCI=y -# CONFIG_USB_DWC2_DEBUG is not set -# CONFIG_USB_DWC2_TRACK_MISSED_SOFS is not set -# CONFIG_USB_CHIPIDEA is not set -CONFIG_USB_ISP1760=m -CONFIG_USB_ISP1760_HCD=y -CONFIG_USB_ISP1760_HOST_ROLE=y - -# -# USB port drivers -# -CONFIG_USB_USS720=m -CONFIG_USB_SERIAL=y -CONFIG_USB_SERIAL_CONSOLE=y -CONFIG_USB_SERIAL_GENERIC=y -# CONFIG_USB_SERIAL_SIMPLE is not set -CONFIG_USB_SERIAL_AIRCABLE=m -CONFIG_USB_SERIAL_ARK3116=m -CONFIG_USB_SERIAL_BELKIN=m -CONFIG_USB_SERIAL_CH341=m -CONFIG_USB_SERIAL_WHITEHEAT=m -CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m -CONFIG_USB_SERIAL_CP210X=m -CONFIG_USB_SERIAL_CYPRESS_M8=m -CONFIG_USB_SERIAL_EMPEG=m -CONFIG_USB_SERIAL_FTDI_SIO=m -CONFIG_USB_SERIAL_VISOR=m -CONFIG_USB_SERIAL_IPAQ=m -CONFIG_USB_SERIAL_IR=m -CONFIG_USB_SERIAL_EDGEPORT=m -CONFIG_USB_SERIAL_EDGEPORT_TI=m -# CONFIG_USB_SERIAL_F81232 is not set -# CONFIG_USB_SERIAL_F8153X is not set -CONFIG_USB_SERIAL_GARMIN=m -CONFIG_USB_SERIAL_IPW=m -CONFIG_USB_SERIAL_IUU=m -CONFIG_USB_SERIAL_KEYSPAN_PDA=m -CONFIG_USB_SERIAL_KEYSPAN=m -CONFIG_USB_SERIAL_KLSI=m -CONFIG_USB_SERIAL_KOBIL_SCT=m -CONFIG_USB_SERIAL_MCT_U232=m -# CONFIG_USB_SERIAL_METRO is not set -CONFIG_USB_SERIAL_MOS7720=m -CONFIG_USB_SERIAL_MOS7715_PARPORT=y -CONFIG_USB_SERIAL_MOS7840=m -CONFIG_USB_SERIAL_MXUPORT=m -CONFIG_USB_SERIAL_NAVMAN=m -CONFIG_USB_SERIAL_PL2303=m -CONFIG_USB_SERIAL_OTI6858=m -CONFIG_USB_SERIAL_QCAUX=m -CONFIG_USB_SERIAL_QUALCOMM=m -CONFIG_USB_SERIAL_SPCP8X5=m -CONFIG_USB_SERIAL_SAFE=m -CONFIG_USB_SERIAL_SAFE_PADDED=y -CONFIG_USB_SERIAL_SIERRAWIRELESS=m -CONFIG_USB_SERIAL_SYMBOL=m -CONFIG_USB_SERIAL_TI=m -CONFIG_USB_SERIAL_CYBERJACK=m -CONFIG_USB_SERIAL_XIRCOM=m -CONFIG_USB_SERIAL_WWAN=m -CONFIG_USB_SERIAL_OPTION=m -CONFIG_USB_SERIAL_OMNINET=m -CONFIG_USB_SERIAL_OPTICON=m -CONFIG_USB_SERIAL_XSENS_MT=m -CONFIG_USB_SERIAL_WISHBONE=m -CONFIG_USB_SERIAL_SSU100=m -CONFIG_USB_SERIAL_QT2=m -# CONFIG_USB_SERIAL_UPD78F0730 is not set -CONFIG_USB_SERIAL_DEBUG=m - -# -# USB Miscellaneous drivers -# -CONFIG_USB_EMI62=m -CONFIG_USB_EMI26=m -CONFIG_USB_ADUTUX=m -CONFIG_USB_SEVSEG=m -# CONFIG_USB_RIO500 is not set -CONFIG_USB_LEGOTOWER=m -CONFIG_USB_LCD=m -# CONFIG_USB_CYPRESS_CY7C63 is not set -# CONFIG_USB_CYTHERM is not set -CONFIG_USB_IDMOUSE=m -CONFIG_USB_FTDI_ELAN=m -CONFIG_USB_APPLEDISPLAY=m -CONFIG_USB_SISUSBVGA=m -CONFIG_USB_SISUSBVGA_CON=y -CONFIG_USB_LD=m -CONFIG_USB_TRANCEVIBRATOR=m -CONFIG_USB_IOWARRIOR=m -# CONFIG_USB_TEST is not set -# CONFIG_USB_EHSET_TEST_FIXTURE is not set -CONFIG_USB_ISIGHTFW=m -CONFIG_USB_YUREX=m -CONFIG_USB_EZUSB_FX2=m -# CONFIG_USB_HUB_USB251XB is not set -CONFIG_USB_HSIC_USB3503=m -CONFIG_USB_HSIC_USB4604=m -# CONFIG_USB_LINK_LAYER_TEST is not set -CONFIG_USB_CHAOSKEY=m -CONFIG_USB_ATM=m -CONFIG_USB_SPEEDTOUCH=m -CONFIG_USB_CXACRU=m -CONFIG_USB_UEAGLEATM=m -CONFIG_USB_XUSBATM=m - -# -# USB Physical Layer drivers -# -CONFIG_USB_PHY=y -CONFIG_NOP_USB_XCEIV=y -CONFIG_USB_GPIO_VBUS=m -# CONFIG_TAHVO_USB is not set -CONFIG_USB_ISP1301=m -# CONFIG_USB_GADGET is not set -# CONFIG_TYPEC is not set -# CONFIG_USB_ROLE_SWITCH is not set -# CONFIG_USB_LED_TRIG is not set -# CONFIG_USB_ULPI_BUS is not set -CONFIG_UWB=m -CONFIG_UWB_HWA=m -CONFIG_UWB_WHCI=m -CONFIG_UWB_I1480U=m -CONFIG_MMC=m -CONFIG_MMC_BLOCK=m -CONFIG_MMC_BLOCK_MINORS=8 -CONFIG_SDIO_UART=m -# CONFIG_MMC_TEST is not set - -# -# MMC/SD/SDIO Host Controller Drivers -# -# CONFIG_MMC_DEBUG is not set -CONFIG_MMC_SDHCI=m -CONFIG_MMC_SDHCI_PCI=m -CONFIG_MMC_RICOH_MMC=y -CONFIG_MMC_SDHCI_ACPI=m -CONFIG_MMC_SDHCI_PLTFM=m -# CONFIG_MMC_SDHCI_F_SDH30 is not set -CONFIG_MMC_WBSD=m -CONFIG_MMC_TIFM_SD=m -CONFIG_MMC_SDRICOH_CS=m -CONFIG_MMC_CB710=m -CONFIG_MMC_VIA_SDMMC=m -CONFIG_MMC_VUB300=m -CONFIG_MMC_USHC=m -CONFIG_MMC_USDHI6ROL0=m -CONFIG_MMC_CQHCI=m -# CONFIG_MMC_TOSHIBA_PCI is not set -# CONFIG_MMC_MTK is not set -# CONFIG_MMC_SDHCI_XENON is not set -CONFIG_MEMSTICK=m -# CONFIG_MEMSTICK_DEBUG is not set - -# -# MemoryStick drivers -# -# CONFIG_MEMSTICK_UNSAFE_RESUME is not set -CONFIG_MSPRO_BLOCK=m -# CONFIG_MS_BLOCK is not set - -# -# MemoryStick Host Controller Drivers -# -CONFIG_MEMSTICK_TIFM_MS=m -CONFIG_MEMSTICK_JMICRON_38X=m -CONFIG_MEMSTICK_R592=m -CONFIG_NEW_LEDS=y -CONFIG_LEDS_CLASS=y -CONFIG_LEDS_CLASS_FLASH=m -# CONFIG_LEDS_BRIGHTNESS_HW_CHANGED is not set - -# -# LED drivers -# -# CONFIG_LEDS_APU is not set -# CONFIG_LEDS_AS3645A is not set -CONFIG_LEDS_LM3530=m -CONFIG_LEDS_LM3642=m -# CONFIG_LEDS_LM3601X is not set -# CONFIG_LEDS_MT6323 is not set -CONFIG_LEDS_PCA9532=m -CONFIG_LEDS_PCA9532_GPIO=y -CONFIG_LEDS_GPIO=m -CONFIG_LEDS_LP3944=m -CONFIG_LEDS_LP3952=m -CONFIG_LEDS_LP55XX_COMMON=m -CONFIG_LEDS_LP5521=m -CONFIG_LEDS_LP5523=m -CONFIG_LEDS_LP5562=m -CONFIG_LEDS_LP8501=m -CONFIG_LEDS_CLEVO_MAIL=m -CONFIG_LEDS_PCA955X=m -# CONFIG_LEDS_PCA955X_GPIO is not set -CONFIG_LEDS_PCA963X=m -CONFIG_LEDS_PWM=m -CONFIG_LEDS_BD2802=m -CONFIG_LEDS_INTEL_SS4200=m -CONFIG_LEDS_LT3593=m -CONFIG_LEDS_TCA6507=m -# CONFIG_LEDS_TLC591XX is not set -CONFIG_LEDS_LM355x=m - -# -# LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM) -# -CONFIG_LEDS_BLINKM=m -CONFIG_LEDS_MLXCPLD=m -# CONFIG_LEDS_MLXREG is not set -# CONFIG_LEDS_USER is not set -# CONFIG_LEDS_NIC78BX is not set - -# -# LED Triggers -# -CONFIG_LEDS_TRIGGERS=y -CONFIG_LEDS_TRIGGER_TIMER=m -CONFIG_LEDS_TRIGGER_ONESHOT=y -# CONFIG_LEDS_TRIGGER_DISK is not set -# CONFIG_LEDS_TRIGGER_MTD is not set -CONFIG_LEDS_TRIGGER_HEARTBEAT=m -CONFIG_LEDS_TRIGGER_BACKLIGHT=m -CONFIG_LEDS_TRIGGER_CPU=y -# CONFIG_LEDS_TRIGGER_ACTIVITY is not set -CONFIG_LEDS_TRIGGER_GPIO=m -CONFIG_LEDS_TRIGGER_DEFAULT_ON=m - -# -# iptables trigger is under Netfilter config (LED target) -# -CONFIG_LEDS_TRIGGER_TRANSIENT=m -CONFIG_LEDS_TRIGGER_CAMERA=m -# CONFIG_LEDS_TRIGGER_PANIC is not set -# CONFIG_LEDS_TRIGGER_NETDEV is not set -CONFIG_ACCESSIBILITY=y -CONFIG_A11Y_BRAILLE_CONSOLE=y -CONFIG_INFINIBAND=m -CONFIG_INFINIBAND_USER_MAD=m -CONFIG_INFINIBAND_USER_ACCESS=m -# CONFIG_INFINIBAND_EXP_LEGACY_VERBS_NEW_UAPI is not set -CONFIG_INFINIBAND_USER_MEM=y -CONFIG_INFINIBAND_ON_DEMAND_PAGING=y -CONFIG_INFINIBAND_ADDR_TRANS=y -CONFIG_INFINIBAND_ADDR_TRANS_CONFIGFS=y -CONFIG_INFINIBAND_MTHCA=m -CONFIG_INFINIBAND_MTHCA_DEBUG=y -CONFIG_INFINIBAND_QIB=m -CONFIG_INFINIBAND_QIB_DCA=y -CONFIG_INFINIBAND_CXGB3=m -CONFIG_INFINIBAND_CXGB4=m -# CONFIG_INFINIBAND_I40IW is not set -CONFIG_MLX4_INFINIBAND=m -CONFIG_INFINIBAND_NES=m -# CONFIG_INFINIBAND_NES_DEBUG is not set -# CONFIG_INFINIBAND_OCRDMA is not set -# CONFIG_INFINIBAND_VMWARE_PVRDMA is not set -CONFIG_INFINIBAND_USNIC=m -CONFIG_INFINIBAND_IPOIB=m -CONFIG_INFINIBAND_IPOIB_CM=y -CONFIG_INFINIBAND_IPOIB_DEBUG=y -CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y -CONFIG_INFINIBAND_SRP=m -CONFIG_INFINIBAND_SRPT=m -CONFIG_INFINIBAND_ISER=m -CONFIG_INFINIBAND_ISERT=m -# CONFIG_INFINIBAND_OPA_VNIC is not set -CONFIG_INFINIBAND_RDMAVT=m -CONFIG_RDMA_RXE=m -CONFIG_INFINIBAND_HFI1=m -CONFIG_HFI1_DEBUG_SDMA_ORDER=y -CONFIG_SDMA_VERBOSITY=y -CONFIG_INFINIBAND_QEDR=m -# CONFIG_INFINIBAND_BNXT_RE is not set -CONFIG_EDAC_ATOMIC_SCRUB=y -CONFIG_EDAC_SUPPORT=y -CONFIG_EDAC=y -CONFIG_EDAC_LEGACY_SYSFS=y -# CONFIG_EDAC_DEBUG is not set -CONFIG_EDAC_DECODE_MCE=m -# CONFIG_EDAC_GHES is not set -CONFIG_EDAC_AMD64=m -# CONFIG_EDAC_AMD64_ERROR_INJECTION is not set -CONFIG_EDAC_E752X=m -CONFIG_EDAC_I82975X=m -CONFIG_EDAC_I3000=m -CONFIG_EDAC_I3200=m -CONFIG_EDAC_IE31200=m -CONFIG_EDAC_X38=m -CONFIG_EDAC_I5400=m -CONFIG_EDAC_I7CORE=m -CONFIG_EDAC_I5000=m -CONFIG_EDAC_I5100=m -CONFIG_EDAC_I7300=m -CONFIG_EDAC_SBRIDGE=m -CONFIG_EDAC_SKX=m -# CONFIG_EDAC_PND2 is not set -CONFIG_RTC_LIB=y -CONFIG_RTC_MC146818_LIB=y -CONFIG_RTC_CLASS=y -CONFIG_RTC_HCTOSYS=y -CONFIG_RTC_HCTOSYS_DEVICE="rtc0" -CONFIG_RTC_SYSTOHC=y -CONFIG_RTC_SYSTOHC_DEVICE="rtc0" -# CONFIG_RTC_DEBUG is not set -CONFIG_RTC_NVMEM=y - -# -# RTC interfaces -# -CONFIG_RTC_INTF_SYSFS=y -CONFIG_RTC_INTF_PROC=y -CONFIG_RTC_INTF_DEV=y -# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set -# CONFIG_RTC_DRV_TEST is not set - -# -# I2C RTC drivers -# -CONFIG_RTC_DRV_ABB5ZES3=m -CONFIG_RTC_DRV_ABX80X=m -CONFIG_RTC_DRV_DS1307=m -# CONFIG_RTC_DRV_DS1307_CENTURY is not set -CONFIG_RTC_DRV_DS1374=m -# CONFIG_RTC_DRV_DS1374_WDT is not set -CONFIG_RTC_DRV_DS1672=m -CONFIG_RTC_DRV_MAX6900=m -CONFIG_RTC_DRV_RS5C372=m -CONFIG_RTC_DRV_ISL1208=m -CONFIG_RTC_DRV_ISL12022=m -CONFIG_RTC_DRV_X1205=m -CONFIG_RTC_DRV_PCF8523=m -CONFIG_RTC_DRV_PCF85063=m -# CONFIG_RTC_DRV_PCF85363 is not set -CONFIG_RTC_DRV_PCF8563=m -CONFIG_RTC_DRV_PCF8583=m -CONFIG_RTC_DRV_M41T80=m -CONFIG_RTC_DRV_M41T80_WDT=y -CONFIG_RTC_DRV_BQ32K=m -# CONFIG_RTC_DRV_S35390A is not set -CONFIG_RTC_DRV_FM3130=m -# CONFIG_RTC_DRV_RX8010 is not set -CONFIG_RTC_DRV_RX8581=m -CONFIG_RTC_DRV_RX8025=m -CONFIG_RTC_DRV_EM3027=m -CONFIG_RTC_DRV_RV8803=m - -# -# SPI RTC drivers -# -CONFIG_RTC_I2C_AND_SPI=m - -# -# SPI and I2C RTC drivers -# -CONFIG_RTC_DRV_DS3232=m -CONFIG_RTC_DRV_DS3232_HWMON=y -# CONFIG_RTC_DRV_PCF2127 is not set -CONFIG_RTC_DRV_RV3029C2=m -CONFIG_RTC_DRV_RV3029_HWMON=y - -# -# Platform RTC drivers -# -CONFIG_RTC_DRV_CMOS=y -CONFIG_RTC_DRV_DS1286=m -CONFIG_RTC_DRV_DS1511=m -CONFIG_RTC_DRV_DS1553=m -CONFIG_RTC_DRV_DS1685_FAMILY=m -CONFIG_RTC_DRV_DS1685=y -# CONFIG_RTC_DRV_DS1689 is not set -# CONFIG_RTC_DRV_DS17285 is not set -# CONFIG_RTC_DRV_DS17485 is not set -# CONFIG_RTC_DRV_DS17885 is not set -CONFIG_RTC_DS1685_PROC_REGS=y -CONFIG_RTC_DRV_DS1742=m -CONFIG_RTC_DRV_DS2404=m -CONFIG_RTC_DRV_STK17TA8=m -# CONFIG_RTC_DRV_M48T86 is not set -CONFIG_RTC_DRV_M48T35=m -CONFIG_RTC_DRV_M48T59=m -CONFIG_RTC_DRV_MSM6242=m -CONFIG_RTC_DRV_BQ4802=m -CONFIG_RTC_DRV_RP5C01=m -CONFIG_RTC_DRV_V3020=m -# CONFIG_RTC_DRV_CROS_EC is not set - -# -# on-CPU RTC drivers -# -# CONFIG_RTC_DRV_FTRTC010 is not set -# CONFIG_RTC_DRV_MT6397 is not set - -# -# HID Sensor RTC drivers -# -# CONFIG_RTC_DRV_HID_SENSOR_TIME is not set -CONFIG_DMADEVICES=y -# CONFIG_DMADEVICES_DEBUG is not set - -# -# DMA Devices -# -CONFIG_DMA_ENGINE=y -CONFIG_DMA_VIRTUAL_CHANNELS=y -CONFIG_DMA_ACPI=y -# CONFIG_ALTERA_MSGDMA is not set -CONFIG_INTEL_IDMA64=m -CONFIG_INTEL_IOATDMA=m -CONFIG_INTEL_MIC_X100_DMA=m -# CONFIG_QCOM_HIDMA_MGMT is not set -# CONFIG_QCOM_HIDMA is not set -CONFIG_DW_DMAC_CORE=y -# CONFIG_DW_DMAC is not set -# CONFIG_DW_DMAC_PCI is not set -CONFIG_HSU_DMA=y - -# -# DMA Clients -# -CONFIG_ASYNC_TX_DMA=y -# CONFIG_DMATEST is not set -CONFIG_DMA_ENGINE_RAID=y - -# -# DMABUF options -# -CONFIG_SYNC_FILE=y -# CONFIG_SW_SYNC is not set -CONFIG_DCA=m -CONFIG_AUXDISPLAY=y -# CONFIG_HD44780 is not set -CONFIG_KS0108=m -CONFIG_KS0108_PORT=0x378 -CONFIG_KS0108_DELAY=2 -CONFIG_CFAG12864B=m -CONFIG_CFAG12864B_RATE=20 -# CONFIG_IMG_ASCII_LCD is not set -# CONFIG_PANEL is not set -CONFIG_UIO=m -CONFIG_UIO_CIF=m -# CONFIG_UIO_PDRV_GENIRQ is not set -CONFIG_UIO_DMEM_GENIRQ=m -CONFIG_UIO_AEC=m -CONFIG_UIO_SERCOS3=m -CONFIG_UIO_PCI_GENERIC=m -# CONFIG_UIO_NETX is not set -# CONFIG_UIO_PRUSS is not set -# CONFIG_UIO_MF624 is not set -# CONFIG_UIO_HV_GENERIC is not set -CONFIG_VFIO_IOMMU_TYPE1=y -CONFIG_VFIO_VIRQFD=y -CONFIG_VFIO=y -# CONFIG_VFIO_NOIOMMU is not set -CONFIG_VFIO_PCI=y -CONFIG_VFIO_PCI_VGA=y -CONFIG_VFIO_PCI_MMAP=y -CONFIG_VFIO_PCI_INTX=y -CONFIG_VFIO_PCI_IGD=y -# CONFIG_VFIO_MDEV is not set -CONFIG_IRQ_BYPASS_MANAGER=y -# CONFIG_VIRT_DRIVERS is not set -CONFIG_VIRTIO=y -CONFIG_VIRTIO_MENU=y -CONFIG_VIRTIO_PCI=y -CONFIG_VIRTIO_PCI_LEGACY=y -CONFIG_VIRTIO_BALLOON=m -CONFIG_VIRTIO_INPUT=m -CONFIG_VIRTIO_MMIO=m -# CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES is not set - -# -# Microsoft Hyper-V guest support -# -CONFIG_HYPERV=m -CONFIG_HYPERV_TSCPAGE=y -CONFIG_HYPERV_UTILS=m -CONFIG_HYPERV_BALLOON=m - -# -# Xen driver support -# -CONFIG_XEN_BALLOON=y -CONFIG_XEN_SELFBALLOONING=y -# CONFIG_XEN_BALLOON_MEMORY_HOTPLUG is not set -CONFIG_XEN_SCRUB_PAGES_DEFAULT=y -CONFIG_XEN_DEV_EVTCHN=m -CONFIG_XEN_BACKEND=y -CONFIG_XENFS=m -CONFIG_XEN_COMPAT_XENFS=y -CONFIG_XEN_SYS_HYPERVISOR=y -CONFIG_XEN_XENBUS_FRONTEND=y -CONFIG_XEN_GNTDEV=m -CONFIG_XEN_GRANT_DEV_ALLOC=m -# CONFIG_XEN_GRANT_DMA_ALLOC is not set -CONFIG_SWIOTLB_XEN=y -CONFIG_XEN_TMEM=m -CONFIG_XEN_PCIDEV_BACKEND=m -# CONFIG_XEN_PVCALLS_FRONTEND is not set -# CONFIG_XEN_PVCALLS_BACKEND is not set -# CONFIG_XEN_SCSI_BACKEND is not set -CONFIG_XEN_PRIVCMD=m -CONFIG_XEN_ACPI_PROCESSOR=m -CONFIG_XEN_MCE_LOG=y -CONFIG_XEN_HAVE_PVMMU=y -CONFIG_XEN_EFI=y -CONFIG_XEN_AUTO_XLATE=y -CONFIG_XEN_ACPI=y -CONFIG_XEN_SYMS=y -CONFIG_XEN_HAVE_VPMU=y -CONFIG_STAGING=y -# CONFIG_PRISM2_USB is not set -# CONFIG_COMEDI is not set -# CONFIG_RTL8192U is not set -# CONFIG_RTLLIB is not set -# CONFIG_RTL8723BS is not set -CONFIG_R8712U=m -CONFIG_R8188EU=m -CONFIG_88EU_AP_MODE=y -# CONFIG_R8822BE is not set -CONFIG_RTS5208=m -# CONFIG_VT6655 is not set -# CONFIG_VT6656 is not set -CONFIG_FB_SM750=m -# CONFIG_FB_XGI is not set - -# -# Speakup console speech -# -# CONFIG_SPEAKUP is not set -CONFIG_STAGING_MEDIA=y -CONFIG_I2C_BCM2048=m -CONFIG_VIDEO_ZORAN=m -CONFIG_VIDEO_ZORAN_DC30=m -CONFIG_VIDEO_ZORAN_ZR36060=m -CONFIG_VIDEO_ZORAN_BUZ=m -CONFIG_VIDEO_ZORAN_DC10=m -CONFIG_VIDEO_ZORAN_LML33=m -CONFIG_VIDEO_ZORAN_LML33R10=m -CONFIG_VIDEO_ZORAN_AVS6EYES=m - -# -# Android -# -# CONFIG_ASHMEM is not set -# CONFIG_ANDROID_VSOC is not set -# CONFIG_ION is not set -CONFIG_LTE_GDM724X=m -CONFIG_FIREWIRE_SERIAL=m -CONFIG_FWTTY_MAX_TOTAL_PORTS=64 -CONFIG_FWTTY_MAX_CARD_PORTS=32 -CONFIG_DGNC=m -# CONFIG_GS_FPGABOOT is not set -CONFIG_UNISYSSPAR=y -# CONFIG_WILC1000_SDIO is not set -CONFIG_MOST=m -# CONFIG_MOST_CDEV is not set -# CONFIG_MOST_NET is not set -# CONFIG_MOST_SOUND is not set -# CONFIG_MOST_VIDEO is not set -# CONFIG_MOST_I2C is not set -# CONFIG_MOST_USB is not set -CONFIG_KS7010=m -CONFIG_GREYBUS=m -CONFIG_GREYBUS_ES2=m -CONFIG_GREYBUS_AUDIO=m -CONFIG_GREYBUS_BOOTROM=m -CONFIG_GREYBUS_HID=m -CONFIG_GREYBUS_LIGHT=m -CONFIG_GREYBUS_LOG=m -CONFIG_GREYBUS_LOOPBACK=m -CONFIG_GREYBUS_POWER=m -CONFIG_GREYBUS_RAW=m -CONFIG_GREYBUS_VIBRATOR=m -CONFIG_GREYBUS_BRIDGED_PHY=m -CONFIG_GREYBUS_GPIO=m -CONFIG_GREYBUS_I2C=m -CONFIG_GREYBUS_PWM=m -CONFIG_GREYBUS_SDIO=m -CONFIG_GREYBUS_UART=m -CONFIG_GREYBUS_USB=m -# CONFIG_DRM_VBOXVIDEO is not set -# CONFIG_MTK_MMC is not set - -# -# Gasket devices -# -# CONFIG_STAGING_GASKET_FRAMEWORK is not set -# CONFIG_EROFS_FS is not set -CONFIG_X86_PLATFORM_DEVICES=y -CONFIG_ACER_WMI=m -# CONFIG_ACER_WIRELESS is not set -CONFIG_ACERHDF=m -CONFIG_ALIENWARE_WMI=m -CONFIG_ASUS_LAPTOP=m -# CONFIG_DELL_SMBIOS is not set -CONFIG_DELL_WMI_AIO=m -# CONFIG_DELL_WMI_LED is not set -CONFIG_DELL_SMO8800=m -# CONFIG_DELL_RBTN is not set -CONFIG_FUJITSU_LAPTOP=m -CONFIG_FUJITSU_TABLET=m -CONFIG_AMILO_RFKILL=m -# CONFIG_GPD_POCKET_FAN is not set -CONFIG_HP_ACCEL=m -CONFIG_HP_WIRELESS=m -CONFIG_HP_WMI=m -CONFIG_MSI_LAPTOP=m -CONFIG_PANASONIC_LAPTOP=m -CONFIG_COMPAL_LAPTOP=m -CONFIG_SONY_LAPTOP=m -CONFIG_SONYPI_COMPAT=y -CONFIG_IDEAPAD_LAPTOP=m -CONFIG_THINKPAD_ACPI=m -CONFIG_THINKPAD_ACPI_ALSA_SUPPORT=y -# CONFIG_THINKPAD_ACPI_DEBUGFACILITIES is not set -# CONFIG_THINKPAD_ACPI_DEBUG is not set -# CONFIG_THINKPAD_ACPI_UNSAFE_LEDS is not set -CONFIG_THINKPAD_ACPI_VIDEO=y -CONFIG_THINKPAD_ACPI_HOTKEY_POLL=y -CONFIG_SENSORS_HDAPS=m -CONFIG_INTEL_MENLOW=m -CONFIG_EEEPC_LAPTOP=m -CONFIG_ASUS_WMI=m -CONFIG_ASUS_NB_WMI=m -CONFIG_EEEPC_WMI=m -# CONFIG_ASUS_WIRELESS is not set -CONFIG_ACPI_WMI=m -CONFIG_WMI_BMOF=m -# CONFIG_INTEL_WMI_THUNDERBOLT is not set -CONFIG_MSI_WMI=m -# CONFIG_PEAQ_WMI is not set -CONFIG_TOPSTAR_LAPTOP=m -CONFIG_TOSHIBA_BT_RFKILL=m -CONFIG_TOSHIBA_HAPS=m -CONFIG_TOSHIBA_WMI=m -CONFIG_ACPI_CMPC=m -# CONFIG_INTEL_INT0002_VGPIO is not set -# CONFIG_INTEL_HID_EVENT is not set -CONFIG_INTEL_VBTN=m -CONFIG_INTEL_IPS=m -# CONFIG_INTEL_PMC_CORE is not set -# CONFIG_IBM_RTL is not set -CONFIG_SAMSUNG_LAPTOP=m -CONFIG_MXM_WMI=m -CONFIG_INTEL_OAKTRAIL=m -CONFIG_SAMSUNG_Q10=m -CONFIG_APPLE_GMUX=m -CONFIG_INTEL_RST=m -# CONFIG_INTEL_SMARTCONNECT is not set -CONFIG_PVPANIC=m -# CONFIG_INTEL_PMC_IPC is not set -CONFIG_SURFACE_PRO3_BUTTON=m -# CONFIG_SURFACE_3_BUTTON is not set -# CONFIG_INTEL_PUNIT_IPC is not set -# CONFIG_MLX_PLATFORM is not set -# CONFIG_INTEL_TURBO_MAX_3 is not set -# CONFIG_I2C_MULTI_INSTANTIATE is not set -# CONFIG_INTEL_ATOMISP2_PM is not set -CONFIG_PMC_ATOM=y -CONFIG_CHROME_PLATFORMS=y -CONFIG_CHROMEOS_LAPTOP=m -CONFIG_CHROMEOS_PSTORE=m -# CONFIG_CHROMEOS_TBMC is not set -# CONFIG_CROS_EC_I2C is not set -CONFIG_CROS_EC_LPC=m -# CONFIG_CROS_EC_LPC_MEC is not set -CONFIG_CROS_EC_PROTO=y -# CONFIG_CROS_KBD_LED_BACKLIGHT is not set -# CONFIG_MELLANOX_PLATFORM is not set -CONFIG_CLKDEV_LOOKUP=y -CONFIG_HAVE_CLK_PREPARE=y -CONFIG_COMMON_CLK=y - -# -# Common Clock Framework -# -# CONFIG_COMMON_CLK_MAX9485 is not set -CONFIG_COMMON_CLK_SI5351=m -# CONFIG_COMMON_CLK_SI544 is not set -CONFIG_COMMON_CLK_CDCE706=m -# CONFIG_COMMON_CLK_CS2000_CP is not set -CONFIG_COMMON_CLK_PWM=m -# CONFIG_HWSPINLOCK is not set - -# -# Clock Source drivers -# -CONFIG_CLKEVT_I8253=y -CONFIG_I8253_LOCK=y -CONFIG_CLKBLD_I8253=y -CONFIG_MAILBOX=y -CONFIG_PCC=y -CONFIG_ALTERA_MBOX=m -CONFIG_IOMMU_API=y -CONFIG_IOMMU_SUPPORT=y - -# -# Generic IOMMU Pagetable Support -# -# CONFIG_IOMMU_DEBUGFS is not set -# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set -CONFIG_IOMMU_IOVA=y -CONFIG_AMD_IOMMU=y -CONFIG_AMD_IOMMU_V2=m -CONFIG_DMAR_TABLE=y -CONFIG_INTEL_IOMMU=y -# CONFIG_INTEL_IOMMU_SVM is not set -# CONFIG_INTEL_IOMMU_DEFAULT_ON is not set -CONFIG_INTEL_IOMMU_FLOPPY_WA=y -CONFIG_IRQ_REMAP=y - -# -# Remoteproc drivers -# -CONFIG_REMOTEPROC=m - -# -# Rpmsg drivers -# -# CONFIG_RPMSG_QCOM_GLINK_RPM is not set -# CONFIG_RPMSG_VIRTIO is not set -# CONFIG_SOUNDWIRE is not set - -# -# SOC (System On Chip) specific Drivers -# - -# -# Amlogic SoC drivers -# - -# -# Broadcom SoC drivers -# - -# -# NXP/Freescale QorIQ SoC drivers -# - -# -# i.MX SoC drivers -# - -# -# Qualcomm SoC drivers -# -# CONFIG_SOC_TI is not set - -# -# Xilinx SoC drivers -# -# CONFIG_XILINX_VCU is not set -CONFIG_PM_DEVFREQ=y - -# -# DEVFREQ Governors -# -CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=m -# CONFIG_DEVFREQ_GOV_PERFORMANCE is not set -# CONFIG_DEVFREQ_GOV_POWERSAVE is not set -# CONFIG_DEVFREQ_GOV_USERSPACE is not set -# CONFIG_DEVFREQ_GOV_PASSIVE is not set - -# -# DEVFREQ Drivers -# -CONFIG_PM_DEVFREQ_EVENT=y -CONFIG_EXTCON=y - -# -# Extcon Device Drivers -# -# CONFIG_EXTCON_GPIO is not set -# CONFIG_EXTCON_INTEL_INT3496 is not set -# CONFIG_EXTCON_MAX14577 is not set -# CONFIG_EXTCON_MAX3355 is not set -# CONFIG_EXTCON_RT8973A is not set -# CONFIG_EXTCON_SM5502 is not set -# CONFIG_EXTCON_USB_GPIO is not set -# CONFIG_EXTCON_USBC_CROS_EC is not set -# CONFIG_MEMORY is not set -# CONFIG_IIO is not set -CONFIG_NTB=m -# CONFIG_NTB_AMD is not set -# CONFIG_NTB_IDT is not set -# CONFIG_NTB_INTEL is not set -# CONFIG_NTB_SWITCHTEC is not set -# CONFIG_NTB_PINGPONG is not set -# CONFIG_NTB_TOOL is not set -# CONFIG_NTB_PERF is not set -# CONFIG_NTB_TRANSPORT is not set -# CONFIG_VME_BUS is not set -CONFIG_PWM=y -CONFIG_PWM_SYSFS=y -CONFIG_PWM_CROS_EC=m -CONFIG_PWM_LP3943=m -# CONFIG_PWM_LPSS_PCI is not set -# CONFIG_PWM_LPSS_PLATFORM is not set -CONFIG_PWM_PCA9685=m - -# -# IRQ chip support -# -CONFIG_ARM_GIC_MAX_NR=1 -# CONFIG_IPACK_BUS is not set -CONFIG_RESET_CONTROLLER=y -# CONFIG_RESET_TI_SYSCON is not set -# CONFIG_FMC is not set - -# -# PHY Subsystem -# -CONFIG_GENERIC_PHY=y -CONFIG_BCM_KONA_USB2_PHY=m -# CONFIG_PHY_PXA_28NM_HSIC is not set -# CONFIG_PHY_PXA_28NM_USB2 is not set -CONFIG_PHY_SAMSUNG_USB2=m -CONFIG_POWERCAP=y -CONFIG_INTEL_RAPL=m -# CONFIG_IDLE_INJECT is not set -# CONFIG_MCB is not set - -# -# Performance monitor support -# -CONFIG_RAS=y -# CONFIG_RAS_CEC is not set -CONFIG_THUNDERBOLT=m - -# -# Android -# -CONFIG_ANDROID=y -CONFIG_ANDROID_BINDER_IPC=y -CONFIG_ANDROID_BINDER_DEVICES="binder,hwbinder,vndbinder" -# CONFIG_ANDROID_BINDER_IPC_SELFTEST is not set -# CONFIG_LIBNVDIMM is not set -CONFIG_DAX=y -# CONFIG_DEV_DAX is not set -CONFIG_NVMEM=y - -# -# HW tracing support -# -CONFIG_STM=m -CONFIG_STM_DUMMY=m -CONFIG_STM_SOURCE_CONSOLE=m -# CONFIG_STM_SOURCE_HEARTBEAT is not set -# CONFIG_STM_SOURCE_FTRACE is not set -CONFIG_INTEL_TH=m -CONFIG_INTEL_TH_PCI=m -# CONFIG_INTEL_TH_ACPI is not set -CONFIG_INTEL_TH_GTH=m -CONFIG_INTEL_TH_STH=m -CONFIG_INTEL_TH_MSU=m -CONFIG_INTEL_TH_PTI=m -# CONFIG_INTEL_TH_DEBUG is not set -CONFIG_FPGA=m -# CONFIG_ALTERA_PR_IP_CORE is not set -# CONFIG_FPGA_MGR_ALTERA_CVP is not set -# CONFIG_FPGA_BRIDGE is not set -# CONFIG_FPGA_DFL is not set -CONFIG_PM_OPP=y -# CONFIG_UNISYS_VISORBUS is not set -# CONFIG_SIOX is not set -# CONFIG_SLIMBUS is not set - -# -# File systems -# -CONFIG_DCACHE_WORD_ACCESS=y -CONFIG_FS_IOMAP=y -CONFIG_EXT2_FS=m -CONFIG_EXT2_FS_XATTR=y -# CONFIG_EXT2_FS_POSIX_ACL is not set -CONFIG_EXT2_FS_SECURITY=y -CONFIG_EXT3_FS=m -CONFIG_EXT3_FS_POSIX_ACL=y -CONFIG_EXT3_FS_SECURITY=y -CONFIG_EXT4_FS=y -CONFIG_EXT4_FS_POSIX_ACL=y -CONFIG_EXT4_FS_SECURITY=y -CONFIG_EXT4_ENCRYPTION=y -CONFIG_EXT4_FS_ENCRYPTION=y -# CONFIG_EXT4_DEBUG is not set -CONFIG_JBD2=y -# CONFIG_JBD2_DEBUG is not set -CONFIG_FS_MBCACHE=y -CONFIG_REISERFS_FS=m -# CONFIG_REISERFS_CHECK is not set -CONFIG_REISERFS_PROC_INFO=y -CONFIG_REISERFS_FS_XATTR=y -CONFIG_REISERFS_FS_POSIX_ACL=y -CONFIG_REISERFS_FS_SECURITY=y -CONFIG_JFS_FS=m -CONFIG_JFS_POSIX_ACL=y -CONFIG_JFS_SECURITY=y -# CONFIG_JFS_DEBUG is not set -# CONFIG_JFS_STATISTICS is not set -CONFIG_XFS_FS=m -CONFIG_XFS_QUOTA=y -CONFIG_XFS_POSIX_ACL=y -# CONFIG_XFS_RT is not set -# CONFIG_XFS_ONLINE_SCRUB is not set -# CONFIG_XFS_WARN is not set -# CONFIG_XFS_DEBUG is not set -CONFIG_GFS2_FS=m -CONFIG_GFS2_FS_LOCKING_DLM=y -CONFIG_OCFS2_FS=m -CONFIG_OCFS2_FS_O2CB=m -CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m -# CONFIG_OCFS2_FS_STATS is not set -# CONFIG_OCFS2_DEBUG_MASKLOG is not set -# CONFIG_OCFS2_DEBUG_FS is not set -CONFIG_BTRFS_FS=m -CONFIG_BTRFS_FS_POSIX_ACL=y -# CONFIG_BTRFS_FS_CHECK_INTEGRITY is not set -# CONFIG_BTRFS_FS_RUN_SANITY_TESTS is not set -# CONFIG_BTRFS_DEBUG is not set -# CONFIG_BTRFS_ASSERT is not set -# CONFIG_BTRFS_FS_REF_VERIFY is not set -CONFIG_NILFS2_FS=m -CONFIG_F2FS_FS=m -CONFIG_F2FS_STAT_FS=y -CONFIG_F2FS_FS_XATTR=y -CONFIG_F2FS_FS_POSIX_ACL=y -# CONFIG_F2FS_FS_SECURITY is not set -# CONFIG_F2FS_CHECK_FS is not set -# CONFIG_F2FS_FS_ENCRYPTION is not set -CONFIG_F2FS_IO_TRACE=y -# CONFIG_F2FS_FAULT_INJECTION is not set -CONFIG_FS_DAX=y -CONFIG_FS_DAX_PMD=y -CONFIG_FS_POSIX_ACL=y -CONFIG_EXPORTFS=y -# CONFIG_EXPORTFS_BLOCK_OPS is not set -CONFIG_FILE_LOCKING=y -CONFIG_MANDATORY_FILE_LOCKING=y -CONFIG_FS_ENCRYPTION=y -CONFIG_FSNOTIFY=y -CONFIG_DNOTIFY=y -CONFIG_INOTIFY_USER=y -CONFIG_FANOTIFY=y -CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y -CONFIG_QUOTA=y -CONFIG_QUOTA_NETLINK_INTERFACE=y -# CONFIG_PRINT_QUOTA_WARNING is not set -# CONFIG_QUOTA_DEBUG is not set -CONFIG_QUOTA_TREE=y -# CONFIG_QFMT_V1 is not set -CONFIG_QFMT_V2=y -CONFIG_QUOTACTL=y -CONFIG_QUOTACTL_COMPAT=y -CONFIG_AUTOFS4_FS=y -CONFIG_AUTOFS_FS=y -CONFIG_FUSE_FS=m -CONFIG_CUSE=m -CONFIG_OVERLAY_FS=y -# CONFIG_OVERLAY_FS_REDIRECT_DIR is not set -CONFIG_OVERLAY_FS_REDIRECT_ALWAYS_FOLLOW=y -# CONFIG_OVERLAY_FS_INDEX is not set -# CONFIG_OVERLAY_FS_XINO_AUTO is not set -# CONFIG_OVERLAY_FS_METACOPY is not set - -# -# Caches -# -CONFIG_FSCACHE=m -CONFIG_FSCACHE_STATS=y -# CONFIG_FSCACHE_HISTOGRAM is not set -# CONFIG_FSCACHE_DEBUG is not set -CONFIG_FSCACHE_OBJECT_LIST=y -CONFIG_CACHEFILES=m -# CONFIG_CACHEFILES_DEBUG is not set -# CONFIG_CACHEFILES_HISTOGRAM is not set - -# -# CD-ROM/DVD Filesystems -# -CONFIG_ISO9660_FS=y -CONFIG_JOLIET=y -CONFIG_ZISOFS=y -CONFIG_UDF_FS=m - -# -# DOS/FAT/NT Filesystems -# -CONFIG_FAT_FS=m -CONFIG_MSDOS_FS=m -CONFIG_VFAT_FS=m -CONFIG_FAT_DEFAULT_CODEPAGE=437 -CONFIG_FAT_DEFAULT_IOCHARSET="ascii" -# CONFIG_FAT_DEFAULT_UTF8 is not set -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -CONFIG_PROC_KCORE=y -CONFIG_PROC_VMCORE=y -# CONFIG_PROC_VMCORE_DEVICE_DUMP is not set -CONFIG_PROC_SYSCTL=y -CONFIG_PROC_PAGE_MONITOR=y -# CONFIG_PROC_CHILDREN is not set -CONFIG_KERNFS=y -CONFIG_SYSFS=y -CONFIG_TMPFS=y -CONFIG_TMPFS_POSIX_ACL=y -CONFIG_TMPFS_XATTR=y -CONFIG_HUGETLBFS=y -CONFIG_HUGETLB_PAGE=y -CONFIG_MEMFD_CREATE=y -CONFIG_ARCH_HAS_GIGANTIC_PAGE=y -CONFIG_CONFIGFS_FS=y -CONFIG_EFIVAR_FS=y -CONFIG_MISC_FILESYSTEMS=y -# CONFIG_ORANGEFS_FS is not set -# CONFIG_ADFS_FS is not set -CONFIG_AFFS_FS=m -CONFIG_ECRYPT_FS=m -CONFIG_ECRYPT_FS_MESSAGING=y -CONFIG_HFS_FS=m -CONFIG_HFSPLUS_FS=m -CONFIG_BEFS_FS=m -# CONFIG_BEFS_DEBUG is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_JFFS2_FS is not set -CONFIG_UBIFS_FS=m -# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set -CONFIG_UBIFS_FS_LZO=y -CONFIG_UBIFS_FS_ZLIB=y -# CONFIG_UBIFS_ATIME_SUPPORT is not set -CONFIG_UBIFS_FS_XATTR=y -# CONFIG_UBIFS_FS_ENCRYPTION is not set -CONFIG_UBIFS_FS_SECURITY=y -CONFIG_CRAMFS=m -CONFIG_CRAMFS_BLOCKDEV=y -# CONFIG_CRAMFS_MTD is not set -CONFIG_SQUASHFS=m -# CONFIG_SQUASHFS_FILE_CACHE is not set -CONFIG_SQUASHFS_FILE_DIRECT=y -# CONFIG_SQUASHFS_DECOMP_SINGLE is not set -# CONFIG_SQUASHFS_DECOMP_MULTI is not set -CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y -CONFIG_SQUASHFS_XATTR=y -CONFIG_SQUASHFS_ZLIB=y -# CONFIG_SQUASHFS_LZ4 is not set -CONFIG_SQUASHFS_LZO=y -CONFIG_SQUASHFS_XZ=y -# CONFIG_SQUASHFS_ZSTD is not set -# CONFIG_SQUASHFS_4K_DEVBLK_SIZE is not set -# CONFIG_SQUASHFS_EMBEDDED is not set -CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 -# CONFIG_VXFS_FS is not set -CONFIG_MINIX_FS=m -# CONFIG_OMFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_QNX6FS_FS is not set -CONFIG_ROMFS_FS=m -CONFIG_ROMFS_BACKED_BY_BLOCK=y -# CONFIG_ROMFS_BACKED_BY_MTD is not set -# CONFIG_ROMFS_BACKED_BY_BOTH is not set -CONFIG_ROMFS_ON_BLOCK=y -CONFIG_PSTORE=y -CONFIG_PSTORE_DEFLATE_COMPRESS=y -# CONFIG_PSTORE_LZO_COMPRESS is not set -# CONFIG_PSTORE_LZ4_COMPRESS is not set -# CONFIG_PSTORE_LZ4HC_COMPRESS is not set -# CONFIG_PSTORE_842_COMPRESS is not set -# CONFIG_PSTORE_ZSTD_COMPRESS is not set -CONFIG_PSTORE_COMPRESS=y -CONFIG_PSTORE_DEFLATE_COMPRESS_DEFAULT=y -CONFIG_PSTORE_COMPRESS_DEFAULT="deflate" -CONFIG_PSTORE_CONSOLE=y -CONFIG_PSTORE_PMSG=y -CONFIG_PSTORE_FTRACE=y -CONFIG_PSTORE_RAM=m -CONFIG_SYSV_FS=m -CONFIG_UFS_FS=m -# CONFIG_UFS_FS_WRITE is not set -# CONFIG_UFS_DEBUG is not set -# CONFIG_EXOFS_FS is not set -CONFIG_AUFS_FS=y -# CONFIG_AUFS_BRANCH_MAX_127 is not set -# CONFIG_AUFS_BRANCH_MAX_511 is not set -# CONFIG_AUFS_BRANCH_MAX_1023 is not set -CONFIG_AUFS_BRANCH_MAX_32767=y -CONFIG_AUFS_SBILIST=y -CONFIG_AUFS_HNOTIFY=y -CONFIG_AUFS_HFSNOTIFY=y -CONFIG_AUFS_EXPORT=y -CONFIG_AUFS_INO_T_64=y -CONFIG_AUFS_XATTR=y -CONFIG_AUFS_FHSM=y -CONFIG_AUFS_RDU=y -# CONFIG_AUFS_DIRREN is not set -CONFIG_AUFS_SHWH=y -CONFIG_AUFS_BR_RAMFS=y -CONFIG_AUFS_BR_FUSE=y -CONFIG_AUFS_POLL=y -CONFIG_AUFS_BR_HFSPLUS=y -CONFIG_AUFS_BDEV_LOOP=y -CONFIG_AUFS_DEBUG=y -CONFIG_AUFS_MAGIC_SYSRQ=y -CONFIG_NETWORK_FILESYSTEMS=y -CONFIG_NFS_FS=m -CONFIG_NFS_V2=m -CONFIG_NFS_V3=m -CONFIG_NFS_V3_ACL=y -CONFIG_NFS_V4=m -CONFIG_NFS_SWAP=y -CONFIG_NFS_V4_1=y -# CONFIG_NFS_V4_2 is not set -CONFIG_PNFS_FILE_LAYOUT=m -CONFIG_PNFS_BLOCK=m -CONFIG_PNFS_FLEXFILE_LAYOUT=m -CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN="kernel.org" -# CONFIG_NFS_V4_1_MIGRATION is not set -CONFIG_NFS_FSCACHE=y -# CONFIG_NFS_USE_LEGACY_DNS is not set -CONFIG_NFS_USE_KERNEL_DNS=y -CONFIG_NFS_DEBUG=y -CONFIG_NFSD=m -CONFIG_NFSD_V2_ACL=y -CONFIG_NFSD_V3=y -CONFIG_NFSD_V3_ACL=y -CONFIG_NFSD_V4=y -# CONFIG_NFSD_BLOCKLAYOUT is not set -# CONFIG_NFSD_SCSILAYOUT is not set -# CONFIG_NFSD_FLEXFILELAYOUT is not set -# CONFIG_NFSD_V4_SECURITY_LABEL is not set -CONFIG_GRACE_PERIOD=m -CONFIG_LOCKD=m -CONFIG_LOCKD_V4=y -CONFIG_NFS_ACL_SUPPORT=m -CONFIG_NFS_COMMON=y -CONFIG_SUNRPC=m -CONFIG_SUNRPC_GSS=m -CONFIG_SUNRPC_BACKCHANNEL=y -CONFIG_SUNRPC_SWAP=y -CONFIG_RPCSEC_GSS_KRB5=m -CONFIG_SUNRPC_DEBUG=y -CONFIG_SUNRPC_XPRT_RDMA=m -CONFIG_CEPH_FS=m -# CONFIG_CEPH_FSCACHE is not set -CONFIG_CEPH_FS_POSIX_ACL=y -CONFIG_CIFS=m -# CONFIG_CIFS_STATS2 is not set -CONFIG_CIFS_ALLOW_INSECURE_LEGACY=y -CONFIG_CIFS_WEAK_PW_HASH=y -CONFIG_CIFS_UPCALL=y -CONFIG_CIFS_XATTR=y -# CONFIG_CIFS_POSIX is not set -CONFIG_CIFS_ACL=y -# CONFIG_CIFS_DEBUG is not set -CONFIG_CIFS_DFS_UPCALL=y -# CONFIG_CIFS_SMB_DIRECT is not set -CONFIG_CIFS_FSCACHE=y -CONFIG_CODA_FS=m -# CONFIG_AFS_FS is not set -CONFIG_9P_FS=m -CONFIG_9P_FSCACHE=y -CONFIG_9P_FS_POSIX_ACL=y -# CONFIG_9P_FS_SECURITY is not set -CONFIG_NLS=y -CONFIG_NLS_DEFAULT="utf8" -CONFIG_NLS_CODEPAGE_437=y -CONFIG_NLS_CODEPAGE_737=m -CONFIG_NLS_CODEPAGE_775=m -CONFIG_NLS_CODEPAGE_850=m -CONFIG_NLS_CODEPAGE_852=m -CONFIG_NLS_CODEPAGE_855=m -CONFIG_NLS_CODEPAGE_857=m -CONFIG_NLS_CODEPAGE_860=m -CONFIG_NLS_CODEPAGE_861=m -CONFIG_NLS_CODEPAGE_862=m -CONFIG_NLS_CODEPAGE_863=m -CONFIG_NLS_CODEPAGE_864=m -CONFIG_NLS_CODEPAGE_865=m -CONFIG_NLS_CODEPAGE_866=m -CONFIG_NLS_CODEPAGE_869=m -CONFIG_NLS_CODEPAGE_936=m -CONFIG_NLS_CODEPAGE_950=m -CONFIG_NLS_CODEPAGE_932=m -CONFIG_NLS_CODEPAGE_949=m -CONFIG_NLS_CODEPAGE_874=m -CONFIG_NLS_ISO8859_8=m -CONFIG_NLS_CODEPAGE_1250=m -CONFIG_NLS_CODEPAGE_1251=m -CONFIG_NLS_ASCII=y -CONFIG_NLS_ISO8859_1=m -CONFIG_NLS_ISO8859_2=m -CONFIG_NLS_ISO8859_3=m -CONFIG_NLS_ISO8859_4=m -CONFIG_NLS_ISO8859_5=m -CONFIG_NLS_ISO8859_6=m -CONFIG_NLS_ISO8859_7=m -CONFIG_NLS_ISO8859_9=m -CONFIG_NLS_ISO8859_13=m -CONFIG_NLS_ISO8859_14=m -CONFIG_NLS_ISO8859_15=m -CONFIG_NLS_KOI8_R=m -CONFIG_NLS_KOI8_U=m -CONFIG_NLS_MAC_ROMAN=m -CONFIG_NLS_MAC_CELTIC=m -CONFIG_NLS_MAC_CENTEURO=m -CONFIG_NLS_MAC_CROATIAN=m -CONFIG_NLS_MAC_CYRILLIC=m -CONFIG_NLS_MAC_GAELIC=m -CONFIG_NLS_MAC_GREEK=m -CONFIG_NLS_MAC_ICELAND=m -CONFIG_NLS_MAC_INUIT=m -CONFIG_NLS_MAC_ROMANIAN=m -CONFIG_NLS_MAC_TURKISH=m -CONFIG_NLS_UTF8=m -CONFIG_DLM=m -CONFIG_DLM_DEBUG=y - -# -# Security options -# -CONFIG_KEYS=y -CONFIG_KEYS_COMPAT=y -# CONFIG_PERSISTENT_KEYRINGS is not set -# CONFIG_BIG_KEYS is not set -CONFIG_TRUSTED_KEYS=m -CONFIG_ENCRYPTED_KEYS=y -# CONFIG_KEY_DH_OPERATIONS is not set -# CONFIG_SECURITY_DMESG_RESTRICT is not set -CONFIG_SECURITY=y -CONFIG_SECURITYFS=y -CONFIG_SECURITY_NETWORK=y -CONFIG_PAGE_TABLE_ISOLATION=y -# CONFIG_SECURITY_INFINIBAND is not set -CONFIG_SECURITY_NETWORK_XFRM=y -CONFIG_SECURITY_PATH=y -CONFIG_INTEL_TXT=y -CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y -# CONFIG_HARDENED_USERCOPY is not set -# CONFIG_FORTIFY_SOURCE is not set -# CONFIG_STATIC_USERMODEHELPER is not set -# CONFIG_SECURITY_SELINUX is not set -# CONFIG_SECURITY_SMACK is not set -# CONFIG_SECURITY_TOMOYO is not set -CONFIG_SECURITY_APPARMOR=y -CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE=1 -CONFIG_SECURITY_APPARMOR_HASH=y -CONFIG_SECURITY_APPARMOR_HASH_DEFAULT=y -# CONFIG_SECURITY_APPARMOR_DEBUG is not set -# CONFIG_SECURITY_LOADPIN is not set -# CONFIG_SECURITY_YAMA is not set -CONFIG_INTEGRITY=y -# CONFIG_INTEGRITY_SIGNATURE is not set -CONFIG_INTEGRITY_AUDIT=y -# CONFIG_IMA is not set -# CONFIG_EVM is not set -CONFIG_DEFAULT_SECURITY_APPARMOR=y -# CONFIG_DEFAULT_SECURITY_DAC is not set -CONFIG_DEFAULT_SECURITY="apparmor" -CONFIG_XOR_BLOCKS=m -CONFIG_ASYNC_CORE=m -CONFIG_ASYNC_MEMCPY=m -CONFIG_ASYNC_XOR=m -CONFIG_ASYNC_PQ=m -CONFIG_ASYNC_RAID6_RECOV=m -CONFIG_CRYPTO=y - -# -# Crypto core or helper -# -CONFIG_CRYPTO_ALGAPI=y -CONFIG_CRYPTO_ALGAPI2=y -CONFIG_CRYPTO_AEAD=y -CONFIG_CRYPTO_AEAD2=y -CONFIG_CRYPTO_BLKCIPHER=y -CONFIG_CRYPTO_BLKCIPHER2=y -CONFIG_CRYPTO_HASH=y -CONFIG_CRYPTO_HASH2=y -CONFIG_CRYPTO_RNG=y -CONFIG_CRYPTO_RNG2=y -CONFIG_CRYPTO_RNG_DEFAULT=y -CONFIG_CRYPTO_AKCIPHER2=y -CONFIG_CRYPTO_AKCIPHER=y -CONFIG_CRYPTO_KPP2=y -CONFIG_CRYPTO_KPP=m -CONFIG_CRYPTO_ACOMP2=y -CONFIG_CRYPTO_RSA=y -CONFIG_CRYPTO_DH=m -CONFIG_CRYPTO_ECDH=m -CONFIG_CRYPTO_MANAGER=y -CONFIG_CRYPTO_MANAGER2=y -CONFIG_CRYPTO_USER=m -# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set -CONFIG_CRYPTO_GF128MUL=y -CONFIG_CRYPTO_NULL=y -CONFIG_CRYPTO_NULL2=y -CONFIG_CRYPTO_PCRYPT=m -CONFIG_CRYPTO_WORKQUEUE=y -CONFIG_CRYPTO_CRYPTD=y -CONFIG_CRYPTO_MCRYPTD=m -CONFIG_CRYPTO_AUTHENC=m -CONFIG_CRYPTO_TEST=m -CONFIG_CRYPTO_SIMD=m -CONFIG_CRYPTO_GLUE_HELPER_X86=m -CONFIG_CRYPTO_ENGINE=m - -# -# Authenticated Encryption with Associated Data -# -CONFIG_CRYPTO_CCM=m -CONFIG_CRYPTO_GCM=m -# CONFIG_CRYPTO_CHACHA20POLY1305 is not set -# CONFIG_CRYPTO_AEGIS128 is not set -# CONFIG_CRYPTO_AEGIS128L is not set -# CONFIG_CRYPTO_AEGIS256 is not set -# CONFIG_CRYPTO_AEGIS128_AESNI_SSE2 is not set -# CONFIG_CRYPTO_AEGIS128L_AESNI_SSE2 is not set -# CONFIG_CRYPTO_AEGIS256_AESNI_SSE2 is not set -# CONFIG_CRYPTO_MORUS640 is not set -# CONFIG_CRYPTO_MORUS640_SSE2 is not set -# CONFIG_CRYPTO_MORUS1280 is not set -# CONFIG_CRYPTO_MORUS1280_SSE2 is not set -# CONFIG_CRYPTO_MORUS1280_AVX2 is not set -CONFIG_CRYPTO_SEQIV=y -CONFIG_CRYPTO_ECHAINIV=m - -# -# Block modes -# -CONFIG_CRYPTO_CBC=y -# CONFIG_CRYPTO_CFB is not set -CONFIG_CRYPTO_CTR=y -CONFIG_CRYPTO_CTS=y -CONFIG_CRYPTO_ECB=y -CONFIG_CRYPTO_LRW=y -CONFIG_CRYPTO_PCBC=m -CONFIG_CRYPTO_XTS=y -CONFIG_CRYPTO_KEYWRAP=m - -# -# Hash modes -# -CONFIG_CRYPTO_CMAC=m -CONFIG_CRYPTO_HMAC=y -CONFIG_CRYPTO_XCBC=m -CONFIG_CRYPTO_VMAC=m - -# -# Digest -# -CONFIG_CRYPTO_CRC32C=y -CONFIG_CRYPTO_CRC32C_INTEL=m -CONFIG_CRYPTO_CRC32=y -CONFIG_CRYPTO_CRC32_PCLMUL=m -CONFIG_CRYPTO_CRCT10DIF=y -# CONFIG_CRYPTO_CRCT10DIF_PCLMUL is not set -CONFIG_CRYPTO_GHASH=m -CONFIG_CRYPTO_POLY1305=m -CONFIG_CRYPTO_POLY1305_X86_64=m -CONFIG_CRYPTO_MD4=m -CONFIG_CRYPTO_MD5=y -CONFIG_CRYPTO_MICHAEL_MIC=m -CONFIG_CRYPTO_RMD128=m -CONFIG_CRYPTO_RMD160=m -CONFIG_CRYPTO_RMD256=m -CONFIG_CRYPTO_RMD320=m -CONFIG_CRYPTO_SHA1=y -CONFIG_CRYPTO_SHA1_SSSE3=m -CONFIG_CRYPTO_SHA256_SSSE3=m -CONFIG_CRYPTO_SHA512_SSSE3=m -# CONFIG_CRYPTO_SHA1_MB is not set -CONFIG_CRYPTO_SHA256_MB=m -CONFIG_CRYPTO_SHA512_MB=m -CONFIG_CRYPTO_SHA256=y -CONFIG_CRYPTO_SHA512=m -CONFIG_CRYPTO_SHA3=m -# CONFIG_CRYPTO_SM3 is not set -CONFIG_CRYPTO_TGR192=m -CONFIG_CRYPTO_WP512=m -CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL=m - -# -# Ciphers -# -CONFIG_CRYPTO_AES=y -# CONFIG_CRYPTO_AES_TI is not set -CONFIG_CRYPTO_AES_X86_64=m -CONFIG_CRYPTO_AES_NI_INTEL=m -CONFIG_CRYPTO_ANUBIS=m -CONFIG_CRYPTO_ARC4=m -CONFIG_CRYPTO_BLOWFISH=m -CONFIG_CRYPTO_BLOWFISH_COMMON=m -CONFIG_CRYPTO_BLOWFISH_X86_64=m -CONFIG_CRYPTO_CAMELLIA=m -CONFIG_CRYPTO_CAMELLIA_X86_64=m -CONFIG_CRYPTO_CAMELLIA_AESNI_AVX_X86_64=m -CONFIG_CRYPTO_CAMELLIA_AESNI_AVX2_X86_64=m -CONFIG_CRYPTO_CAST_COMMON=m -CONFIG_CRYPTO_CAST5=m -CONFIG_CRYPTO_CAST5_AVX_X86_64=m -CONFIG_CRYPTO_CAST6=m -CONFIG_CRYPTO_CAST6_AVX_X86_64=m -CONFIG_CRYPTO_DES=m -CONFIG_CRYPTO_DES3_EDE_X86_64=m -CONFIG_CRYPTO_FCRYPT=m -CONFIG_CRYPTO_KHAZAD=m -CONFIG_CRYPTO_SALSA20=m -CONFIG_CRYPTO_CHACHA20=m -CONFIG_CRYPTO_CHACHA20_X86_64=m -CONFIG_CRYPTO_SEED=m -CONFIG_CRYPTO_SERPENT=m -CONFIG_CRYPTO_SERPENT_SSE2_X86_64=m -CONFIG_CRYPTO_SERPENT_AVX_X86_64=m -CONFIG_CRYPTO_SERPENT_AVX2_X86_64=m -# CONFIG_CRYPTO_SM4 is not set -CONFIG_CRYPTO_TEA=m -CONFIG_CRYPTO_TWOFISH=m -CONFIG_CRYPTO_TWOFISH_COMMON=m -CONFIG_CRYPTO_TWOFISH_X86_64=m -CONFIG_CRYPTO_TWOFISH_X86_64_3WAY=m -CONFIG_CRYPTO_TWOFISH_AVX_X86_64=m - -# -# Compression -# -CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_LZO=y -# CONFIG_CRYPTO_842 is not set -CONFIG_CRYPTO_LZ4=m -CONFIG_CRYPTO_LZ4HC=m -# CONFIG_CRYPTO_ZSTD is not set - -# -# Random Number Generation -# -CONFIG_CRYPTO_ANSI_CPRNG=m -CONFIG_CRYPTO_DRBG_MENU=y -CONFIG_CRYPTO_DRBG_HMAC=y -# CONFIG_CRYPTO_DRBG_HASH is not set -# CONFIG_CRYPTO_DRBG_CTR is not set -CONFIG_CRYPTO_DRBG=y -CONFIG_CRYPTO_JITTERENTROPY=y -CONFIG_CRYPTO_USER_API=y -CONFIG_CRYPTO_USER_API_HASH=y -CONFIG_CRYPTO_USER_API_SKCIPHER=y -CONFIG_CRYPTO_USER_API_RNG=m -# CONFIG_CRYPTO_USER_API_AEAD is not set -CONFIG_CRYPTO_HASH_INFO=y -CONFIG_CRYPTO_HW=y -CONFIG_CRYPTO_DEV_PADLOCK=m -CONFIG_CRYPTO_DEV_PADLOCK_AES=m -CONFIG_CRYPTO_DEV_PADLOCK_SHA=m -CONFIG_CRYPTO_DEV_CCP=y -CONFIG_CRYPTO_DEV_CCP_DD=m -CONFIG_CRYPTO_DEV_SP_CCP=y -CONFIG_CRYPTO_DEV_CCP_CRYPTO=m -CONFIG_CRYPTO_DEV_SP_PSP=y -CONFIG_CRYPTO_DEV_QAT=m -CONFIG_CRYPTO_DEV_QAT_DH895xCC=m -# CONFIG_CRYPTO_DEV_QAT_C3XXX is not set -# CONFIG_CRYPTO_DEV_QAT_C62X is not set -CONFIG_CRYPTO_DEV_QAT_DH895xCCVF=m -# CONFIG_CRYPTO_DEV_QAT_C3XXXVF is not set -# CONFIG_CRYPTO_DEV_QAT_C62XVF is not set -# CONFIG_CRYPTO_DEV_NITROX_CNN55XX is not set -CONFIG_CRYPTO_DEV_CHELSIO=m -CONFIG_CRYPTO_DEV_VIRTIO=m -CONFIG_ASYMMETRIC_KEY_TYPE=y -CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y -CONFIG_X509_CERTIFICATE_PARSER=y -CONFIG_PKCS7_MESSAGE_PARSER=y -# CONFIG_PKCS7_TEST_KEY is not set -# CONFIG_SIGNED_PE_FILE_VERIFICATION is not set - -# -# Certificates for signature checking -# -CONFIG_SYSTEM_TRUSTED_KEYRING=y -CONFIG_SYSTEM_TRUSTED_KEYS="" -# CONFIG_SYSTEM_EXTRA_CERTIFICATE is not set -# CONFIG_SECONDARY_TRUSTED_KEYRING is not set -# CONFIG_SYSTEM_BLACKLIST_KEYRING is not set -CONFIG_BINARY_PRINTF=y - -# -# Library routines -# -CONFIG_RAID6_PQ=m -CONFIG_BITREVERSE=y -CONFIG_RATIONAL=y -CONFIG_GENERIC_STRNCPY_FROM_USER=y -CONFIG_GENERIC_STRNLEN_USER=y -CONFIG_GENERIC_NET_UTILS=y -CONFIG_GENERIC_FIND_FIRST_BIT=y -CONFIG_GENERIC_PCI_IOMAP=y -CONFIG_GENERIC_IOMAP=y -CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y -CONFIG_ARCH_HAS_FAST_MULTIPLIER=y -CONFIG_CRC_CCITT=y -CONFIG_CRC16=y -CONFIG_CRC_T10DIF=y -CONFIG_CRC_ITU_T=m -CONFIG_CRC32=y -# CONFIG_CRC32_SELFTEST is not set -CONFIG_CRC32_SLICEBY8=y -# CONFIG_CRC32_SLICEBY4 is not set -# CONFIG_CRC32_SARWATE is not set -# CONFIG_CRC32_BIT is not set -CONFIG_CRC64=m -# CONFIG_CRC4 is not set -# CONFIG_CRC7 is not set -CONFIG_LIBCRC32C=m -CONFIG_CRC8=m -CONFIG_XXHASH=m -# CONFIG_RANDOM32_SELFTEST is not set -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=y -CONFIG_LZO_COMPRESS=y -CONFIG_LZO_DECOMPRESS=y -CONFIG_LZ4_COMPRESS=m -CONFIG_LZ4HC_COMPRESS=m -CONFIG_LZ4_DECOMPRESS=y -CONFIG_ZSTD_COMPRESS=m -CONFIG_ZSTD_DECOMPRESS=m -CONFIG_XZ_DEC=y -CONFIG_XZ_DEC_X86=y -CONFIG_XZ_DEC_POWERPC=y -CONFIG_XZ_DEC_IA64=y -CONFIG_XZ_DEC_ARM=y -CONFIG_XZ_DEC_ARMTHUMB=y -CONFIG_XZ_DEC_SPARC=y -CONFIG_XZ_DEC_BCJ=y -# CONFIG_XZ_DEC_TEST is not set -CONFIG_DECOMPRESS_GZIP=y -CONFIG_DECOMPRESS_BZIP2=y -CONFIG_DECOMPRESS_LZMA=y -CONFIG_DECOMPRESS_XZ=y -CONFIG_DECOMPRESS_LZO=y -CONFIG_DECOMPRESS_LZ4=y -CONFIG_GENERIC_ALLOCATOR=y -CONFIG_REED_SOLOMON=m -CONFIG_REED_SOLOMON_ENC8=y -CONFIG_REED_SOLOMON_DEC8=y -CONFIG_TEXTSEARCH=y -CONFIG_TEXTSEARCH_KMP=m -CONFIG_TEXTSEARCH_BM=m -CONFIG_TEXTSEARCH_FSM=m -CONFIG_BTREE=y -CONFIG_INTERVAL_TREE=y -CONFIG_RADIX_TREE_MULTIORDER=y -CONFIG_ASSOCIATIVE_ARRAY=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT_MAP=y -CONFIG_HAS_DMA=y -CONFIG_NEED_SG_DMA_LENGTH=y -CONFIG_NEED_DMA_MAP_STATE=y -CONFIG_ARCH_DMA_ADDR_T_64BIT=y -CONFIG_DMA_DIRECT_OPS=y -CONFIG_DMA_VIRT_OPS=y -CONFIG_SWIOTLB=y -CONFIG_SGL_ALLOC=y -CONFIG_IOMMU_HELPER=y -CONFIG_CHECK_SIGNATURE=y -CONFIG_CPU_RMAP=y -CONFIG_DQL=y -CONFIG_GLOB=y -# CONFIG_GLOB_SELFTEST is not set -CONFIG_NLATTR=y -CONFIG_LRU_CACHE=m -CONFIG_CLZ_TAB=y -CONFIG_CORDIC=m -# CONFIG_DDR is not set -CONFIG_IRQ_POLL=y -CONFIG_MPILIB=y -CONFIG_OID_REGISTRY=y -CONFIG_UCS2_STRING=y -CONFIG_FONT_SUPPORT=y -# CONFIG_FONTS is not set -CONFIG_FONT_8x8=y -CONFIG_FONT_8x16=y -CONFIG_SG_POOL=y -CONFIG_ARCH_HAS_SG_CHAIN=y -CONFIG_ARCH_HAS_PMEM_API=y -CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE=y -CONFIG_ARCH_HAS_UACCESS_MCSAFE=y -CONFIG_SBITMAP=y -CONFIG_PARMAN=m -# CONFIG_STRING_SELFTEST is not set - -# -# Kernel hacking -# - -# -# printk and dmesg options -# -CONFIG_PRINTK_TIME=y -CONFIG_CONSOLE_LOGLEVEL_DEFAULT=7 -CONFIG_CONSOLE_LOGLEVEL_QUIET=4 -CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 -CONFIG_DYNAMIC_DEBUG=y - -# -# Compile-time checks and compiler options -# -CONFIG_ENABLE_MUST_CHECK=y -CONFIG_FRAME_WARN=2048 -CONFIG_STRIP_ASM_SYMS=y -CONFIG_UNUSED_SYMBOLS=y -CONFIG_DEBUG_FS=y -CONFIG_HEADERS_CHECK=y -CONFIG_DEBUG_SECTION_MISMATCH=y -CONFIG_SECTION_MISMATCH_WARN_ONLY=y -CONFIG_STACK_VALIDATION=y -CONFIG_MAGIC_SYSRQ=y -CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1 -CONFIG_MAGIC_SYSRQ_SERIAL=y -# CONFIG_DEBUG_KERNEL is not set - -# -# Memory Debugging -# -# CONFIG_PAGE_EXTENSION is not set -# CONFIG_PAGE_POISONING is not set -CONFIG_DEBUG_RODATA_TEST=y -CONFIG_HAVE_DEBUG_KMEMLEAK=y -CONFIG_ARCH_HAS_DEBUG_VIRTUAL=y -CONFIG_DEBUG_MEMORY_INIT=y -CONFIG_HAVE_DEBUG_STACKOVERFLOW=y -CONFIG_HAVE_ARCH_KASAN=y -# CONFIG_KASAN is not set -CONFIG_ARCH_HAS_KCOV=y -CONFIG_CC_HAS_SANCOV_TRACE_PC=y -# CONFIG_KCOV is not set - -# -# Debug Lockups and Hangs -# -CONFIG_HARDLOCKUP_CHECK_TIMESTAMP=y -# CONFIG_PANIC_ON_OOPS is not set -CONFIG_PANIC_ON_OOPS_VALUE=0 -CONFIG_PANIC_TIMEOUT=0 -CONFIG_SCHED_INFO=y -CONFIG_DEBUG_TIMEKEEPING=y - -# -# Lock Debugging (spinlocks, mutexes, etc...) -# -CONFIG_LOCK_DEBUGGING_SUPPORT=y -# CONFIG_WW_MUTEX_SELFTEST is not set -CONFIG_STACKTRACE=y -# CONFIG_WARN_ALL_UNSEEDED_RANDOM is not set -CONFIG_DEBUG_BUGVERBOSE=y - -# -# RCU Debugging -# -CONFIG_RCU_CPU_STALL_TIMEOUT=60 -CONFIG_FUNCTION_ERROR_INJECTION=y -CONFIG_USER_STACKTRACE_SUPPORT=y -CONFIG_NOP_TRACER=y -CONFIG_HAVE_FUNCTION_TRACER=y -CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y -CONFIG_HAVE_DYNAMIC_FTRACE=y -CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS=y -CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y -CONFIG_HAVE_SYSCALL_TRACEPOINTS=y -CONFIG_HAVE_FENTRY=y -CONFIG_HAVE_C_RECORDMCOUNT=y -CONFIG_TRACER_MAX_TRACE=y -CONFIG_TRACE_CLOCK=y -CONFIG_RING_BUFFER=y -CONFIG_EVENT_TRACING=y -CONFIG_CONTEXT_SWITCH_TRACER=y -CONFIG_RING_BUFFER_ALLOW_SWAP=y -CONFIG_TRACING=y -CONFIG_GENERIC_TRACER=y -CONFIG_TRACING_SUPPORT=y -CONFIG_FTRACE=y -CONFIG_FUNCTION_TRACER=y -CONFIG_FUNCTION_GRAPH_TRACER=y -# CONFIG_PREEMPTIRQ_EVENTS is not set -# CONFIG_IRQSOFF_TRACER is not set -CONFIG_SCHED_TRACER=y -# CONFIG_HWLAT_TRACER is not set -CONFIG_FTRACE_SYSCALLS=y -CONFIG_TRACER_SNAPSHOT=y -CONFIG_TRACER_SNAPSHOT_PER_CPU_SWAP=y -CONFIG_BRANCH_PROFILE_NONE=y -# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set -# CONFIG_PROFILE_ALL_BRANCHES is not set -CONFIG_STACK_TRACER=y -CONFIG_BLK_DEV_IO_TRACE=y -CONFIG_KPROBE_EVENTS=y -# CONFIG_KPROBE_EVENTS_ON_NOTRACE is not set -CONFIG_UPROBE_EVENTS=y -CONFIG_BPF_EVENTS=y -CONFIG_PROBE_EVENTS=y -CONFIG_DYNAMIC_FTRACE=y -CONFIG_DYNAMIC_FTRACE_WITH_REGS=y -CONFIG_FUNCTION_PROFILER=y -# CONFIG_BPF_KPROBE_OVERRIDE is not set -CONFIG_FTRACE_MCOUNT_RECORD=y -# CONFIG_FTRACE_STARTUP_TEST is not set -# CONFIG_MMIOTRACE is not set -# CONFIG_HIST_TRIGGERS is not set -# CONFIG_TRACEPOINT_BENCHMARK is not set -CONFIG_RING_BUFFER_BENCHMARK=m -# CONFIG_RING_BUFFER_STARTUP_TEST is not set -# CONFIG_PREEMPTIRQ_DELAY_TEST is not set -# CONFIG_TRACE_EVAL_MAP_FILE is not set -CONFIG_TRACING_EVENTS_GPIO=y -# CONFIG_PROVIDE_OHCI1394_DMA_INIT is not set -# CONFIG_DMA_API_DEBUG is not set -CONFIG_RUNTIME_TESTING_MENU=y -# CONFIG_LKDTM is not set -# CONFIG_TEST_LIST_SORT is not set -# CONFIG_TEST_SORT is not set -CONFIG_ATOMIC64_SELFTEST=y -CONFIG_ASYNC_RAID6_TEST=m -CONFIG_TEST_HEXDUMP=m -# CONFIG_TEST_STRING_HELPERS is not set -CONFIG_TEST_KSTRTOX=y -CONFIG_TEST_PRINTF=m -# CONFIG_TEST_BITMAP is not set -# CONFIG_TEST_BITFIELD is not set -# CONFIG_TEST_UUID is not set -# CONFIG_TEST_OVERFLOW is not set -# CONFIG_TEST_RHASHTABLE is not set -# CONFIG_TEST_HASH is not set -# CONFIG_TEST_IDA is not set -# CONFIG_TEST_PARMAN is not set -# CONFIG_TEST_LKM is not set -# CONFIG_TEST_USER_COPY is not set -# CONFIG_TEST_BPF is not set -# CONFIG_FIND_BIT_BENCHMARK is not set -# CONFIG_TEST_FIRMWARE is not set -# CONFIG_TEST_SYSCTL is not set -# CONFIG_TEST_UDELAY is not set -CONFIG_TEST_STATIC_KEYS=m -# CONFIG_TEST_KMOD is not set -# CONFIG_MEMTEST is not set -# CONFIG_BUG_ON_DATA_CORRUPTION is not set -# CONFIG_SAMPLES is not set -CONFIG_HAVE_ARCH_KGDB=y -CONFIG_ARCH_HAS_UBSAN_SANITIZE_ALL=y -# CONFIG_UBSAN is not set -CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y -CONFIG_STRICT_DEVMEM=y -# CONFIG_IO_STRICT_DEVMEM is not set -CONFIG_TRACE_IRQFLAGS_SUPPORT=y -CONFIG_EARLY_PRINTK_USB=y -# CONFIG_X86_VERBOSE_BOOTUP is not set -CONFIG_EARLY_PRINTK=y -CONFIG_EARLY_PRINTK_DBGP=y -# CONFIG_EARLY_PRINTK_EFI is not set -# CONFIG_EARLY_PRINTK_USB_XDBC is not set -# CONFIG_EFI_PGT_DUMP is not set -# CONFIG_DEBUG_WX is not set -CONFIG_DOUBLEFAULT=y -CONFIG_HAVE_MMIOTRACE_SUPPORT=y -CONFIG_IO_DELAY_TYPE_0X80=0 -CONFIG_IO_DELAY_TYPE_0XED=1 -CONFIG_IO_DELAY_TYPE_UDELAY=2 -CONFIG_IO_DELAY_TYPE_NONE=3 -CONFIG_IO_DELAY_0X80=y -# CONFIG_IO_DELAY_0XED is not set -# CONFIG_IO_DELAY_UDELAY is not set -# CONFIG_IO_DELAY_NONE is not set -CONFIG_DEFAULT_IO_DELAY_TYPE=0 -CONFIG_OPTIMIZE_INLINING=y -# CONFIG_PUNIT_ATOM_DEBUG is not set -CONFIG_UNWINDER_ORC=y -# CONFIG_UNWINDER_FRAME_POINTER is not set +# +# Automatically generated file; DO NOT EDIT. +# Linux/x86_64 5.4.6 Kernel Configuration +# + +# +# Compiler: gcc (Pisi Linux) 9.2.1 20191214 +# +CONFIG_CC_IS_GCC=y +CONFIG_GCC_VERSION=90201 +CONFIG_CLANG_VERSION=0 +CONFIG_CC_CAN_LINK=y +CONFIG_CC_HAS_ASM_GOTO=y +CONFIG_CC_HAS_ASM_INLINE=y +CONFIG_CC_HAS_WARN_MAYBE_UNINITIALIZED=y +CONFIG_IRQ_WORK=y +CONFIG_BUILDTIME_EXTABLE_SORT=y +CONFIG_THREAD_INFO_IN_TASK=y + +# +# General setup +# +CONFIG_INIT_ENV_ARG_LIMIT=32 +# CONFIG_COMPILE_TEST is not set +# CONFIG_HEADER_TEST is not set +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_BUILD_SALT="" +CONFIG_HAVE_KERNEL_GZIP=y +CONFIG_HAVE_KERNEL_BZIP2=y +CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_XZ=y +CONFIG_HAVE_KERNEL_LZO=y +CONFIG_HAVE_KERNEL_LZ4=y +# CONFIG_KERNEL_GZIP is not set +# CONFIG_KERNEL_BZIP2 is not set +# CONFIG_KERNEL_LZMA is not set +CONFIG_KERNEL_XZ=y +# CONFIG_KERNEL_LZO is not set +# CONFIG_KERNEL_LZ4 is not set +CONFIG_DEFAULT_HOSTNAME="(none)" +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_POSIX_MQUEUE=y +CONFIG_POSIX_MQUEUE_SYSCTL=y +CONFIG_CROSS_MEMORY_ATTACH=y +# CONFIG_USELIB is not set +CONFIG_AUDIT=y +CONFIG_HAVE_ARCH_AUDITSYSCALL=y +CONFIG_AUDITSYSCALL=y + +# +# IRQ subsystem +# +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y +CONFIG_GENERIC_PENDING_IRQ=y +CONFIG_GENERIC_IRQ_MIGRATION=y +CONFIG_GENERIC_IRQ_CHIP=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_DOMAIN_HIERARCHY=y +CONFIG_GENERIC_MSI_IRQ=y +CONFIG_GENERIC_MSI_IRQ_DOMAIN=y +CONFIG_GENERIC_IRQ_MATRIX_ALLOCATOR=y +CONFIG_GENERIC_IRQ_RESERVATION_MODE=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_SPARSE_IRQ=y +# CONFIG_GENERIC_IRQ_DEBUGFS is not set +# end of IRQ subsystem + +CONFIG_CLOCKSOURCE_WATCHDOG=y +CONFIG_ARCH_CLOCKSOURCE_DATA=y +CONFIG_ARCH_CLOCKSOURCE_INIT=y +CONFIG_CLOCKSOURCE_VALIDATE_LAST_CYCLE=y +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y +CONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST=y +CONFIG_GENERIC_CMOS_UPDATE=y + +# +# Timers subsystem +# +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ_COMMON=y +# CONFIG_HZ_PERIODIC is not set +# CONFIG_NO_HZ_IDLE is not set +CONFIG_NO_HZ_FULL=y +CONFIG_CONTEXT_TRACKING=y +# CONFIG_CONTEXT_TRACKING_FORCE is not set +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +# end of Timers subsystem + +# CONFIG_PREEMPT_NONE is not set +CONFIG_PREEMPT_VOLUNTARY=y +# CONFIG_PREEMPT is not set + +# +# CPU/Task time and stats accounting +# +CONFIG_VIRT_CPU_ACCOUNTING=y +CONFIG_VIRT_CPU_ACCOUNTING_GEN=y +# CONFIG_IRQ_TIME_ACCOUNTING is not set +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_TASK_XACCT=y +CONFIG_TASK_IO_ACCOUNTING=y +# CONFIG_PSI is not set +# end of CPU/Task time and stats accounting + +CONFIG_CPU_ISOLATION=y + +# +# RCU Subsystem +# +CONFIG_TREE_RCU=y +# CONFIG_RCU_EXPERT is not set +CONFIG_SRCU=y +CONFIG_TREE_SRCU=y +CONFIG_TASKS_RCU=y +CONFIG_RCU_STALL_COMMON=y +CONFIG_RCU_NEED_SEGCBLIST=y +CONFIG_RCU_NOCB_CPU=y +# end of RCU Subsystem + +CONFIG_BUILD_BIN2C=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +# CONFIG_IKHEADERS is not set +CONFIG_LOG_BUF_SHIFT=17 +CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 +CONFIG_PRINTK_SAFE_LOG_BUF_SHIFT=13 +CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y + +# +# Scheduler features +# +# CONFIG_UCLAMP_TASK is not set +# end of Scheduler features + +CONFIG_ARCH_SUPPORTS_NUMA_BALANCING=y +CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH=y +CONFIG_ARCH_SUPPORTS_INT128=y +# CONFIG_NUMA_BALANCING is not set +CONFIG_CGROUPS=y +CONFIG_PAGE_COUNTER=y +CONFIG_MEMCG=y +CONFIG_MEMCG_SWAP=y +# CONFIG_MEMCG_SWAP_ENABLED is not set +CONFIG_MEMCG_KMEM=y +CONFIG_BLK_CGROUP=y +CONFIG_CGROUP_WRITEBACK=y +CONFIG_CGROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +CONFIG_CFS_BANDWIDTH=y +# CONFIG_RT_GROUP_SCHED is not set +# CONFIG_CGROUP_PIDS is not set +# CONFIG_CGROUP_RDMA is not set +CONFIG_CGROUP_FREEZER=y +# CONFIG_CGROUP_HUGETLB is not set +CONFIG_CPUSETS=y +CONFIG_PROC_PID_CPUSET=y +CONFIG_CGROUP_DEVICE=y +CONFIG_CGROUP_CPUACCT=y +# CONFIG_CGROUP_PERF is not set +CONFIG_CGROUP_BPF=y +# CONFIG_CGROUP_DEBUG is not set +CONFIG_SOCK_CGROUP_DATA=y +CONFIG_NAMESPACES=y +CONFIG_UTS_NS=y +CONFIG_IPC_NS=y +CONFIG_USER_NS=y +CONFIG_PID_NS=y +CONFIG_NET_NS=y +CONFIG_CHECKPOINT_RESTORE=y +CONFIG_SCHED_AUTOGROUP=y +# CONFIG_SYSFS_DEPRECATED is not set +CONFIG_RELAY=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +CONFIG_RD_BZIP2=y +CONFIG_RD_LZMA=y +CONFIG_RD_XZ=y +CONFIG_RD_LZO=y +CONFIG_RD_LZ4=y +CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y +CONFIG_HAVE_UID16=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +CONFIG_HAVE_PCSPKR_PLATFORM=y +CONFIG_BPF=y +CONFIG_EXPERT=y +CONFIG_UID16=y +CONFIG_MULTIUSER=y +CONFIG_SGETMASK_SYSCALL=y +# CONFIG_SYSFS_SYSCALL is not set +CONFIG_SYSCTL_SYSCALL=y +CONFIG_FHANDLE=y +CONFIG_POSIX_TIMERS=y +CONFIG_PRINTK=y +CONFIG_PRINTK_NMI=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_PCSPKR_PLATFORM=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_FUTEX_PI=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_IO_URING=y +CONFIG_ADVISE_SYSCALLS=y +CONFIG_MEMBARRIER=y +CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_ALL=y +CONFIG_KALLSYMS_ABSOLUTE_PERCPU=y +CONFIG_KALLSYMS_BASE_RELATIVE=y +CONFIG_BPF_SYSCALL=y +CONFIG_BPF_JIT_ALWAYS_ON=y +# CONFIG_USERFAULTFD is not set +CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y +CONFIG_RSEQ=y +# CONFIG_DEBUG_RSEQ is not set +CONFIG_EMBEDDED=y +CONFIG_HAVE_PERF_EVENTS=y +# CONFIG_PC104 is not set + +# +# Kernel Performance Events And Counters +# +CONFIG_PERF_EVENTS=y +# CONFIG_DEBUG_PERF_USE_VMALLOC is not set +# end of Kernel Performance Events And Counters + +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLUB_DEBUG=y +# CONFIG_SLUB_MEMCG_SYSFS_ON is not set +# CONFIG_COMPAT_BRK is not set +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SLOB is not set +# CONFIG_SLAB_MERGE_DEFAULT is not set +CONFIG_SLAB_FREELIST_RANDOM=y +# CONFIG_SLAB_FREELIST_HARDENED is not set +CONFIG_SHUFFLE_PAGE_ALLOCATOR=y +CONFIG_SLUB_CPU_PARTIAL=y +CONFIG_SYSTEM_DATA_VERIFICATION=y +CONFIG_PROFILING=y +CONFIG_TRACEPOINTS=y +# end of General setup + +CONFIG_64BIT=y +CONFIG_X86_64=y +CONFIG_X86=y +CONFIG_INSTRUCTION_DECODER=y +CONFIG_OUTPUT_FORMAT="elf64-x86-64" +CONFIG_ARCH_DEFCONFIG="arch/x86/configs/x86_64_defconfig" +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_MMU=y +CONFIG_ARCH_MMAP_RND_BITS_MIN=28 +CONFIG_ARCH_MMAP_RND_BITS_MAX=32 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=8 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=16 +CONFIG_GENERIC_ISA_DMA=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_ARCH_HAS_CPU_RELAX=y +CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y +CONFIG_ARCH_HAS_FILTER_PGPROT=y +CONFIG_HAVE_SETUP_PER_CPU_AREA=y +CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y +CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARCH_WANT_GENERAL_HUGETLB=y +CONFIG_ZONE_DMA32=y +CONFIG_AUDIT_ARCH=y +CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y +CONFIG_HAVE_INTEL_TXT=y +CONFIG_X86_64_SMP=y +CONFIG_ARCH_SUPPORTS_UPROBES=y +CONFIG_FIX_EARLYCON_MEM=y +CONFIG_PGTABLE_LEVELS=4 +CONFIG_CC_HAS_SANE_STACKPROTECTOR=y + +# +# Processor type and features +# +CONFIG_ZONE_DMA=y +CONFIG_SMP=y +CONFIG_X86_FEATURE_NAMES=y +CONFIG_X86_X2APIC=y +CONFIG_X86_MPPARSE=y +# CONFIG_GOLDFISH is not set +CONFIG_RETPOLINE=y +CONFIG_X86_CPU_RESCTRL=y +CONFIG_X86_EXTENDED_PLATFORM=y +# CONFIG_X86_NUMACHIP is not set +# CONFIG_X86_VSMP is not set +# CONFIG_X86_UV is not set +# CONFIG_X86_GOLDFISH is not set +# CONFIG_X86_INTEL_MID is not set +CONFIG_X86_INTEL_LPSS=y +CONFIG_X86_AMD_PLATFORM_DEVICE=y +CONFIG_IOSF_MBI=y +# CONFIG_IOSF_MBI_DEBUG is not set +CONFIG_X86_SUPPORTS_MEMORY_FAILURE=y +CONFIG_SCHED_OMIT_FRAME_POINTER=y +CONFIG_HYPERVISOR_GUEST=y +CONFIG_PARAVIRT=y +CONFIG_PARAVIRT_XXL=y +# CONFIG_PARAVIRT_DEBUG is not set +# CONFIG_PARAVIRT_SPINLOCKS is not set +CONFIG_X86_HV_CALLBACK_VECTOR=y +CONFIG_XEN=y +CONFIG_XEN_PV=y +CONFIG_XEN_PV_SMP=y +CONFIG_XEN_DOM0=y +CONFIG_XEN_PVHVM=y +CONFIG_XEN_PVHVM_SMP=y +CONFIG_XEN_512GB=y +CONFIG_XEN_SAVE_RESTORE=y +CONFIG_XEN_DEBUG_FS=y +CONFIG_XEN_PVH=y +CONFIG_KVM_GUEST=y +CONFIG_ARCH_CPUIDLE_HALTPOLL=y +CONFIG_PVH=y +# CONFIG_KVM_DEBUG_FS is not set +# CONFIG_PARAVIRT_TIME_ACCOUNTING is not set +CONFIG_PARAVIRT_CLOCK=y +# CONFIG_JAILHOUSE_GUEST is not set +CONFIG_ACRN_GUEST=y +# CONFIG_MK8 is not set +# CONFIG_MPSC is not set +# CONFIG_MCORE2 is not set +# CONFIG_MATOM is not set +CONFIG_GENERIC_CPU=y +CONFIG_X86_INTERNODE_CACHE_SHIFT=6 +CONFIG_X86_L1_CACHE_SHIFT=6 +CONFIG_X86_TSC=y +CONFIG_X86_CMPXCHG64=y +CONFIG_X86_CMOV=y +CONFIG_X86_MINIMUM_CPU_FAMILY=64 +CONFIG_X86_DEBUGCTLMSR=y +# CONFIG_PROCESSOR_SELECT is not set +CONFIG_CPU_SUP_INTEL=y +CONFIG_CPU_SUP_AMD=y +CONFIG_CPU_SUP_HYGON=y +CONFIG_CPU_SUP_CENTAUR=y +CONFIG_CPU_SUP_ZHAOXIN=y +CONFIG_HPET_TIMER=y +CONFIG_HPET_EMULATE_RTC=y +CONFIG_DMI=y +CONFIG_GART_IOMMU=y +CONFIG_CALGARY_IOMMU=y +CONFIG_CALGARY_IOMMU_ENABLED_BY_DEFAULT=y +# CONFIG_MAXSMP is not set +CONFIG_NR_CPUS_RANGE_BEGIN=2 +CONFIG_NR_CPUS_RANGE_END=512 +CONFIG_NR_CPUS_DEFAULT=64 +CONFIG_NR_CPUS=128 +CONFIG_SCHED_SMT=y +CONFIG_SCHED_MC=y +CONFIG_SCHED_MC_PRIO=y +CONFIG_X86_LOCAL_APIC=y +CONFIG_X86_IO_APIC=y +CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS=y +CONFIG_X86_MCE=y +# CONFIG_X86_MCELOG_LEGACY is not set +CONFIG_X86_MCE_INTEL=y +CONFIG_X86_MCE_AMD=y +CONFIG_X86_MCE_THRESHOLD=y +CONFIG_X86_MCE_INJECT=m +CONFIG_X86_THERMAL_VECTOR=y + +# +# Performance monitoring +# +CONFIG_PERF_EVENTS_INTEL_UNCORE=m +CONFIG_PERF_EVENTS_INTEL_RAPL=m +CONFIG_PERF_EVENTS_INTEL_CSTATE=m +CONFIG_PERF_EVENTS_AMD_POWER=m +# end of Performance monitoring + +CONFIG_X86_16BIT=y +CONFIG_X86_ESPFIX64=y +CONFIG_X86_VSYSCALL_EMULATION=y +CONFIG_I8K=m +CONFIG_MICROCODE=y +CONFIG_MICROCODE_INTEL=y +CONFIG_MICROCODE_AMD=y +CONFIG_MICROCODE_OLD_INTERFACE=y +CONFIG_X86_MSR=m +CONFIG_X86_CPUID=m +# CONFIG_X86_5LEVEL is not set +CONFIG_X86_DIRECT_GBPAGES=y +# CONFIG_X86_CPA_STATISTICS is not set +# CONFIG_AMD_MEM_ENCRYPT is not set +CONFIG_NUMA=y +CONFIG_AMD_NUMA=y +CONFIG_X86_64_ACPI_NUMA=y +CONFIG_NODES_SPAN_OTHER_NODES=y +# CONFIG_NUMA_EMU is not set +CONFIG_NODES_SHIFT=6 +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_SPARSEMEM_DEFAULT=y +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_ARCH_MEMORY_PROBE=y +CONFIG_ARCH_PROC_KCORE_TEXT=y +CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 +# CONFIG_X86_PMEM_LEGACY is not set +CONFIG_X86_CHECK_BIOS_CORRUPTION=y +# CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK is not set +CONFIG_X86_RESERVE_LOW=64 +CONFIG_MTRR=y +CONFIG_MTRR_SANITIZER=y +CONFIG_MTRR_SANITIZER_ENABLE_DEFAULT=0 +CONFIG_MTRR_SANITIZER_SPARE_REG_NR_DEFAULT=1 +CONFIG_X86_PAT=y +CONFIG_ARCH_USES_PG_UNCACHED=y +CONFIG_ARCH_RANDOM=y +CONFIG_X86_SMAP=y +CONFIG_X86_INTEL_UMIP=y +# CONFIG_X86_INTEL_MPX is not set +CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS=y +# CONFIG_X86_INTEL_TSX_MODE_OFF is not set +# CONFIG_X86_INTEL_TSX_MODE_ON is not set +CONFIG_X86_INTEL_TSX_MODE_AUTO=y +CONFIG_EFI=y +CONFIG_EFI_STUB=y +CONFIG_EFI_MIXED=y +CONFIG_SECCOMP=y +# CONFIG_HZ_100 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_300 is not set +CONFIG_HZ_1000=y +CONFIG_HZ=1000 +CONFIG_SCHED_HRTICK=y +CONFIG_KEXEC=y +# CONFIG_KEXEC_FILE is not set +CONFIG_CRASH_DUMP=y +CONFIG_KEXEC_JUMP=y +CONFIG_PHYSICAL_START=0x200000 +CONFIG_RELOCATABLE=y +CONFIG_RANDOMIZE_BASE=y +CONFIG_X86_NEED_RELOCS=y +CONFIG_PHYSICAL_ALIGN=0x1000000 +CONFIG_DYNAMIC_MEMORY_LAYOUT=y +CONFIG_RANDOMIZE_MEMORY=y +CONFIG_RANDOMIZE_MEMORY_PHYSICAL_PADDING=0xa +CONFIG_HOTPLUG_CPU=y +# CONFIG_BOOTPARAM_HOTPLUG_CPU0 is not set +# CONFIG_DEBUG_HOTPLUG_CPU0 is not set +# CONFIG_COMPAT_VDSO is not set +CONFIG_LEGACY_VSYSCALL_EMULATE=y +# CONFIG_LEGACY_VSYSCALL_XONLY is not set +# CONFIG_LEGACY_VSYSCALL_NONE is not set +# CONFIG_CMDLINE_BOOL is not set +CONFIG_MODIFY_LDT_SYSCALL=y +CONFIG_HAVE_LIVEPATCH=y +CONFIG_LIVEPATCH=y +# end of Processor type and features + +CONFIG_ARCH_HAS_ADD_PAGES=y +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y +CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y +CONFIG_USE_PERCPU_NUMA_NODE_ID=y +CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK=y +CONFIG_ARCH_ENABLE_HUGEPAGE_MIGRATION=y +CONFIG_ARCH_ENABLE_THP_MIGRATION=y + +# +# Power management and ACPI options +# +CONFIG_ARCH_HIBERNATION_HEADER=y +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y +# CONFIG_SUSPEND_SKIP_SYNC is not set +CONFIG_HIBERNATE_CALLBACKS=y +CONFIG_HIBERNATION=y +CONFIG_PM_STD_PARTITION="" +CONFIG_PM_SLEEP=y +CONFIG_PM_SLEEP_SMP=y +# CONFIG_PM_AUTOSLEEP is not set +# CONFIG_PM_WAKELOCKS is not set +CONFIG_PM=y +CONFIG_PM_DEBUG=y +# CONFIG_PM_ADVANCED_DEBUG is not set +# CONFIG_PM_TEST_SUSPEND is not set +CONFIG_PM_SLEEP_DEBUG=y +# CONFIG_DPM_WATCHDOG is not set +CONFIG_PM_TRACE=y +CONFIG_PM_TRACE_RTC=y +CONFIG_PM_CLK=y +CONFIG_PM_GENERIC_DOMAINS=y +# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set +CONFIG_PM_GENERIC_DOMAINS_SLEEP=y +# CONFIG_ENERGY_MODEL is not set +CONFIG_ARCH_SUPPORTS_ACPI=y +CONFIG_ACPI=y +CONFIG_ACPI_LEGACY_TABLES_LOOKUP=y +CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC=y +CONFIG_ACPI_SYSTEM_POWER_STATES_SUPPORT=y +# CONFIG_ACPI_DEBUGGER is not set +CONFIG_ACPI_SPCR_TABLE=y +CONFIG_ACPI_LPIT=y +CONFIG_ACPI_SLEEP=y +# CONFIG_ACPI_PROCFS_POWER is not set +CONFIG_ACPI_REV_OVERRIDE_POSSIBLE=y +# CONFIG_ACPI_EC_DEBUGFS is not set +CONFIG_ACPI_AC=m +CONFIG_ACPI_BATTERY=m +CONFIG_ACPI_BUTTON=m +CONFIG_ACPI_VIDEO=m +CONFIG_ACPI_FAN=m +CONFIG_ACPI_TAD=m +CONFIG_ACPI_DOCK=y +CONFIG_ACPI_CPU_FREQ_PSS=y +CONFIG_ACPI_PROCESSOR_CSTATE=y +CONFIG_ACPI_PROCESSOR_IDLE=y +CONFIG_ACPI_CPPC_LIB=y +CONFIG_ACPI_PROCESSOR=y +CONFIG_ACPI_IPMI=m +CONFIG_ACPI_HOTPLUG_CPU=y +CONFIG_ACPI_PROCESSOR_AGGREGATOR=m +CONFIG_ACPI_THERMAL=m +CONFIG_ACPI_NUMA=y +CONFIG_ACPI_CUSTOM_DSDT_FILE="" +CONFIG_ARCH_HAS_ACPI_TABLE_UPGRADE=y +CONFIG_ACPI_TABLE_UPGRADE=y +# CONFIG_ACPI_DEBUG is not set +# CONFIG_ACPI_PCI_SLOT is not set +CONFIG_ACPI_CONTAINER=y +# CONFIG_ACPI_HOTPLUG_MEMORY is not set +CONFIG_ACPI_HOTPLUG_IOAPIC=y +CONFIG_ACPI_SBS=m +CONFIG_ACPI_HED=y +# CONFIG_ACPI_CUSTOM_METHOD is not set +CONFIG_ACPI_BGRT=y +# CONFIG_ACPI_REDUCED_HARDWARE_ONLY is not set +CONFIG_ACPI_NFIT=m +# CONFIG_NFIT_SECURITY_DEBUG is not set +# CONFIG_ACPI_HMAT is not set +CONFIG_HAVE_ACPI_APEI=y +CONFIG_HAVE_ACPI_APEI_NMI=y +CONFIG_ACPI_APEI=y +CONFIG_ACPI_APEI_GHES=y +CONFIG_ACPI_APEI_PCIEAER=y +CONFIG_ACPI_APEI_MEMORY_FAILURE=y +CONFIG_ACPI_APEI_EINJ=m +# CONFIG_ACPI_APEI_ERST_DEBUG is not set +CONFIG_DPTF_POWER=m +CONFIG_ACPI_WATCHDOG=y +CONFIG_ACPI_EXTLOG=m +CONFIG_ACPI_ADXL=y +CONFIG_PMIC_OPREGION=y +CONFIG_CRC_PMIC_OPREGION=y +# CONFIG_XPOWER_PMIC_OPREGION is not set +CONFIG_BXT_WC_PMIC_OPREGION=y +CONFIG_CHT_WC_PMIC_OPREGION=y +CONFIG_CHT_DC_TI_PMIC_OPREGION=y +CONFIG_ACPI_CONFIGFS=m +# CONFIG_TPS68470_PMIC_OPREGION is not set +CONFIG_X86_PM_TIMER=y +# CONFIG_SFI is not set + +# +# CPU Frequency scaling +# +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_GOV_ATTR_SET=y +CONFIG_CPU_FREQ_GOV_COMMON=y +# CONFIG_CPU_FREQ_STAT is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL is not set +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y + +# +# CPU frequency scaling drivers +# +CONFIG_X86_INTEL_PSTATE=y +CONFIG_X86_PCC_CPUFREQ=m +CONFIG_X86_ACPI_CPUFREQ=m +CONFIG_X86_ACPI_CPUFREQ_CPB=y +CONFIG_X86_POWERNOW_K8=m +CONFIG_X86_AMD_FREQ_SENSITIVITY=m +CONFIG_X86_SPEEDSTEP_CENTRINO=m +CONFIG_X86_P4_CLOCKMOD=m + +# +# shared options +# +CONFIG_X86_SPEEDSTEP_LIB=m +# end of CPU Frequency scaling + +# +# CPU Idle +# +CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE_GOV_LADDER=y +CONFIG_CPU_IDLE_GOV_MENU=y +CONFIG_CPU_IDLE_GOV_TEO=y +CONFIG_CPU_IDLE_GOV_HALTPOLL=y +CONFIG_HALTPOLL_CPUIDLE=m +# end of CPU Idle + +CONFIG_INTEL_IDLE=y +# end of Power management and ACPI options + +# +# Bus options (PCI etc.) +# +CONFIG_PCI_DIRECT=y +CONFIG_PCI_MMCONFIG=y +CONFIG_PCI_XEN=y +CONFIG_MMCONF_FAM10H=y +# CONFIG_PCI_CNB20LE_QUIRK is not set +CONFIG_ISA_BUS=y +CONFIG_ISA_DMA_API=y +CONFIG_AMD_NB=y +# CONFIG_X86_SYSFB is not set +# end of Bus options (PCI etc.) + +# +# Binary Emulations +# +CONFIG_IA32_EMULATION=y +CONFIG_X86_X32=y +CONFIG_COMPAT_32=y +CONFIG_COMPAT=y +CONFIG_COMPAT_FOR_U64_ALIGNMENT=y +CONFIG_SYSVIPC_COMPAT=y +# end of Binary Emulations + +CONFIG_X86_DEV_DMA_OPS=y + +# +# Firmware Drivers +# +CONFIG_EDD=y +# CONFIG_EDD_OFF is not set +CONFIG_FIRMWARE_MEMMAP=y +CONFIG_DMIID=y +CONFIG_DMI_SYSFS=m +CONFIG_DMI_SCAN_MACHINE_NON_EFI_FALLBACK=y +CONFIG_ISCSI_IBFT_FIND=y +CONFIG_ISCSI_IBFT=m +CONFIG_FW_CFG_SYSFS=m +# CONFIG_FW_CFG_SYSFS_CMDLINE is not set +# CONFIG_GOOGLE_FIRMWARE is not set + +# +# EFI (Extensible Firmware Interface) Support +# +CONFIG_EFI_VARS=y +CONFIG_EFI_ESRT=y +CONFIG_EFI_VARS_PSTORE=y +CONFIG_EFI_VARS_PSTORE_DEFAULT_DISABLE=y +CONFIG_EFI_RUNTIME_MAP=y +# CONFIG_EFI_FAKE_MEMMAP is not set +CONFIG_EFI_RUNTIME_WRAPPERS=y +CONFIG_EFI_BOOTLOADER_CONTROL=m +CONFIG_EFI_CAPSULE_LOADER=m +# CONFIG_EFI_TEST is not set +CONFIG_APPLE_PROPERTIES=y +# CONFIG_RESET_ATTACK_MITIGATION is not set +CONFIG_EFI_RCI2_TABLE=y +# end of EFI (Extensible Firmware Interface) Support + +CONFIG_UEFI_CPER=y +CONFIG_UEFI_CPER_X86=y +CONFIG_EFI_DEV_PATH_PARSER=y +CONFIG_EFI_EARLYCON=y + +# +# Tegra firmware driver +# +# end of Tegra firmware driver +# end of Firmware Drivers + +CONFIG_HAVE_KVM=y +CONFIG_HAVE_KVM_IRQCHIP=y +CONFIG_HAVE_KVM_IRQFD=y +CONFIG_HAVE_KVM_IRQ_ROUTING=y +CONFIG_HAVE_KVM_EVENTFD=y +CONFIG_KVM_MMIO=y +CONFIG_KVM_ASYNC_PF=y +CONFIG_HAVE_KVM_MSI=y +CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT=y +CONFIG_KVM_VFIO=y +CONFIG_KVM_GENERIC_DIRTYLOG_READ_PROTECT=y +CONFIG_KVM_COMPAT=y +CONFIG_HAVE_KVM_IRQ_BYPASS=y +CONFIG_HAVE_KVM_NO_POLL=y +CONFIG_VIRTUALIZATION=y +CONFIG_KVM=m +CONFIG_KVM_INTEL=m +CONFIG_KVM_AMD=m +CONFIG_KVM_AMD_SEV=y +# CONFIG_KVM_MMU_AUDIT is not set +CONFIG_VHOST_NET=m +CONFIG_VHOST_SCSI=m +CONFIG_VHOST_VSOCK=m +CONFIG_VHOST=m +# CONFIG_VHOST_CROSS_ENDIAN_LEGACY is not set + +# +# General architecture-dependent options +# +CONFIG_CRASH_CORE=y +CONFIG_KEXEC_CORE=y +CONFIG_HOTPLUG_SMT=y +CONFIG_OPROFILE=m +CONFIG_OPROFILE_EVENT_MULTIPLEX=y +CONFIG_HAVE_OPROFILE=y +CONFIG_OPROFILE_NMI_TIMER=y +CONFIG_KPROBES=y +CONFIG_JUMP_LABEL=y +# CONFIG_STATIC_KEYS_SELFTEST is not set +CONFIG_OPTPROBES=y +CONFIG_KPROBES_ON_FTRACE=y +CONFIG_UPROBES=y +CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y +CONFIG_ARCH_USE_BUILTIN_BSWAP=y +CONFIG_KRETPROBES=y +CONFIG_USER_RETURN_NOTIFIER=y +CONFIG_HAVE_IOREMAP_PROT=y +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_OPTPROBES=y +CONFIG_HAVE_KPROBES_ON_FTRACE=y +CONFIG_HAVE_FUNCTION_ERROR_INJECTION=y +CONFIG_HAVE_NMI=y +CONFIG_HAVE_ARCH_TRACEHOOK=y +CONFIG_HAVE_DMA_CONTIGUOUS=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_ARCH_HAS_FORTIFY_SOURCE=y +CONFIG_ARCH_HAS_SET_MEMORY=y +CONFIG_ARCH_HAS_SET_DIRECT_MAP=y +CONFIG_HAVE_ARCH_THREAD_STRUCT_WHITELIST=y +CONFIG_ARCH_WANTS_DYNAMIC_TASK_STRUCT=y +CONFIG_HAVE_ASM_MODVERSIONS=y +CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y +CONFIG_HAVE_RSEQ=y +CONFIG_HAVE_FUNCTION_ARG_ACCESS_API=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_HW_BREAKPOINT=y +CONFIG_HAVE_MIXED_BREAKPOINTS_REGS=y +CONFIG_HAVE_USER_RETURN_NOTIFIER=y +CONFIG_HAVE_PERF_EVENTS_NMI=y +CONFIG_HAVE_HARDLOCKUP_DETECTOR_PERF=y +CONFIG_HAVE_PERF_REGS=y +CONFIG_HAVE_PERF_USER_STACK_DUMP=y +CONFIG_HAVE_ARCH_JUMP_LABEL=y +CONFIG_HAVE_ARCH_JUMP_LABEL_RELATIVE=y +CONFIG_HAVE_RCU_TABLE_FREE=y +CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y +CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y +CONFIG_HAVE_CMPXCHG_LOCAL=y +CONFIG_HAVE_CMPXCHG_DOUBLE=y +CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION=y +CONFIG_ARCH_WANT_OLD_COMPAT_IPC=y +CONFIG_HAVE_ARCH_SECCOMP_FILTER=y +CONFIG_SECCOMP_FILTER=y +CONFIG_HAVE_ARCH_STACKLEAK=y +CONFIG_HAVE_STACKPROTECTOR=y +CONFIG_CC_HAS_STACKPROTECTOR_NONE=y +CONFIG_STACKPROTECTOR=y +CONFIG_STACKPROTECTOR_STRONG=y +CONFIG_HAVE_ARCH_WITHIN_STACK_FRAMES=y +CONFIG_HAVE_CONTEXT_TRACKING=y +CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y +CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y +CONFIG_HAVE_MOVE_PMD=y +CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y +CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD=y +CONFIG_HAVE_ARCH_HUGE_VMAP=y +CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y +CONFIG_HAVE_ARCH_SOFT_DIRTY=y +CONFIG_HAVE_MOD_ARCH_SPECIFIC=y +CONFIG_MODULES_USE_ELF_RELA=y +CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK=y +CONFIG_ARCH_HAS_ELF_RANDOMIZE=y +CONFIG_HAVE_ARCH_MMAP_RND_BITS=y +CONFIG_HAVE_EXIT_THREAD=y +CONFIG_ARCH_MMAP_RND_BITS=28 +CONFIG_HAVE_ARCH_MMAP_RND_COMPAT_BITS=y +CONFIG_ARCH_MMAP_RND_COMPAT_BITS=8 +CONFIG_HAVE_ARCH_COMPAT_MMAP_BASES=y +CONFIG_HAVE_COPY_THREAD_TLS=y +CONFIG_HAVE_STACK_VALIDATION=y +CONFIG_HAVE_RELIABLE_STACKTRACE=y +CONFIG_ISA_BUS_API=y +CONFIG_OLD_SIGSUSPEND3=y +CONFIG_COMPAT_OLD_SIGACTION=y +CONFIG_64BIT_TIME=y +CONFIG_COMPAT_32BIT_TIME=y +CONFIG_HAVE_ARCH_VMAP_STACK=y +CONFIG_VMAP_STACK=y +CONFIG_ARCH_HAS_STRICT_KERNEL_RWX=y +CONFIG_STRICT_KERNEL_RWX=y +CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y +CONFIG_STRICT_MODULE_RWX=y +CONFIG_ARCH_HAS_REFCOUNT=y +# CONFIG_REFCOUNT_FULL is not set +CONFIG_HAVE_ARCH_PREL32_RELOCATIONS=y +CONFIG_ARCH_USE_MEMREMAP_PROT=y +# CONFIG_LOCK_EVENT_COUNTS is not set +CONFIG_ARCH_HAS_MEM_ENCRYPT=y + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set +CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y +# end of GCOV-based kernel profiling + +CONFIG_PLUGIN_HOSTCC="" +CONFIG_HAVE_GCC_PLUGINS=y +# end of General architecture-dependent options + +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +CONFIG_MODULE_FORCE_LOAD=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +# CONFIG_MODULE_SIG is not set +# CONFIG_MODULE_COMPRESS is not set +# CONFIG_MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS is not set +CONFIG_UNUSED_SYMBOLS=y +CONFIG_MODULES_TREE_LOOKUP=y +CONFIG_BLOCK=y +CONFIG_BLK_SCSI_REQUEST=y +CONFIG_BLK_DEV_BSG=y +CONFIG_BLK_DEV_BSGLIB=y +CONFIG_BLK_DEV_INTEGRITY=y +# CONFIG_BLK_DEV_ZONED is not set +CONFIG_BLK_DEV_THROTTLING=y +# CONFIG_BLK_DEV_THROTTLING_LOW is not set +# CONFIG_BLK_CMDLINE_PARSER is not set +CONFIG_BLK_WBT=y +# CONFIG_BLK_CGROUP_IOLATENCY is not set +# CONFIG_BLK_CGROUP_IOCOST is not set +CONFIG_BLK_WBT_MQ=y +# CONFIG_BLK_DEBUG_FS is not set +CONFIG_BLK_SED_OPAL=y + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_AIX_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +CONFIG_MAC_PARTITION=y +CONFIG_MSDOS_PARTITION=y +CONFIG_BSD_DISKLABEL=y +CONFIG_MINIX_SUBPARTITION=y +CONFIG_SOLARIS_X86_PARTITION=y +CONFIG_UNIXWARE_DISKLABEL=y +CONFIG_LDM_PARTITION=y +# CONFIG_LDM_DEBUG is not set +CONFIG_SGI_PARTITION=y +# CONFIG_ULTRIX_PARTITION is not set +CONFIG_SUN_PARTITION=y +CONFIG_KARMA_PARTITION=y +CONFIG_EFI_PARTITION=y +CONFIG_SYSV68_PARTITION=y +# CONFIG_CMDLINE_PARTITION is not set +# end of Partition Types + +CONFIG_BLOCK_COMPAT=y +CONFIG_BLK_MQ_PCI=y +CONFIG_BLK_MQ_VIRTIO=y +CONFIG_BLK_MQ_RDMA=y +CONFIG_BLK_PM=y + +# +# IO Schedulers +# +CONFIG_MQ_IOSCHED_DEADLINE=y +CONFIG_MQ_IOSCHED_KYBER=y +CONFIG_IOSCHED_BFQ=y +CONFIG_BFQ_GROUP_IOSCHED=y +# CONFIG_BFQ_CGROUP_DEBUG is not set +# end of IO Schedulers + +CONFIG_PREEMPT_NOTIFIERS=y +CONFIG_PADATA=y +CONFIG_ASN1=y +CONFIG_INLINE_SPIN_UNLOCK_IRQ=y +CONFIG_INLINE_READ_UNLOCK=y +CONFIG_INLINE_READ_UNLOCK_IRQ=y +CONFIG_INLINE_WRITE_UNLOCK=y +CONFIG_INLINE_WRITE_UNLOCK_IRQ=y +CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y +CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_RWSEM_SPIN_ON_OWNER=y +CONFIG_LOCK_SPIN_ON_OWNER=y +CONFIG_ARCH_USE_QUEUED_SPINLOCKS=y +CONFIG_QUEUED_SPINLOCKS=y +CONFIG_ARCH_USE_QUEUED_RWLOCKS=y +CONFIG_QUEUED_RWLOCKS=y +CONFIG_ARCH_HAS_SYNC_CORE_BEFORE_USERMODE=y +CONFIG_ARCH_HAS_SYSCALL_WRAPPER=y +CONFIG_FREEZER=y + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +CONFIG_COMPAT_BINFMT_ELF=y +CONFIG_ELFCORE=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_BINFMT_SCRIPT=y +CONFIG_BINFMT_MISC=m +CONFIG_COREDUMP=y +# end of Executable file formats + +# +# Memory Management options +# +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_SPARSEMEM_MANUAL=y +CONFIG_SPARSEMEM=y +CONFIG_NEED_MULTIPLE_NODES=y +CONFIG_HAVE_MEMORY_PRESENT=y +CONFIG_SPARSEMEM_EXTREME=y +CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y +CONFIG_SPARSEMEM_VMEMMAP=y +CONFIG_HAVE_MEMBLOCK_NODE_MAP=y +CONFIG_HAVE_FAST_GUP=y +CONFIG_MEMORY_ISOLATION=y +CONFIG_HAVE_BOOTMEM_INFO_NODE=y +CONFIG_MEMORY_HOTPLUG=y +CONFIG_MEMORY_HOTPLUG_SPARSE=y +# CONFIG_MEMORY_HOTPLUG_DEFAULT_ONLINE is not set +CONFIG_MEMORY_HOTREMOVE=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_MEMORY_BALLOON=y +CONFIG_BALLOON_COMPACTION=y +CONFIG_COMPACTION=y +CONFIG_MIGRATION=y +CONFIG_CONTIG_ALLOC=y +CONFIG_PHYS_ADDR_T_64BIT=y +CONFIG_BOUNCE=y +CONFIG_VIRT_TO_BUS=y +CONFIG_MMU_NOTIFIER=y +CONFIG_KSM=y +CONFIG_DEFAULT_MMAP_MIN_ADDR=65536 +CONFIG_ARCH_SUPPORTS_MEMORY_FAILURE=y +CONFIG_MEMORY_FAILURE=y +# CONFIG_HWPOISON_INJECT is not set +CONFIG_TRANSPARENT_HUGEPAGE=y +# CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS is not set +CONFIG_TRANSPARENT_HUGEPAGE_MADVISE=y +CONFIG_ARCH_WANTS_THP_SWAP=y +CONFIG_THP_SWAP=y +CONFIG_TRANSPARENT_HUGE_PAGECACHE=y +CONFIG_CLEANCACHE=y +CONFIG_FRONTSWAP=y +CONFIG_CMA=y +# CONFIG_CMA_DEBUG is not set +# CONFIG_CMA_DEBUGFS is not set +CONFIG_CMA_AREAS=7 +# CONFIG_MEM_SOFT_DIRTY is not set +CONFIG_ZSWAP=y +CONFIG_ZPOOL=y +CONFIG_ZBUD=y +CONFIG_Z3FOLD=m +CONFIG_ZSMALLOC=y +# CONFIG_PGTABLE_MAPPING is not set +# CONFIG_ZSMALLOC_STAT is not set +CONFIG_GENERIC_EARLY_IOREMAP=y +# CONFIG_DEFERRED_STRUCT_PAGE_INIT is not set +# CONFIG_IDLE_PAGE_TRACKING is not set +CONFIG_ARCH_HAS_PTE_DEVMAP=y +# CONFIG_ZONE_DEVICE is not set +CONFIG_HMM_MIRROR=y +CONFIG_FRAME_VECTOR=y +CONFIG_ARCH_USES_HIGH_VMA_FLAGS=y +CONFIG_ARCH_HAS_PKEYS=y +# CONFIG_PERCPU_STATS is not set +# CONFIG_GUP_BENCHMARK is not set +# CONFIG_READ_ONLY_THP_FOR_FS is not set +CONFIG_ARCH_HAS_PTE_SPECIAL=y +# end of Memory Management options + +CONFIG_NET=y +CONFIG_COMPAT_NETLINK_MESSAGES=y +CONFIG_NET_INGRESS=y +CONFIG_NET_EGRESS=y +CONFIG_SKB_EXTENSIONS=y + +# +# Networking options +# +CONFIG_PACKET=m +CONFIG_PACKET_DIAG=m +CONFIG_UNIX=y +CONFIG_UNIX_SCM=y +CONFIG_UNIX_DIAG=m +CONFIG_TLS=m +# CONFIG_TLS_DEVICE is not set +CONFIG_XFRM=y +CONFIG_XFRM_OFFLOAD=y +CONFIG_XFRM_ALGO=m +CONFIG_XFRM_USER=m +CONFIG_XFRM_INTERFACE=m +CONFIG_XFRM_SUB_POLICY=y +CONFIG_XFRM_MIGRATE=y +# CONFIG_XFRM_STATISTICS is not set +CONFIG_XFRM_IPCOMP=m +CONFIG_NET_KEY=m +CONFIG_NET_KEY_MIGRATE=y +# CONFIG_SMC is not set +CONFIG_XDP_SOCKETS=y +CONFIG_XDP_SOCKETS_DIAG=m +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +# CONFIG_IP_FIB_TRIE_STATS is not set +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_ROUTE_CLASSID=y +# CONFIG_IP_PNP is not set +CONFIG_NET_IPIP=m +CONFIG_NET_IPGRE_DEMUX=m +CONFIG_NET_IP_TUNNEL=m +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE_COMMON=y +CONFIG_IP_MROUTE=y +CONFIG_IP_MROUTE_MULTIPLE_TABLES=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +CONFIG_SYN_COOKIES=y +CONFIG_NET_IPVTI=m +CONFIG_NET_UDP_TUNNEL=m +CONFIG_NET_FOU=m +CONFIG_NET_FOU_IP_TUNNELS=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_ESP_OFFLOAD=m +CONFIG_INET_IPCOMP=m +CONFIG_INET_XFRM_TUNNEL=m +CONFIG_INET_TUNNEL=m +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +CONFIG_INET_UDP_DIAG=m +CONFIG_INET_RAW_DIAG=m +# CONFIG_INET_DIAG_DESTROY is not set +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +CONFIG_IPV6=m +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_ESP_OFFLOAD=m +CONFIG_INET6_IPCOMP=m +CONFIG_IPV6_MIP6=m +# CONFIG_IPV6_ILA is not set +CONFIG_INET6_XFRM_TUNNEL=m +CONFIG_INET6_TUNNEL=m +CONFIG_IPV6_VTI=m +CONFIG_IPV6_SIT=m +# CONFIG_IPV6_SIT_6RD is not set +CONFIG_IPV6_NDISC_NODETYPE=y +CONFIG_IPV6_TUNNEL=m +CONFIG_IPV6_GRE=m +CONFIG_IPV6_FOU=m +CONFIG_IPV6_FOU_TUNNEL=m +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_SUBTREES=y +CONFIG_IPV6_MROUTE=y +CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y +CONFIG_IPV6_PIMSM_V2=y +# CONFIG_IPV6_SEG6_LWTUNNEL is not set +# CONFIG_IPV6_SEG6_HMAC is not set +CONFIG_NETLABEL=y +CONFIG_NETWORK_SECMARK=y +CONFIG_NET_PTP_CLASSIFY=y +# CONFIG_NETWORK_PHY_TIMESTAMPING is not set +CONFIG_NETFILTER=y +CONFIG_NETFILTER_ADVANCED=y +CONFIG_BRIDGE_NETFILTER=m + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_INGRESS=y +CONFIG_NETFILTER_NETLINK=m +CONFIG_NETFILTER_FAMILY_BRIDGE=y +CONFIG_NETFILTER_FAMILY_ARP=y +CONFIG_NETFILTER_NETLINK_ACCT=m +CONFIG_NETFILTER_NETLINK_QUEUE=m +CONFIG_NETFILTER_NETLINK_LOG=m +CONFIG_NETFILTER_NETLINK_OSF=m +CONFIG_NF_CONNTRACK=m +CONFIG_NF_LOG_COMMON=m +CONFIG_NF_LOG_NETDEV=m +CONFIG_NETFILTER_CONNCOUNT=m +CONFIG_NF_CONNTRACK_MARK=y +CONFIG_NF_CONNTRACK_SECMARK=y +CONFIG_NF_CONNTRACK_ZONES=y +# CONFIG_NF_CONNTRACK_PROCFS is not set +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CONNTRACK_TIMEOUT=y +CONFIG_NF_CONNTRACK_TIMESTAMP=y +CONFIG_NF_CONNTRACK_LABELS=y +CONFIG_NF_CT_PROTO_DCCP=y +CONFIG_NF_CT_PROTO_GRE=y +CONFIG_NF_CT_PROTO_SCTP=y +CONFIG_NF_CT_PROTO_UDPLITE=y +CONFIG_NF_CONNTRACK_AMANDA=m +CONFIG_NF_CONNTRACK_FTP=m +CONFIG_NF_CONNTRACK_H323=m +CONFIG_NF_CONNTRACK_IRC=m +CONFIG_NF_CONNTRACK_BROADCAST=m +CONFIG_NF_CONNTRACK_NETBIOS_NS=m +CONFIG_NF_CONNTRACK_SNMP=m +CONFIG_NF_CONNTRACK_PPTP=m +CONFIG_NF_CONNTRACK_SANE=m +CONFIG_NF_CONNTRACK_SIP=m +CONFIG_NF_CONNTRACK_TFTP=m +CONFIG_NF_CT_NETLINK=m +CONFIG_NF_CT_NETLINK_TIMEOUT=m +CONFIG_NF_CT_NETLINK_HELPER=m +CONFIG_NETFILTER_NETLINK_GLUE_CT=y +CONFIG_NF_NAT=m +CONFIG_NF_NAT_AMANDA=m +CONFIG_NF_NAT_FTP=m +CONFIG_NF_NAT_IRC=m +CONFIG_NF_NAT_SIP=m +CONFIG_NF_NAT_TFTP=m +CONFIG_NF_NAT_REDIRECT=y +CONFIG_NF_NAT_MASQUERADE=y +CONFIG_NETFILTER_SYNPROXY=m +CONFIG_NF_TABLES=m +CONFIG_NF_TABLES_SET=m +# CONFIG_NF_TABLES_INET is not set +CONFIG_NF_TABLES_NETDEV=y +CONFIG_NFT_NUMGEN=m +CONFIG_NFT_CT=m +CONFIG_NFT_FLOW_OFFLOAD=m +CONFIG_NFT_COUNTER=m +CONFIG_NFT_CONNLIMIT=m +CONFIG_NFT_LOG=m +CONFIG_NFT_LIMIT=m +CONFIG_NFT_MASQ=m +CONFIG_NFT_REDIR=m +CONFIG_NFT_NAT=m +CONFIG_NFT_TUNNEL=m +CONFIG_NFT_OBJREF=m +CONFIG_NFT_QUEUE=m +CONFIG_NFT_QUOTA=m +CONFIG_NFT_REJECT=m +CONFIG_NFT_COMPAT=m +CONFIG_NFT_HASH=m +CONFIG_NFT_FIB=m +CONFIG_NFT_XFRM=m +CONFIG_NFT_SOCKET=m +CONFIG_NFT_OSF=m +CONFIG_NFT_TPROXY=m +CONFIG_NFT_SYNPROXY=m +CONFIG_NF_DUP_NETDEV=m +CONFIG_NFT_DUP_NETDEV=m +CONFIG_NFT_FWD_NETDEV=m +CONFIG_NFT_FIB_NETDEV=m +CONFIG_NF_FLOW_TABLE_INET=m +CONFIG_NF_FLOW_TABLE=m +CONFIG_NETFILTER_XTABLES=m + +# +# Xtables combined modules +# +CONFIG_NETFILTER_XT_MARK=m +CONFIG_NETFILTER_XT_CONNMARK=m +CONFIG_NETFILTER_XT_SET=m + +# +# Xtables targets +# +CONFIG_NETFILTER_XT_TARGET_AUDIT=m +CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m +CONFIG_NETFILTER_XT_TARGET_CT=m +CONFIG_NETFILTER_XT_TARGET_DSCP=m +CONFIG_NETFILTER_XT_TARGET_HL=m +CONFIG_NETFILTER_XT_TARGET_HMARK=m +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m +CONFIG_NETFILTER_XT_TARGET_LED=m +CONFIG_NETFILTER_XT_TARGET_LOG=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_NAT=m +CONFIG_NETFILTER_XT_TARGET_NETMAP=m +CONFIG_NETFILTER_XT_TARGET_NFLOG=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +# CONFIG_NETFILTER_XT_TARGET_NOTRACK is not set +CONFIG_NETFILTER_XT_TARGET_RATEEST=m +CONFIG_NETFILTER_XT_TARGET_REDIRECT=m +CONFIG_NETFILTER_XT_TARGET_MASQUERADE=m +CONFIG_NETFILTER_XT_TARGET_TEE=m +CONFIG_NETFILTER_XT_TARGET_TPROXY=m +CONFIG_NETFILTER_XT_TARGET_TRACE=m +CONFIG_NETFILTER_XT_TARGET_SECMARK=m +CONFIG_NETFILTER_XT_TARGET_TCPMSS=m +CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m + +# +# Xtables matches +# +CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m +CONFIG_NETFILTER_XT_MATCH_BPF=m +CONFIG_NETFILTER_XT_MATCH_CGROUP=m +CONFIG_NETFILTER_XT_MATCH_CLUSTER=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m +CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_CPU=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m +CONFIG_NETFILTER_XT_MATCH_DSCP=m +CONFIG_NETFILTER_XT_MATCH_ECN=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_HL=m +CONFIG_NETFILTER_XT_MATCH_IPCOMP=m +CONFIG_NETFILTER_XT_MATCH_IPRANGE=m +CONFIG_NETFILTER_XT_MATCH_IPVS=m +CONFIG_NETFILTER_XT_MATCH_L2TP=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_NFACCT=m +CONFIG_NETFILTER_XT_MATCH_OSF=m +CONFIG_NETFILTER_XT_MATCH_OWNER=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_RATEEST=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_RECENT=m +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_SOCKET=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m +CONFIG_NETFILTER_XT_MATCH_TIME=m +CONFIG_NETFILTER_XT_MATCH_U32=m +# end of Core Netfilter Configuration + +CONFIG_IP_SET=m +CONFIG_IP_SET_MAX=256 +CONFIG_IP_SET_BITMAP_IP=m +CONFIG_IP_SET_BITMAP_IPMAC=m +CONFIG_IP_SET_BITMAP_PORT=m +CONFIG_IP_SET_HASH_IP=m +CONFIG_IP_SET_HASH_IPMARK=m +CONFIG_IP_SET_HASH_IPPORT=m +CONFIG_IP_SET_HASH_IPPORTIP=m +CONFIG_IP_SET_HASH_IPPORTNET=m +CONFIG_IP_SET_HASH_IPMAC=m +CONFIG_IP_SET_HASH_MAC=m +CONFIG_IP_SET_HASH_NETPORTNET=m +CONFIG_IP_SET_HASH_NET=m +CONFIG_IP_SET_HASH_NETNET=m +CONFIG_IP_SET_HASH_NETPORT=m +CONFIG_IP_SET_HASH_NETIFACE=m +CONFIG_IP_SET_LIST_SET=m +CONFIG_IP_VS=m +CONFIG_IP_VS_IPV6=y +CONFIG_IP_VS_DEBUG=y +CONFIG_IP_VS_TAB_BITS=12 + +# +# IPVS transport protocol load balancing support +# +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_AH_ESP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y +CONFIG_IP_VS_PROTO_SCTP=y + +# +# IPVS scheduler +# +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_FO=m +CONFIG_IP_VS_OVF=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_MH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m + +# +# IPVS SH scheduler +# +CONFIG_IP_VS_SH_TAB_BITS=8 + +# +# IPVS MH scheduler +# +CONFIG_IP_VS_MH_TAB_INDEX=12 + +# +# IPVS application helper +# +CONFIG_IP_VS_FTP=m +CONFIG_IP_VS_NFCT=y +CONFIG_IP_VS_PE_SIP=m + +# +# IP: Netfilter Configuration +# +CONFIG_NF_DEFRAG_IPV4=m +CONFIG_NF_SOCKET_IPV4=m +CONFIG_NF_TPROXY_IPV4=m +CONFIG_NF_TABLES_IPV4=y +CONFIG_NFT_REJECT_IPV4=m +CONFIG_NFT_DUP_IPV4=m +CONFIG_NFT_FIB_IPV4=m +CONFIG_NF_TABLES_ARP=y +CONFIG_NF_FLOW_TABLE_IPV4=m +CONFIG_NF_DUP_IPV4=m +CONFIG_NF_LOG_ARP=m +CONFIG_NF_LOG_IPV4=m +CONFIG_NF_REJECT_IPV4=m +CONFIG_NF_NAT_SNMP_BASIC=m +CONFIG_NF_NAT_PPTP=m +CONFIG_NF_NAT_H323=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_RPFILTER=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_SYNPROXY=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_MANGLE=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_TARGET_ECN=m +CONFIG_IP_NF_TARGET_TTL=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_SECURITY=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m +# end of IP: Netfilter Configuration + +# +# IPv6: Netfilter Configuration +# +CONFIG_NF_SOCKET_IPV6=m +CONFIG_NF_TPROXY_IPV6=m +CONFIG_NF_TABLES_IPV6=y +CONFIG_NFT_REJECT_IPV6=m +CONFIG_NFT_DUP_IPV6=m +CONFIG_NFT_FIB_IPV6=m +CONFIG_NF_FLOW_TABLE_IPV6=m +CONFIG_NF_DUP_IPV6=m +CONFIG_NF_REJECT_IPV6=m +CONFIG_NF_LOG_IPV6=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_MH=m +CONFIG_IP6_NF_MATCH_RPFILTER=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_MATCH_SRH=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_TARGET_SYNPROXY=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_RAW=m +CONFIG_IP6_NF_SECURITY=m +CONFIG_IP6_NF_NAT=m +CONFIG_IP6_NF_TARGET_MASQUERADE=m +CONFIG_IP6_NF_TARGET_NPT=m +# end of IPv6: Netfilter Configuration + +CONFIG_NF_DEFRAG_IPV6=m + +# +# DECnet: Netfilter Configuration +# +CONFIG_DECNET_NF_GRABULATOR=m +# end of DECnet: Netfilter Configuration + +CONFIG_NF_TABLES_BRIDGE=m +CONFIG_NFT_BRIDGE_META=m +CONFIG_NFT_BRIDGE_REJECT=m +CONFIG_NF_LOG_BRIDGE=m +CONFIG_NF_CONNTRACK_BRIDGE=m +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_IP6=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_NFLOG=m +# CONFIG_BPFILTER is not set +CONFIG_IP_DCCP=m +CONFIG_INET_DCCP_DIAG=m + +# +# DCCP CCIDs Configuration +# +# CONFIG_IP_DCCP_CCID2_DEBUG is not set +CONFIG_IP_DCCP_CCID3=y +# CONFIG_IP_DCCP_CCID3_DEBUG is not set +CONFIG_IP_DCCP_TFRC_LIB=y +# end of DCCP CCIDs Configuration + +# +# DCCP Kernel Hacking +# +# CONFIG_IP_DCCP_DEBUG is not set +# end of DCCP Kernel Hacking + +CONFIG_IP_SCTP=m +# CONFIG_SCTP_DBG_OBJCNT is not set +CONFIG_SCTP_DEFAULT_COOKIE_HMAC_MD5=y +# CONFIG_SCTP_DEFAULT_COOKIE_HMAC_SHA1 is not set +# CONFIG_SCTP_DEFAULT_COOKIE_HMAC_NONE is not set +CONFIG_SCTP_COOKIE_HMAC_MD5=y +CONFIG_SCTP_COOKIE_HMAC_SHA1=y +CONFIG_INET_SCTP_DIAG=m +CONFIG_RDS=m +CONFIG_RDS_RDMA=m +CONFIG_RDS_TCP=m +# CONFIG_RDS_DEBUG is not set +CONFIG_TIPC=m +CONFIG_TIPC_MEDIA_IB=y +CONFIG_TIPC_MEDIA_UDP=y +CONFIG_TIPC_DIAG=m +CONFIG_ATM=m +CONFIG_ATM_CLIP=m +# CONFIG_ATM_CLIP_NO_ICMP is not set +CONFIG_ATM_LANE=m +CONFIG_ATM_MPOA=m +CONFIG_ATM_BR2684=m +CONFIG_ATM_BR2684_IPFILTER=y +CONFIG_L2TP=m +CONFIG_L2TP_DEBUGFS=m +# CONFIG_L2TP_V3 is not set +CONFIG_STP=m +CONFIG_GARP=m +CONFIG_MRP=m +CONFIG_BRIDGE=m +CONFIG_BRIDGE_IGMP_SNOOPING=y +CONFIG_BRIDGE_VLAN_FILTERING=y +CONFIG_HAVE_NET_DSA=y +CONFIG_NET_DSA=m +# CONFIG_NET_DSA_TAG_8021Q is not set +CONFIG_NET_DSA_TAG_BRCM_COMMON=m +CONFIG_NET_DSA_TAG_BRCM=m +CONFIG_NET_DSA_TAG_BRCM_PREPEND=m +CONFIG_NET_DSA_TAG_GSWIP=m +CONFIG_NET_DSA_TAG_DSA=m +CONFIG_NET_DSA_TAG_EDSA=m +# CONFIG_NET_DSA_TAG_MTK is not set +# CONFIG_NET_DSA_TAG_KSZ is not set +# CONFIG_NET_DSA_TAG_QCA is not set +# CONFIG_NET_DSA_TAG_LAN9303 is not set +# CONFIG_NET_DSA_TAG_SJA1105 is not set +CONFIG_NET_DSA_TAG_TRAILER=m +CONFIG_VLAN_8021Q=m +CONFIG_VLAN_8021Q_GVRP=y +CONFIG_VLAN_8021Q_MVRP=y +CONFIG_DECNET=m +# CONFIG_DECNET_ROUTER is not set +CONFIG_LLC=m +CONFIG_LLC2=m +CONFIG_ATALK=m +CONFIG_DEV_APPLETALK=m +CONFIG_IPDDP=m +CONFIG_IPDDP_ENCAP=y +CONFIG_X25=m +CONFIG_LAPB=m +CONFIG_PHONET=m +CONFIG_6LOWPAN=m +# CONFIG_6LOWPAN_DEBUGFS is not set +CONFIG_6LOWPAN_NHC=m +CONFIG_6LOWPAN_NHC_DEST=m +CONFIG_6LOWPAN_NHC_FRAGMENT=m +CONFIG_6LOWPAN_NHC_HOP=m +CONFIG_6LOWPAN_NHC_IPV6=m +CONFIG_6LOWPAN_NHC_MOBILITY=m +CONFIG_6LOWPAN_NHC_ROUTING=m +CONFIG_6LOWPAN_NHC_UDP=m +CONFIG_6LOWPAN_GHC_EXT_HDR_HOP=m +CONFIG_6LOWPAN_GHC_UDP=m +CONFIG_6LOWPAN_GHC_ICMPV6=m +CONFIG_6LOWPAN_GHC_EXT_HDR_DEST=m +CONFIG_6LOWPAN_GHC_EXT_HDR_FRAG=m +CONFIG_6LOWPAN_GHC_EXT_HDR_ROUTE=m +CONFIG_IEEE802154=m +CONFIG_IEEE802154_NL802154_EXPERIMENTAL=y +CONFIG_IEEE802154_SOCKET=m +CONFIG_IEEE802154_6LOWPAN=m +CONFIG_MAC802154=m +CONFIG_NET_SCHED=y + +# +# Queueing/Scheduling +# +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +# CONFIG_NET_SCH_ATM is not set +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_MULTIQ=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFB=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_CBS=m +CONFIG_NET_SCH_ETF=m +CONFIG_NET_SCH_TAPRIO=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_NETEM=m +CONFIG_NET_SCH_DRR=m +CONFIG_NET_SCH_MQPRIO=m +CONFIG_NET_SCH_SKBPRIO=m +CONFIG_NET_SCH_CHOKE=m +CONFIG_NET_SCH_QFQ=m +CONFIG_NET_SCH_CODEL=m +CONFIG_NET_SCH_FQ_CODEL=m +CONFIG_NET_SCH_CAKE=m +CONFIG_NET_SCH_FQ=m +CONFIG_NET_SCH_HHF=m +CONFIG_NET_SCH_PIE=m +CONFIG_NET_SCH_INGRESS=m +CONFIG_NET_SCH_PLUG=m +# CONFIG_NET_SCH_DEFAULT is not set + +# +# Classification +# +CONFIG_NET_CLS=y +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +# CONFIG_CLS_U32_PERF is not set +# CONFIG_CLS_U32_MARK is not set +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_CLS_FLOW=m +CONFIG_NET_CLS_CGROUP=y +CONFIG_NET_CLS_BPF=m +CONFIG_NET_CLS_FLOWER=m +CONFIG_NET_CLS_MATCHALL=m +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_STACK=32 +CONFIG_NET_EMATCH_CMP=m +CONFIG_NET_EMATCH_NBYTE=m +CONFIG_NET_EMATCH_U32=m +CONFIG_NET_EMATCH_META=m +CONFIG_NET_EMATCH_TEXT=m +CONFIG_NET_EMATCH_CANID=m +CONFIG_NET_EMATCH_IPSET=m +CONFIG_NET_EMATCH_IPT=m +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=y +CONFIG_NET_ACT_GACT=m +CONFIG_GACT_PROB=y +CONFIG_NET_ACT_MIRRED=m +CONFIG_NET_ACT_SAMPLE=m +CONFIG_NET_ACT_IPT=m +CONFIG_NET_ACT_NAT=m +CONFIG_NET_ACT_PEDIT=m +CONFIG_NET_ACT_SIMP=m +CONFIG_NET_ACT_SKBEDIT=m +CONFIG_NET_ACT_CSUM=m +CONFIG_NET_ACT_MPLS=m +CONFIG_NET_ACT_VLAN=m +CONFIG_NET_ACT_BPF=m +CONFIG_NET_ACT_CONNMARK=m +CONFIG_NET_ACT_CTINFO=m +# CONFIG_NET_ACT_SKBMOD is not set +CONFIG_NET_ACT_IFE=m +# CONFIG_NET_ACT_TUNNEL_KEY is not set +CONFIG_NET_ACT_CT=m +CONFIG_NET_IFE_SKBMARK=m +CONFIG_NET_IFE_SKBPRIO=m +CONFIG_NET_IFE_SKBTCINDEX=m +# CONFIG_NET_TC_SKB_EXT is not set +CONFIG_NET_SCH_FIFO=y +CONFIG_DCB=y +CONFIG_DNS_RESOLVER=y +# CONFIG_BATMAN_ADV is not set +CONFIG_OPENVSWITCH=m +CONFIG_OPENVSWITCH_GRE=m +CONFIG_OPENVSWITCH_VXLAN=m +CONFIG_OPENVSWITCH_GENEVE=m +CONFIG_VSOCKETS=m +CONFIG_VSOCKETS_DIAG=m +CONFIG_VMWARE_VMCI_VSOCKETS=m +CONFIG_VIRTIO_VSOCKETS=m +CONFIG_VIRTIO_VSOCKETS_COMMON=m +CONFIG_HYPERV_VSOCKETS=m +CONFIG_NETLINK_DIAG=m +CONFIG_MPLS=y +CONFIG_NET_MPLS_GSO=y +CONFIG_MPLS_ROUTING=m +CONFIG_MPLS_IPTUNNEL=m +CONFIG_NET_NSH=m +CONFIG_HSR=m +CONFIG_NET_SWITCHDEV=y +CONFIG_NET_L3_MASTER_DEV=y +# CONFIG_NET_NCSI is not set +CONFIG_RPS=y +CONFIG_RFS_ACCEL=y +CONFIG_XPS=y +# CONFIG_CGROUP_NET_PRIO is not set +CONFIG_CGROUP_NET_CLASSID=y +CONFIG_NET_RX_BUSY_POLL=y +CONFIG_BQL=y +CONFIG_BPF_JIT=y +CONFIG_BPF_STREAM_PARSER=y +CONFIG_NET_FLOW_LIMIT=y + +# +# Network testing +# +CONFIG_NET_PKTGEN=m +# CONFIG_NET_DROP_MONITOR is not set +# end of Network testing +# end of Networking options + +CONFIG_HAMRADIO=y + +# +# Packet Radio protocols +# +CONFIG_AX25=m +CONFIG_AX25_DAMA_SLAVE=y +CONFIG_NETROM=m +CONFIG_ROSE=m + +# +# AX.25 network device drivers +# +CONFIG_MKISS=m +CONFIG_6PACK=m +CONFIG_BPQETHER=m +CONFIG_BAYCOM_SER_FDX=m +CONFIG_BAYCOM_SER_HDX=m +CONFIG_BAYCOM_PAR=m +CONFIG_YAM=m +# end of AX.25 network device drivers + +CONFIG_CAN=m +CONFIG_CAN_RAW=m +CONFIG_CAN_BCM=m +CONFIG_CAN_GW=m +# CONFIG_CAN_J1939 is not set + +# +# CAN Device Drivers +# +CONFIG_CAN_VCAN=m +CONFIG_CAN_VXCAN=m +CONFIG_CAN_SLCAN=m +CONFIG_CAN_DEV=m +# CONFIG_CAN_CALC_BITTIMING is not set +# CONFIG_CAN_KVASER_PCIEFD is not set +CONFIG_CAN_C_CAN=m +CONFIG_CAN_C_CAN_PLATFORM=m +CONFIG_CAN_C_CAN_PCI=m +CONFIG_CAN_CC770=m +CONFIG_CAN_CC770_ISA=m +CONFIG_CAN_CC770_PLATFORM=m +CONFIG_CAN_IFI_CANFD=m +CONFIG_CAN_M_CAN=m +# CONFIG_CAN_M_CAN_PLATFORM is not set +# CONFIG_CAN_M_CAN_TCAN4X5X is not set +CONFIG_CAN_PEAK_PCIEFD=m +CONFIG_CAN_SJA1000=m +CONFIG_CAN_EMS_PCI=m +CONFIG_CAN_EMS_PCMCIA=m +# CONFIG_CAN_F81601 is not set +CONFIG_CAN_KVASER_PCI=m +CONFIG_CAN_PEAK_PCI=m +CONFIG_CAN_PEAK_PCIEC=y +CONFIG_CAN_PEAK_PCMCIA=m +CONFIG_CAN_PLX_PCI=m +CONFIG_CAN_SJA1000_ISA=m +# CONFIG_CAN_SJA1000_PLATFORM is not set +CONFIG_CAN_SOFTING=m +CONFIG_CAN_SOFTING_CS=m + +# +# CAN SPI interfaces +# +# CONFIG_CAN_HI311X is not set +CONFIG_CAN_MCP251X=m +# end of CAN SPI interfaces + +# +# CAN USB interfaces +# +CONFIG_CAN_8DEV_USB=m +CONFIG_CAN_EMS_USB=m +CONFIG_CAN_ESD_USB2=m +CONFIG_CAN_GS_USB=m +CONFIG_CAN_KVASER_USB=m +# CONFIG_CAN_MCBA_USB is not set +CONFIG_CAN_PEAK_USB=m +# CONFIG_CAN_UCAN is not set +# end of CAN USB interfaces + +# CONFIG_CAN_DEBUG_DEVICES is not set +# end of CAN Device Drivers + +CONFIG_BT=m +CONFIG_BT_BREDR=y +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_CMTP=m +CONFIG_BT_HIDP=m +CONFIG_BT_HS=y +CONFIG_BT_LE=y +CONFIG_BT_6LOWPAN=m +CONFIG_BT_LEDS=y +# CONFIG_BT_SELFTEST is not set +# CONFIG_BT_DEBUGFS is not set + +# +# Bluetooth device drivers +# +CONFIG_BT_INTEL=m +CONFIG_BT_BCM=m +CONFIG_BT_RTL=m +CONFIG_BT_QCA=m +CONFIG_BT_HCIBTUSB=m +# CONFIG_BT_HCIBTUSB_AUTOSUSPEND is not set +CONFIG_BT_HCIBTUSB_BCM=y +CONFIG_BT_HCIBTUSB_MTK=y +CONFIG_BT_HCIBTUSB_RTL=y +CONFIG_BT_HCIBTSDIO=m +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_SERDEV=y +CONFIG_BT_HCIUART_H4=y +# CONFIG_BT_HCIUART_NOKIA is not set +CONFIG_BT_HCIUART_BCSP=y +CONFIG_BT_HCIUART_ATH3K=y +CONFIG_BT_HCIUART_LL=y +CONFIG_BT_HCIUART_3WIRE=y +CONFIG_BT_HCIUART_INTEL=y +CONFIG_BT_HCIUART_RTL=y +CONFIG_BT_HCIUART_QCA=y +CONFIG_BT_HCIUART_AG6XX=y +CONFIG_BT_HCIUART_MRVL=y +CONFIG_BT_HCIBCM203X=m +CONFIG_BT_HCIBPA10X=m +CONFIG_BT_HCIBFUSB=m +CONFIG_BT_HCIDTL1=m +CONFIG_BT_HCIBT3C=m +CONFIG_BT_HCIBLUECARD=m +CONFIG_BT_HCIVHCI=m +CONFIG_BT_MRVL=m +CONFIG_BT_MRVL_SDIO=m +CONFIG_BT_ATH3K=m +CONFIG_BT_WILINK=m +CONFIG_BT_MTKSDIO=m +CONFIG_BT_MTKUART=m +CONFIG_BT_HCIRSI=m +# end of Bluetooth device drivers + +CONFIG_AF_RXRPC=m +CONFIG_AF_RXRPC_IPV6=y +# CONFIG_AF_RXRPC_INJECT_LOSS is not set +# CONFIG_AF_RXRPC_DEBUG is not set +# CONFIG_RXKAD is not set +CONFIG_AF_KCM=m +CONFIG_STREAM_PARSER=y +CONFIG_FIB_RULES=y +CONFIG_WIRELESS=y +CONFIG_WIRELESS_EXT=y +CONFIG_WEXT_CORE=y +CONFIG_WEXT_PROC=y +CONFIG_WEXT_SPY=y +CONFIG_WEXT_PRIV=y +CONFIG_CFG80211=m +# CONFIG_NL80211_TESTMODE is not set +# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set +# CONFIG_CFG80211_CERTIFICATION_ONUS is not set +CONFIG_CFG80211_REQUIRE_SIGNED_REGDB=y +CONFIG_CFG80211_USE_KERNEL_REGDB_KEYS=y +CONFIG_CFG80211_DEFAULT_PS=y +# CONFIG_CFG80211_DEBUGFS is not set +CONFIG_CFG80211_CRDA_SUPPORT=y +CONFIG_CFG80211_WEXT=y +CONFIG_CFG80211_WEXT_EXPORT=y +CONFIG_LIB80211=m +CONFIG_LIB80211_CRYPT_WEP=m +CONFIG_LIB80211_CRYPT_CCMP=m +CONFIG_LIB80211_CRYPT_TKIP=m +# CONFIG_LIB80211_DEBUG is not set +CONFIG_MAC80211=m +CONFIG_MAC80211_HAS_RC=y +CONFIG_MAC80211_RC_MINSTREL=y +CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y +CONFIG_MAC80211_RC_DEFAULT="minstrel_ht" +CONFIG_MAC80211_MESH=y +CONFIG_MAC80211_LEDS=y +# CONFIG_MAC80211_DEBUGFS is not set +# CONFIG_MAC80211_MESSAGE_TRACING is not set +# CONFIG_MAC80211_DEBUG_MENU is not set +CONFIG_MAC80211_STA_HASH_MAX_SIZE=0 +CONFIG_WIMAX=m +CONFIG_WIMAX_DEBUG_LEVEL=8 +CONFIG_RFKILL=m +CONFIG_RFKILL_LEDS=y +CONFIG_RFKILL_INPUT=y +CONFIG_RFKILL_GPIO=m +CONFIG_NET_9P=m +CONFIG_NET_9P_VIRTIO=m +CONFIG_NET_9P_XEN=m +CONFIG_NET_9P_RDMA=m +# CONFIG_NET_9P_DEBUG is not set +CONFIG_CAIF=m +# CONFIG_CAIF_DEBUG is not set +CONFIG_CAIF_NETDEV=m +CONFIG_CAIF_USB=m +CONFIG_CEPH_LIB=m +# CONFIG_CEPH_LIB_PRETTYDEBUG is not set +# CONFIG_CEPH_LIB_USE_DNS_RESOLVER is not set +CONFIG_NFC=m +CONFIG_NFC_DIGITAL=m +CONFIG_NFC_NCI=m +# CONFIG_NFC_NCI_SPI is not set +CONFIG_NFC_NCI_UART=m +CONFIG_NFC_HCI=m +CONFIG_NFC_SHDLC=y + +# +# Near Field Communication (NFC) devices +# +CONFIG_NFC_TRF7970A=m +CONFIG_NFC_MEI_PHY=m +CONFIG_NFC_SIM=m +CONFIG_NFC_PORT100=m +CONFIG_NFC_FDP=m +CONFIG_NFC_FDP_I2C=m +CONFIG_NFC_PN544=m +CONFIG_NFC_PN544_I2C=m +CONFIG_NFC_PN544_MEI=m +CONFIG_NFC_PN533=m +CONFIG_NFC_PN533_USB=m +CONFIG_NFC_PN533_I2C=m +CONFIG_NFC_MICROREAD=m +CONFIG_NFC_MICROREAD_I2C=m +CONFIG_NFC_MICROREAD_MEI=m +CONFIG_NFC_MRVL=m +CONFIG_NFC_MRVL_USB=m +CONFIG_NFC_MRVL_UART=m +CONFIG_NFC_MRVL_I2C=m +CONFIG_NFC_ST21NFCA=m +CONFIG_NFC_ST21NFCA_I2C=m +CONFIG_NFC_ST_NCI=m +CONFIG_NFC_ST_NCI_I2C=m +CONFIG_NFC_ST_NCI_SPI=m +# CONFIG_NFC_NXP_NCI is not set +CONFIG_NFC_S3FWRN5=m +CONFIG_NFC_S3FWRN5_I2C=m +CONFIG_NFC_ST95HF=m +# end of Near Field Communication (NFC) devices + +CONFIG_PSAMPLE=m +CONFIG_NET_IFE=m +CONFIG_LWTUNNEL=y +CONFIG_LWTUNNEL_BPF=y +CONFIG_DST_CACHE=y +CONFIG_GRO_CELLS=y +CONFIG_NET_SOCK_MSG=y +CONFIG_NET_DEVLINK=y +CONFIG_PAGE_POOL=y +CONFIG_FAILOVER=m +CONFIG_HAVE_EBPF_JIT=y + +# +# Device Drivers +# +CONFIG_HAVE_EISA=y +# CONFIG_EISA is not set +CONFIG_HAVE_PCI=y +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCIEPORTBUS=y +CONFIG_HOTPLUG_PCI_PCIE=y +CONFIG_PCIEAER=y +# CONFIG_PCIEAER_INJECT is not set +CONFIG_PCIE_ECRC=y +CONFIG_PCIEASPM=y +# CONFIG_PCIEASPM_DEBUG is not set +CONFIG_PCIEASPM_DEFAULT=y +# CONFIG_PCIEASPM_POWERSAVE is not set +# CONFIG_PCIEASPM_POWER_SUPERSAVE is not set +# CONFIG_PCIEASPM_PERFORMANCE is not set +CONFIG_PCIE_PME=y +CONFIG_PCIE_DPC=y +# CONFIG_PCIE_PTM is not set +# CONFIG_PCIE_BW is not set +CONFIG_PCI_MSI=y +CONFIG_PCI_MSI_IRQ_DOMAIN=y +CONFIG_PCI_QUIRKS=y +# CONFIG_PCI_DEBUG is not set +# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set +CONFIG_PCI_STUB=m +CONFIG_PCI_PF_STUB=m +CONFIG_XEN_PCIDEV_FRONTEND=m +CONFIG_PCI_ATS=y +CONFIG_PCI_LOCKLESS_CONFIG=y +CONFIG_PCI_IOV=y +CONFIG_PCI_PRI=y +CONFIG_PCI_PASID=y +CONFIG_PCI_LABEL=y +CONFIG_PCI_HYPERV=m +CONFIG_HOTPLUG_PCI=y +CONFIG_HOTPLUG_PCI_ACPI=y +CONFIG_HOTPLUG_PCI_ACPI_IBM=m +CONFIG_HOTPLUG_PCI_CPCI=y +CONFIG_HOTPLUG_PCI_CPCI_ZT5550=m +CONFIG_HOTPLUG_PCI_CPCI_GENERIC=m +# CONFIG_HOTPLUG_PCI_SHPC is not set + +# +# PCI controller drivers +# + +# +# Cadence PCIe controllers support +# +# end of Cadence PCIe controllers support + +CONFIG_VMD=m +CONFIG_PCI_HYPERV_INTERFACE=m + +# +# DesignWare PCI Core Support +# +CONFIG_PCIE_DW=y +CONFIG_PCIE_DW_HOST=y +CONFIG_PCIE_DW_PLAT=y +CONFIG_PCIE_DW_PLAT_HOST=y +# CONFIG_PCI_MESON is not set +# end of DesignWare PCI Core Support +# end of PCI controller drivers + +# +# PCI Endpoint +# +# CONFIG_PCI_ENDPOINT is not set +# end of PCI Endpoint + +# +# PCI switch controller drivers +# +# CONFIG_PCI_SW_SWITCHTEC is not set +# end of PCI switch controller drivers + +CONFIG_PCCARD=m +CONFIG_PCMCIA=m +CONFIG_PCMCIA_LOAD_CIS=y +CONFIG_CARDBUS=y + +# +# PC-card bridges +# +CONFIG_YENTA=m +CONFIG_YENTA_O2=y +CONFIG_YENTA_RICOH=y +CONFIG_YENTA_TI=y +CONFIG_YENTA_ENE_TUNE=y +CONFIG_YENTA_TOSHIBA=y +CONFIG_PD6729=m +CONFIG_I82092=m +CONFIG_PCCARD_NONSTATIC=y +CONFIG_RAPIDIO=y +CONFIG_RAPIDIO_TSI721=y +CONFIG_RAPIDIO_DISC_TIMEOUT=30 +# CONFIG_RAPIDIO_ENABLE_RX_TX_PORTS is not set +CONFIG_RAPIDIO_DMA_ENGINE=y +# CONFIG_RAPIDIO_DEBUG is not set +CONFIG_RAPIDIO_ENUM_BASIC=m +CONFIG_RAPIDIO_CHMAN=m +CONFIG_RAPIDIO_MPORT_CDEV=m + +# +# RapidIO Switch drivers +# +CONFIG_RAPIDIO_TSI57X=y +CONFIG_RAPIDIO_CPS_XX=y +CONFIG_RAPIDIO_TSI568=y +CONFIG_RAPIDIO_CPS_GEN2=y +CONFIG_RAPIDIO_RXS_GEN3=y +# end of RapidIO Switch drivers + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER=y +CONFIG_UEVENT_HELPER_PATH="" +CONFIG_DEVTMPFS=y +# CONFIG_DEVTMPFS_MOUNT is not set +# CONFIG_STANDALONE is not set +CONFIG_PREVENT_FIRMWARE_BUILD=y + +# +# Firmware loader +# +CONFIG_FW_LOADER=y +CONFIG_FW_LOADER_PAGED_BUF=y +CONFIG_EXTRA_FIRMWARE="" +CONFIG_FW_LOADER_USER_HELPER=y +# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set +CONFIG_FW_LOADER_COMPRESS=y +# end of Firmware loader + +CONFIG_WANT_DEV_COREDUMP=y +CONFIG_ALLOW_DEV_COREDUMP=y +CONFIG_DEV_COREDUMP=y +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set +# CONFIG_TEST_ASYNC_DRIVER_PROBE is not set +CONFIG_SYS_HYPERVISOR=y +CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_GENERIC_CPU_VULNERABILITIES=y +CONFIG_REGMAP=y +CONFIG_REGMAP_I2C=y +CONFIG_REGMAP_SPI=y +CONFIG_REGMAP_SPMI=m +CONFIG_REGMAP_MMIO=y +CONFIG_REGMAP_IRQ=y +CONFIG_REGMAP_SCCB=m +CONFIG_DMA_SHARED_BUFFER=y +# CONFIG_DMA_FENCE_TRACE is not set +# end of Generic Driver Options + +# +# Bus devices +# +# end of Bus devices + +CONFIG_CONNECTOR=m +CONFIG_GNSS=m +CONFIG_GNSS_SERIAL=m +# CONFIG_GNSS_MTK_SERIAL is not set +CONFIG_GNSS_SIRF_SERIAL=m +CONFIG_GNSS_UBX_SERIAL=m +CONFIG_MTD=m +CONFIG_MTD_TESTS=m + +# +# Partition parsers +# +CONFIG_MTD_AR7_PARTS=m +# CONFIG_MTD_CMDLINE_PARTS is not set +CONFIG_MTD_REDBOOT_PARTS=m +CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 +# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set +# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set +# end of Partition parsers + +# +# User Modules And Translation Layers +# +CONFIG_MTD_BLKDEVS=m +CONFIG_MTD_BLOCK=m +CONFIG_MTD_BLOCK_RO=m +CONFIG_FTL=m +CONFIG_NFTL=m +# CONFIG_NFTL_RW is not set +CONFIG_INFTL=m +CONFIG_RFD_FTL=m +CONFIG_SSFDC=m +CONFIG_SM_FTL=m +CONFIG_MTD_OOPS=m +CONFIG_MTD_SWAP=m +# CONFIG_MTD_PARTITIONED_MASTER is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=m +CONFIG_MTD_JEDECPROBE=m +CONFIG_MTD_GEN_PROBE=m +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +CONFIG_MTD_CFI_INTELEXT=m +CONFIG_MTD_CFI_AMDSTD=m +CONFIG_MTD_CFI_STAA=m +CONFIG_MTD_CFI_UTIL=m +CONFIG_MTD_RAM=m +CONFIG_MTD_ROM=m +CONFIG_MTD_ABSENT=m +# end of RAM/ROM/Flash chip drivers + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PHYSMAP is not set +CONFIG_MTD_AMD76XROM=m +CONFIG_MTD_ICHXROM=m +CONFIG_MTD_ESB2ROM=m +CONFIG_MTD_CK804XROM=m +CONFIG_MTD_SCB2_FLASH=m +CONFIG_MTD_NETtel=m +CONFIG_MTD_L440GX=m +CONFIG_MTD_INTEL_VR_NOR=m +# CONFIG_MTD_PLATRAM is not set +# end of Mapping drivers for chip access + +# +# Self-contained MTD device drivers +# +CONFIG_MTD_PMC551=m +# CONFIG_MTD_PMC551_BUGFIX is not set +# CONFIG_MTD_PMC551_DEBUG is not set +CONFIG_MTD_DATAFLASH=m +# CONFIG_MTD_DATAFLASH_WRITE_VERIFY is not set +# CONFIG_MTD_DATAFLASH_OTP is not set +# CONFIG_MTD_MCHP23K256 is not set +CONFIG_MTD_SST25L=m +CONFIG_MTD_SLRAM=m +CONFIG_MTD_PHRAM=m +CONFIG_MTD_MTDRAM=m +CONFIG_MTDRAM_TOTAL_SIZE=4096 +CONFIG_MTDRAM_ERASE_SIZE=128 +CONFIG_MTD_BLOCK2MTD=m + +# +# Disk-On-Chip Device Drivers +# +CONFIG_MTD_DOCG3=m +CONFIG_BCH_CONST_M=14 +CONFIG_BCH_CONST_T=4 +# end of Self-contained MTD device drivers + +CONFIG_MTD_NAND_CORE=m +CONFIG_MTD_ONENAND=m +# CONFIG_MTD_ONENAND_VERIFY_WRITE is not set +# CONFIG_MTD_ONENAND_GENERIC is not set +CONFIG_MTD_ONENAND_OTP=y +CONFIG_MTD_ONENAND_2X_PROGRAM=y +CONFIG_MTD_NAND_ECC_SW_HAMMING=m +# CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC is not set +CONFIG_MTD_RAW_NAND=m +CONFIG_MTD_NAND_ECC_SW_BCH=y + +# +# Raw/parallel NAND flash controllers +# +CONFIG_MTD_NAND_DENALI=m +CONFIG_MTD_NAND_DENALI_PCI=m +CONFIG_MTD_NAND_CAFE=m +CONFIG_MTD_NAND_MXIC=m +CONFIG_MTD_NAND_GPIO=m +# CONFIG_MTD_NAND_PLATFORM is not set + +# +# Misc +# +CONFIG_MTD_SM_COMMON=m +CONFIG_MTD_NAND_NANDSIM=m +CONFIG_MTD_NAND_RICOH=m +CONFIG_MTD_NAND_DISKONCHIP=m +# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set +CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0 +# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set +CONFIG_MTD_SPI_NAND=m + +# +# LPDDR & LPDDR2 PCM memory drivers +# +CONFIG_MTD_LPDDR=m +CONFIG_MTD_QINFO_PROBE=m +# end of LPDDR & LPDDR2 PCM memory drivers + +CONFIG_MTD_SPI_NOR=m +CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y +# CONFIG_SPI_MTK_QUADSPI is not set +# CONFIG_SPI_INTEL_SPI_PCI is not set +# CONFIG_SPI_INTEL_SPI_PLATFORM is not set +CONFIG_MTD_UBI=m +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_MTD_UBI_BEB_LIMIT=20 +# CONFIG_MTD_UBI_FASTMAP is not set +# CONFIG_MTD_UBI_GLUEBI is not set +# CONFIG_MTD_UBI_BLOCK is not set +# CONFIG_MTD_HYPERBUS is not set +# CONFIG_OF is not set +CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y +CONFIG_PARPORT=m +CONFIG_PARPORT_PC=m +CONFIG_PARPORT_SERIAL=m +CONFIG_PARPORT_PC_FIFO=y +CONFIG_PARPORT_PC_SUPERIO=y +CONFIG_PARPORT_PC_PCMCIA=m +# CONFIG_PARPORT_AX88796 is not set +CONFIG_PARPORT_1284=y +CONFIG_PARPORT_NOT_PC=y +CONFIG_PNP=y +CONFIG_PNP_DEBUG_MESSAGES=y + +# +# Protocols +# +CONFIG_PNPACPI=y +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_NULL_BLK is not set +CONFIG_BLK_DEV_FD=m +CONFIG_CDROM=y +CONFIG_PARIDE=m + +# +# Parallel IDE high-level drivers +# +CONFIG_PARIDE_PD=m +CONFIG_PARIDE_PCD=m +CONFIG_PARIDE_PF=m +CONFIG_PARIDE_PT=m +CONFIG_PARIDE_PG=m + +# +# Parallel IDE protocol modules +# +CONFIG_PARIDE_ATEN=m +CONFIG_PARIDE_BPCK=m +CONFIG_PARIDE_COMM=m +CONFIG_PARIDE_DSTR=m +CONFIG_PARIDE_FIT2=m +CONFIG_PARIDE_FIT3=m +CONFIG_PARIDE_EPAT=m +CONFIG_PARIDE_EPATC8=y +CONFIG_PARIDE_EPIA=m +CONFIG_PARIDE_FRIQ=m +CONFIG_PARIDE_FRPW=m +CONFIG_PARIDE_KBIC=m +CONFIG_PARIDE_KTTI=m +CONFIG_PARIDE_ON20=m +CONFIG_PARIDE_ON26=m +CONFIG_BLK_DEV_PCIESSD_MTIP32XX=m +CONFIG_ZRAM=m +# CONFIG_ZRAM_WRITEBACK is not set +# CONFIG_ZRAM_MEMORY_TRACKING is not set +CONFIG_BLK_DEV_UMEM=m +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 +CONFIG_BLK_DEV_CRYPTOLOOP=m +# CONFIG_BLK_DEV_DRBD is not set +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_SKD=m +CONFIG_BLK_DEV_SX8=m +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=32000 +CONFIG_CDROM_PKTCDVD=y +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set +CONFIG_ATA_OVER_ETH=m +CONFIG_XEN_BLKDEV_FRONTEND=m +CONFIG_XEN_BLKDEV_BACKEND=m +CONFIG_VIRTIO_BLK=m +# CONFIG_VIRTIO_BLK_SCSI is not set +CONFIG_BLK_DEV_RBD=m +CONFIG_BLK_DEV_RSXX=m + +# +# NVME Support +# +CONFIG_NVME_CORE=y +CONFIG_BLK_DEV_NVME=y +# CONFIG_NVME_MULTIPATH is not set +CONFIG_NVME_FABRICS=m +CONFIG_NVME_RDMA=m +CONFIG_NVME_FC=m +CONFIG_NVME_TCP=m +CONFIG_NVME_TARGET=m +CONFIG_NVME_TARGET_LOOP=m +CONFIG_NVME_TARGET_RDMA=m +CONFIG_NVME_TARGET_FC=m +# CONFIG_NVME_TARGET_FCLOOP is not set +CONFIG_NVME_TARGET_TCP=m +# end of NVME Support + +# +# Misc devices +# +CONFIG_SENSORS_LIS3LV02D=m +# CONFIG_AD525X_DPOT is not set +CONFIG_DUMMY_IRQ=m +CONFIG_IBM_ASM=m +CONFIG_PHANTOM=m +CONFIG_TIFM_CORE=m +CONFIG_TIFM_7XX1=m +CONFIG_ICS932S401=m +CONFIG_ENCLOSURE_SERVICES=m +CONFIG_HP_ILO=m +CONFIG_APDS9802ALS=m +# CONFIG_ISL29003 is not set +CONFIG_ISL29020=m +CONFIG_SENSORS_TSL2550=m +CONFIG_SENSORS_BH1770=m +CONFIG_SENSORS_APDS990X=m +CONFIG_HMC6352=m +CONFIG_DS1682=m +CONFIG_VMWARE_BALLOON=m +CONFIG_LATTICE_ECP3_CONFIG=m +CONFIG_SRAM=y +# CONFIG_PCI_ENDPOINT_TEST is not set +# CONFIG_XILINX_SDFEC is not set +CONFIG_MISC_RTSX=m +CONFIG_PVPANIC=m +CONFIG_C2PORT=m +CONFIG_C2PORT_DURAMAR_2150=m + +# +# EEPROM support +# +# CONFIG_EEPROM_AT24 is not set +CONFIG_EEPROM_AT25=m +CONFIG_EEPROM_LEGACY=m +CONFIG_EEPROM_MAX6875=m +CONFIG_EEPROM_93CX6=m +CONFIG_EEPROM_93XX46=m +CONFIG_EEPROM_IDT_89HPESX=m +CONFIG_EEPROM_EE1004=m +# end of EEPROM support + +CONFIG_CB710_CORE=m +# CONFIG_CB710_DEBUG is not set +CONFIG_CB710_DEBUG_ASSUMPTIONS=y + +# +# Texas Instruments shared transport line discipline +# +CONFIG_TI_ST=m +# end of Texas Instruments shared transport line discipline + +CONFIG_SENSORS_LIS3_I2C=m +CONFIG_ALTERA_STAPL=m +CONFIG_INTEL_MEI=m +CONFIG_INTEL_MEI_ME=m +CONFIG_INTEL_MEI_TXE=m +CONFIG_INTEL_MEI_HDCP=m +CONFIG_VMWARE_VMCI=m + +# +# Intel MIC & related support +# + +# +# Intel MIC Bus Driver +# +CONFIG_INTEL_MIC_BUS=m + +# +# SCIF Bus Driver +# +CONFIG_SCIF_BUS=m + +# +# VOP Bus Driver +# +# CONFIG_VOP_BUS is not set + +# +# Intel MIC Host Driver +# + +# +# Intel MIC Card Driver +# + +# +# SCIF Driver +# +CONFIG_SCIF=m + +# +# Intel MIC Coprocessor State Management (COSM) Drivers +# +CONFIG_MIC_COSM=m + +# +# VOP Driver +# +CONFIG_VHOST_RING=m +# end of Intel MIC & related support + +CONFIG_GENWQE=m +CONFIG_GENWQE_PLATFORM_ERROR_RECOVERY=1 +CONFIG_ECHO=m +CONFIG_MISC_ALCOR_PCI=m +CONFIG_MISC_RTSX_PCI=m +CONFIG_MISC_RTSX_USB=m +# CONFIG_HABANA_AI is not set +# end of Misc devices + +CONFIG_HAVE_IDE=y +CONFIG_IDE=m + +# +# Please see Documentation/ide/ide.rst for help/info on IDE drives +# +CONFIG_IDE_XFER_MODE=y +CONFIG_IDE_TIMINGS=y +CONFIG_IDE_ATAPI=y +# CONFIG_BLK_DEV_IDE_SATA is not set +CONFIG_IDE_GD=m +CONFIG_IDE_GD_ATA=y +CONFIG_IDE_GD_ATAPI=y +CONFIG_BLK_DEV_IDECS=m +CONFIG_BLK_DEV_DELKIN=m +CONFIG_BLK_DEV_IDECD=m +CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS=y +CONFIG_BLK_DEV_IDETAPE=m +CONFIG_BLK_DEV_IDEACPI=y +CONFIG_IDE_TASK_IOCTL=y +CONFIG_IDE_PROC_FS=y + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=m +# CONFIG_BLK_DEV_PLATFORM is not set +CONFIG_BLK_DEV_CMD640=m +# CONFIG_BLK_DEV_CMD640_ENHANCED is not set +# CONFIG_BLK_DEV_IDEPNP is not set +CONFIG_BLK_DEV_IDEDMA_SFF=y + +# +# PCI IDE chipsets support +# +CONFIG_BLK_DEV_IDEPCI=y +# CONFIG_BLK_DEV_OFFBOARD is not set +CONFIG_BLK_DEV_GENERIC=m +CONFIG_BLK_DEV_OPTI621=m +CONFIG_BLK_DEV_RZ1000=m +CONFIG_BLK_DEV_IDEDMA_PCI=y +CONFIG_BLK_DEV_AEC62XX=m +CONFIG_BLK_DEV_ALI15X3=m +CONFIG_BLK_DEV_AMD74XX=m +CONFIG_BLK_DEV_ATIIXP=m +CONFIG_BLK_DEV_CMD64X=m +CONFIG_BLK_DEV_TRIFLEX=m +CONFIG_BLK_DEV_HPT366=m +CONFIG_BLK_DEV_JMICRON=m +CONFIG_BLK_DEV_PIIX=m +CONFIG_BLK_DEV_IT8172=m +CONFIG_BLK_DEV_IT8213=m +CONFIG_BLK_DEV_IT821X=m +CONFIG_BLK_DEV_NS87415=m +CONFIG_BLK_DEV_PDC202XX_OLD=m +CONFIG_BLK_DEV_PDC202XX_NEW=m +CONFIG_BLK_DEV_SVWKS=m +CONFIG_BLK_DEV_SIIMAGE=m +CONFIG_BLK_DEV_SIS5513=m +CONFIG_BLK_DEV_SLC90E66=m +CONFIG_BLK_DEV_TRM290=m +CONFIG_BLK_DEV_VIA82CXXX=m +CONFIG_BLK_DEV_TC86C001=m +CONFIG_BLK_DEV_IDEDMA=y + +# +# SCSI device support +# +CONFIG_SCSI_MOD=y +CONFIG_RAID_ATTRS=m +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +CONFIG_SCSI_NETLINK=y +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_ST=m +CONFIG_BLK_DEV_SR=m +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_CHR_DEV_SG=m +CONFIG_CHR_DEV_SCH=m +CONFIG_SCSI_ENCLOSURE=m +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y +# CONFIG_SCSI_SCAN_ASYNC is not set + +# +# SCSI Transports +# +CONFIG_SCSI_SPI_ATTRS=m +CONFIG_SCSI_FC_ATTRS=m +CONFIG_SCSI_ISCSI_ATTRS=m +CONFIG_SCSI_SAS_ATTRS=m +CONFIG_SCSI_SAS_LIBSAS=m +CONFIG_SCSI_SAS_ATA=y +CONFIG_SCSI_SAS_HOST_SMP=y +CONFIG_SCSI_SRP_ATTRS=m +# end of SCSI Transports + +CONFIG_SCSI_LOWLEVEL=y +CONFIG_ISCSI_TCP=m +CONFIG_ISCSI_BOOT_SYSFS=m +CONFIG_SCSI_CXGB3_ISCSI=m +CONFIG_SCSI_CXGB4_ISCSI=m +CONFIG_SCSI_BNX2_ISCSI=m +CONFIG_SCSI_BNX2X_FCOE=m +CONFIG_BE2ISCSI=m +CONFIG_BLK_DEV_3W_XXXX_RAID=m +CONFIG_SCSI_HPSA=m +CONFIG_SCSI_3W_9XXX=m +CONFIG_SCSI_3W_SAS=m +CONFIG_SCSI_ACARD=m +CONFIG_SCSI_AACRAID=m +CONFIG_SCSI_AIC7XXX=m +CONFIG_AIC7XXX_CMDS_PER_DEVICE=253 +CONFIG_AIC7XXX_RESET_DELAY_MS=15000 +# CONFIG_AIC7XXX_DEBUG_ENABLE is not set +CONFIG_AIC7XXX_DEBUG_MASK=0 +CONFIG_AIC7XXX_REG_PRETTY_PRINT=y +CONFIG_SCSI_AIC79XX=m +CONFIG_AIC79XX_CMDS_PER_DEVICE=32 +CONFIG_AIC79XX_RESET_DELAY_MS=15000 +# CONFIG_AIC79XX_DEBUG_ENABLE is not set +CONFIG_AIC79XX_DEBUG_MASK=0 +CONFIG_AIC79XX_REG_PRETTY_PRINT=y +CONFIG_SCSI_AIC94XX=m +CONFIG_AIC94XX_DEBUG=y +CONFIG_SCSI_MVSAS=m +CONFIG_SCSI_MVSAS_DEBUG=y +# CONFIG_SCSI_MVSAS_TASKLET is not set +CONFIG_SCSI_MVUMI=m +CONFIG_SCSI_DPT_I2O=m +CONFIG_SCSI_ADVANSYS=m +CONFIG_SCSI_ARCMSR=m +CONFIG_SCSI_ESAS2R=m +CONFIG_MEGARAID_NEWGEN=y +CONFIG_MEGARAID_MM=m +CONFIG_MEGARAID_MAILBOX=m +CONFIG_MEGARAID_LEGACY=m +CONFIG_MEGARAID_SAS=m +CONFIG_SCSI_MPT3SAS=m +CONFIG_SCSI_MPT2SAS_MAX_SGE=128 +CONFIG_SCSI_MPT3SAS_MAX_SGE=128 +CONFIG_SCSI_MPT2SAS=m +CONFIG_SCSI_SMARTPQI=m +CONFIG_SCSI_UFSHCD=m +CONFIG_SCSI_UFSHCD_PCI=m +# CONFIG_SCSI_UFS_DWC_TC_PCI is not set +# CONFIG_SCSI_UFSHCD_PLATFORM is not set +CONFIG_SCSI_UFS_BSG=y +CONFIG_SCSI_HPTIOP=m +CONFIG_SCSI_BUSLOGIC=m +CONFIG_SCSI_FLASHPOINT=y +CONFIG_SCSI_MYRB=m +CONFIG_SCSI_MYRS=m +CONFIG_VMWARE_PVSCSI=m +CONFIG_XEN_SCSI_FRONTEND=m +CONFIG_HYPERV_STORAGE=m +CONFIG_LIBFC=m +CONFIG_LIBFCOE=m +CONFIG_FCOE=m +CONFIG_FCOE_FNIC=m +CONFIG_SCSI_SNIC=m +# CONFIG_SCSI_SNIC_DEBUG_FS is not set +CONFIG_SCSI_DMX3191D=m +CONFIG_SCSI_FDOMAIN=m +CONFIG_SCSI_FDOMAIN_PCI=m +CONFIG_SCSI_GDTH=m +CONFIG_SCSI_ISCI=m +CONFIG_SCSI_IPS=m +CONFIG_SCSI_INITIO=m +CONFIG_SCSI_INIA100=m +CONFIG_SCSI_PPA=m +CONFIG_SCSI_IMM=m +# CONFIG_SCSI_IZIP_EPP16 is not set +# CONFIG_SCSI_IZIP_SLOW_CTR is not set +CONFIG_SCSI_STEX=m +CONFIG_SCSI_SYM53C8XX_2=m +CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0 +CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 +CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 +CONFIG_SCSI_SYM53C8XX_MMIO=y +CONFIG_SCSI_IPR=m +# CONFIG_SCSI_IPR_TRACE is not set +# CONFIG_SCSI_IPR_DUMP is not set +CONFIG_SCSI_QLOGIC_1280=m +CONFIG_SCSI_QLA_FC=m +CONFIG_TCM_QLA2XXX=m +# CONFIG_TCM_QLA2XXX_DEBUG is not set +CONFIG_SCSI_QLA_ISCSI=m +CONFIG_QEDI=m +CONFIG_QEDF=m +CONFIG_SCSI_LPFC=m +# CONFIG_SCSI_LPFC_DEBUG_FS is not set +CONFIG_SCSI_DC395x=m +CONFIG_SCSI_AM53C974=m +CONFIG_SCSI_WD719X=m +CONFIG_SCSI_DEBUG=m +CONFIG_SCSI_PMCRAID=m +CONFIG_SCSI_PM8001=m +CONFIG_SCSI_BFA_FC=m +CONFIG_SCSI_VIRTIO=m +CONFIG_SCSI_CHELSIO_FCOE=m +CONFIG_SCSI_LOWLEVEL_PCMCIA=y +CONFIG_PCMCIA_AHA152X=m +CONFIG_PCMCIA_FDOMAIN=m +CONFIG_PCMCIA_QLOGIC=m +CONFIG_PCMCIA_SYM53C500=m +CONFIG_SCSI_DH=y +CONFIG_SCSI_DH_RDAC=m +CONFIG_SCSI_DH_HP_SW=m +CONFIG_SCSI_DH_EMC=m +CONFIG_SCSI_DH_ALUA=m +# end of SCSI device support + +CONFIG_ATA=y +CONFIG_ATA_VERBOSE_ERROR=y +CONFIG_ATA_ACPI=y +CONFIG_SATA_ZPODD=y +CONFIG_SATA_PMP=y + +# +# Controllers with non-SFF native interface +# +CONFIG_SATA_AHCI=y +CONFIG_SATA_MOBILE_LPM_POLICY=0 +CONFIG_SATA_AHCI_PLATFORM=y +# CONFIG_SATA_INIC162X is not set +CONFIG_SATA_ACARD_AHCI=m +CONFIG_SATA_SIL24=m +CONFIG_ATA_SFF=y + +# +# SFF controllers with custom DMA interface +# +CONFIG_PDC_ADMA=m +CONFIG_SATA_QSTOR=m +CONFIG_SATA_SX4=m +CONFIG_ATA_BMDMA=y + +# +# SATA SFF controllers with BMDMA +# +CONFIG_ATA_PIIX=m +# CONFIG_SATA_DWC is not set +CONFIG_SATA_MV=m +CONFIG_SATA_NV=m +CONFIG_SATA_PROMISE=m +CONFIG_SATA_SIL=m +CONFIG_SATA_SIS=m +CONFIG_SATA_SVW=m +CONFIG_SATA_ULI=m +CONFIG_SATA_VIA=m +CONFIG_SATA_VITESSE=m + +# +# PATA SFF controllers with BMDMA +# +CONFIG_PATA_ALI=m +CONFIG_PATA_AMD=m +CONFIG_PATA_ARTOP=m +CONFIG_PATA_ATIIXP=m +CONFIG_PATA_ATP867X=m +CONFIG_PATA_CMD64X=m +CONFIG_PATA_CYPRESS=m +CONFIG_PATA_EFAR=m +CONFIG_PATA_HPT366=m +CONFIG_PATA_HPT37X=m +CONFIG_PATA_HPT3X2N=m +CONFIG_PATA_HPT3X3=m +CONFIG_PATA_HPT3X3_DMA=y +CONFIG_PATA_IT8213=m +CONFIG_PATA_IT821X=m +CONFIG_PATA_JMICRON=m +CONFIG_PATA_MARVELL=m +CONFIG_PATA_NETCELL=m +CONFIG_PATA_NINJA32=m +CONFIG_PATA_NS87415=m +CONFIG_PATA_OLDPIIX=m +CONFIG_PATA_OPTIDMA=m +CONFIG_PATA_PDC2027X=m +CONFIG_PATA_PDC_OLD=m +CONFIG_PATA_RADISYS=m +CONFIG_PATA_RDC=m +CONFIG_PATA_SCH=m +CONFIG_PATA_SERVERWORKS=m +CONFIG_PATA_SIL680=m +CONFIG_PATA_SIS=m +CONFIG_PATA_TOSHIBA=m +CONFIG_PATA_TRIFLEX=m +CONFIG_PATA_VIA=m +CONFIG_PATA_WINBOND=m + +# +# PIO-only SFF controllers +# +CONFIG_PATA_CMD640_PCI=m +CONFIG_PATA_MPIIX=m +CONFIG_PATA_NS87410=m +CONFIG_PATA_OPTI=m +CONFIG_PATA_PCMCIA=m +# CONFIG_PATA_PLATFORM is not set +CONFIG_PATA_RZ1000=m + +# +# Generic fallback / legacy drivers +# +CONFIG_PATA_ACPI=m +CONFIG_ATA_GENERIC=m +CONFIG_PATA_LEGACY=m +CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +# CONFIG_MD_AUTODETECT is not set +CONFIG_MD_LINEAR=m +CONFIG_MD_RAID0=m +CONFIG_MD_RAID1=m +CONFIG_MD_RAID10=m +CONFIG_MD_RAID456=m +CONFIG_MD_MULTIPATH=m +CONFIG_MD_FAULTY=m +CONFIG_MD_CLUSTER=m +CONFIG_BCACHE=m +# CONFIG_BCACHE_DEBUG is not set +# CONFIG_BCACHE_CLOSURES_DEBUG is not set +CONFIG_BLK_DEV_DM_BUILTIN=y +CONFIG_BLK_DEV_DM=m +# CONFIG_DM_DEBUG is not set +CONFIG_DM_BUFIO=m +# CONFIG_DM_DEBUG_BLOCK_MANAGER_LOCKING is not set +CONFIG_DM_BIO_PRISON=m +CONFIG_DM_PERSISTENT_DATA=m +CONFIG_DM_UNSTRIPED=m +CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_THIN_PROVISIONING=m +CONFIG_DM_CACHE=m +CONFIG_DM_CACHE_SMQ=m +CONFIG_DM_WRITECACHE=m +CONFIG_DM_ERA=m +CONFIG_DM_CLONE=m +CONFIG_DM_MIRROR=m +CONFIG_DM_LOG_USERSPACE=m +CONFIG_DM_RAID=m +CONFIG_DM_ZERO=m +CONFIG_DM_MULTIPATH=m +CONFIG_DM_MULTIPATH_QL=m +CONFIG_DM_MULTIPATH_ST=m +# CONFIG_DM_DELAY is not set +# CONFIG_DM_DUST is not set +CONFIG_DM_UEVENT=y +CONFIG_DM_FLAKEY=m +CONFIG_DM_VERITY=m +# CONFIG_DM_VERITY_VERIFY_ROOTHASH_SIG is not set +# CONFIG_DM_VERITY_FEC is not set +CONFIG_DM_SWITCH=m +CONFIG_DM_LOG_WRITES=m +CONFIG_DM_INTEGRITY=m +CONFIG_TARGET_CORE=m +CONFIG_TCM_IBLOCK=m +CONFIG_TCM_FILEIO=m +CONFIG_TCM_PSCSI=m +CONFIG_TCM_USER2=m +CONFIG_LOOPBACK_TARGET=m +CONFIG_TCM_FC=m +CONFIG_ISCSI_TARGET=m +CONFIG_ISCSI_TARGET_CXGB4=m +CONFIG_SBP_TARGET=m +CONFIG_FUSION=y +CONFIG_FUSION_SPI=m +CONFIG_FUSION_FC=m +CONFIG_FUSION_SAS=m +CONFIG_FUSION_MAX_SGE=128 +CONFIG_FUSION_CTL=m +CONFIG_FUSION_LAN=m +CONFIG_FUSION_LOGGING=y + +# +# IEEE 1394 (FireWire) support +# +CONFIG_FIREWIRE=m +CONFIG_FIREWIRE_OHCI=m +CONFIG_FIREWIRE_SBP2=m +CONFIG_FIREWIRE_NET=m +CONFIG_FIREWIRE_NOSY=m +# end of IEEE 1394 (FireWire) support + +CONFIG_MACINTOSH_DRIVERS=y +CONFIG_MAC_EMUMOUSEBTN=y +CONFIG_NETDEVICES=y +CONFIG_MII=m +CONFIG_NET_CORE=y +CONFIG_BONDING=m +CONFIG_DUMMY=m +CONFIG_EQUALIZER=m +CONFIG_NET_FC=y +CONFIG_IFB=m +CONFIG_NET_TEAM=m +CONFIG_NET_TEAM_MODE_BROADCAST=m +CONFIG_NET_TEAM_MODE_ROUNDROBIN=m +CONFIG_NET_TEAM_MODE_RANDOM=m +CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m +CONFIG_NET_TEAM_MODE_LOADBALANCE=m +CONFIG_MACVLAN=m +CONFIG_MACVTAP=m +CONFIG_IPVLAN_L3S=y +CONFIG_IPVLAN=m +CONFIG_IPVTAP=m +CONFIG_VXLAN=m +CONFIG_GENEVE=m +CONFIG_GTP=m +CONFIG_MACSEC=m +CONFIG_NETCONSOLE=m +CONFIG_NETCONSOLE_DYNAMIC=y +CONFIG_NETPOLL=y +CONFIG_NET_POLL_CONTROLLER=y +CONFIG_NTB_NETDEV=m +CONFIG_RIONET=m +CONFIG_RIONET_TX_SIZE=128 +CONFIG_RIONET_RX_SIZE=128 +CONFIG_TUN=m +CONFIG_TAP=m +# CONFIG_TUN_VNET_CROSS_LE is not set +CONFIG_VETH=m +CONFIG_VIRTIO_NET=m +CONFIG_NLMON=m +CONFIG_NET_VRF=m +CONFIG_VSOCKMON=m +CONFIG_SUNGEM_PHY=m +CONFIG_ARCNET=m +CONFIG_ARCNET_1201=m +CONFIG_ARCNET_1051=m +CONFIG_ARCNET_RAW=m +CONFIG_ARCNET_CAP=m +CONFIG_ARCNET_COM90xx=m +CONFIG_ARCNET_COM90xxIO=m +CONFIG_ARCNET_RIM_I=m +CONFIG_ARCNET_COM20020=m +CONFIG_ARCNET_COM20020_PCI=m +CONFIG_ARCNET_COM20020_CS=m +CONFIG_ATM_DRIVERS=y +# CONFIG_ATM_DUMMY is not set +CONFIG_ATM_TCP=m +CONFIG_ATM_LANAI=m +CONFIG_ATM_ENI=m +# CONFIG_ATM_ENI_DEBUG is not set +# CONFIG_ATM_ENI_TUNE_BURST is not set +CONFIG_ATM_FIRESTREAM=m +CONFIG_ATM_ZATM=m +# CONFIG_ATM_ZATM_DEBUG is not set +# CONFIG_ATM_NICSTAR is not set +CONFIG_ATM_IDT77252=m +# CONFIG_ATM_IDT77252_DEBUG is not set +# CONFIG_ATM_IDT77252_RCV_ALL is not set +CONFIG_ATM_IDT77252_USE_SUNI=y +CONFIG_ATM_AMBASSADOR=m +# CONFIG_ATM_AMBASSADOR_DEBUG is not set +CONFIG_ATM_HORIZON=m +# CONFIG_ATM_HORIZON_DEBUG is not set +CONFIG_ATM_IA=m +# CONFIG_ATM_IA_DEBUG is not set +CONFIG_ATM_FORE200E=m +CONFIG_ATM_FORE200E_USE_TASKLET=y +CONFIG_ATM_FORE200E_TX_RETRY=16 +CONFIG_ATM_FORE200E_DEBUG=0 +CONFIG_ATM_HE=m +CONFIG_ATM_HE_USE_SUNI=y +CONFIG_ATM_SOLOS=m + +# +# CAIF transport drivers +# +CONFIG_CAIF_TTY=m +CONFIG_CAIF_SPI_SLAVE=m +# CONFIG_CAIF_SPI_SYNC is not set +CONFIG_CAIF_HSI=m +CONFIG_CAIF_VIRTIO=m + +# +# Distributed Switch Architecture drivers +# +CONFIG_B53=m +CONFIG_B53_SPI_DRIVER=m +CONFIG_B53_MDIO_DRIVER=m +CONFIG_B53_MMAP_DRIVER=m +CONFIG_B53_SRAB_DRIVER=m +CONFIG_B53_SERDES=m +CONFIG_NET_DSA_BCM_SF2=m +# CONFIG_NET_DSA_LOOP is not set +CONFIG_NET_DSA_LANTIQ_GSWIP=m +# CONFIG_NET_DSA_MT7530 is not set +CONFIG_NET_DSA_MV88E6060=m +# CONFIG_NET_DSA_MICROCHIP_KSZ9477 is not set +# CONFIG_NET_DSA_MICROCHIP_KSZ8795 is not set +# CONFIG_NET_DSA_MV88E6XXX is not set +# CONFIG_NET_DSA_SJA1105 is not set +# CONFIG_NET_DSA_QCA8K is not set +CONFIG_NET_DSA_REALTEK_SMI=m +# CONFIG_NET_DSA_SMSC_LAN9303_I2C is not set +# CONFIG_NET_DSA_SMSC_LAN9303_MDIO is not set +# end of Distributed Switch Architecture drivers + +CONFIG_ETHERNET=y +CONFIG_MDIO=m +CONFIG_NET_VENDOR_3COM=y +CONFIG_PCMCIA_3C574=m +CONFIG_PCMCIA_3C589=m +CONFIG_VORTEX=m +CONFIG_TYPHOON=m +CONFIG_NET_VENDOR_ADAPTEC=y +CONFIG_ADAPTEC_STARFIRE=m +CONFIG_NET_VENDOR_AGERE=y +CONFIG_ET131X=m +CONFIG_NET_VENDOR_ALACRITECH=y +CONFIG_SLICOSS=m +CONFIG_NET_VENDOR_ALTEON=y +CONFIG_ACENIC=m +# CONFIG_ACENIC_OMIT_TIGON_I is not set +CONFIG_ALTERA_TSE=m +CONFIG_NET_VENDOR_AMAZON=y +CONFIG_ENA_ETHERNET=m +CONFIG_NET_VENDOR_AMD=y +CONFIG_AMD8111_ETH=m +CONFIG_PCNET32=m +CONFIG_PCMCIA_NMCLAN=m +CONFIG_AMD_XGBE=m +CONFIG_AMD_XGBE_DCB=y +CONFIG_AMD_XGBE_HAVE_ECC=y +CONFIG_NET_VENDOR_AQUANTIA=y +CONFIG_AQTION=m +CONFIG_NET_VENDOR_ARC=y +CONFIG_NET_VENDOR_ATHEROS=y +CONFIG_ATL2=m +CONFIG_ATL1=m +CONFIG_ATL1E=m +CONFIG_ATL1C=m +CONFIG_ALX=m +CONFIG_NET_VENDOR_AURORA=y +CONFIG_AURORA_NB8800=m +CONFIG_NET_VENDOR_BROADCOM=y +CONFIG_B44=m +CONFIG_B44_PCI_AUTOSELECT=y +CONFIG_B44_PCICORE_AUTOSELECT=y +CONFIG_B44_PCI=y +CONFIG_BCMGENET=m +CONFIG_BNX2=m +CONFIG_CNIC=m +CONFIG_TIGON3=m +CONFIG_TIGON3_HWMON=y +CONFIG_BNX2X=m +CONFIG_BNX2X_SRIOV=y +CONFIG_SYSTEMPORT=m +CONFIG_BNXT=m +CONFIG_BNXT_SRIOV=y +CONFIG_BNXT_FLOWER_OFFLOAD=y +CONFIG_BNXT_DCB=y +CONFIG_BNXT_HWMON=y +CONFIG_NET_VENDOR_BROCADE=y +CONFIG_BNA=m +CONFIG_NET_VENDOR_CADENCE=y +CONFIG_MACB=m +CONFIG_MACB_USE_HWSTAMP=y +CONFIG_MACB_PCI=m +CONFIG_NET_VENDOR_CAVIUM=y +CONFIG_THUNDER_NIC_PF=m +CONFIG_THUNDER_NIC_VF=m +CONFIG_THUNDER_NIC_BGX=m +CONFIG_THUNDER_NIC_RGX=m +CONFIG_CAVIUM_PTP=m +CONFIG_LIQUIDIO=m +CONFIG_LIQUIDIO_VF=m +CONFIG_NET_VENDOR_CHELSIO=y +CONFIG_CHELSIO_T1=m +CONFIG_CHELSIO_T1_1G=y +CONFIG_CHELSIO_T3=m +CONFIG_CHELSIO_T4=m +CONFIG_CHELSIO_T4_DCB=y +CONFIG_CHELSIO_T4_FCOE=y +CONFIG_CHELSIO_T4VF=m +CONFIG_CHELSIO_LIB=m +CONFIG_NET_VENDOR_CISCO=y +CONFIG_ENIC=m +CONFIG_NET_VENDOR_CORTINA=y +CONFIG_CX_ECAT=m +# CONFIG_DNET is not set +CONFIG_NET_VENDOR_DEC=y +CONFIG_NET_TULIP=y +CONFIG_DE2104X=m +CONFIG_DE2104X_DSL=0 +CONFIG_TULIP=m +# CONFIG_TULIP_MWI is not set +# CONFIG_TULIP_MMIO is not set +# CONFIG_TULIP_NAPI is not set +CONFIG_DE4X5=m +CONFIG_WINBOND_840=m +CONFIG_DM9102=m +CONFIG_ULI526X=m +CONFIG_PCMCIA_XIRCOM=m +CONFIG_NET_VENDOR_DLINK=y +CONFIG_DL2K=m +CONFIG_SUNDANCE=m +# CONFIG_SUNDANCE_MMIO is not set +CONFIG_NET_VENDOR_EMULEX=y +CONFIG_BE2NET=m +CONFIG_BE2NET_HWMON=y +CONFIG_BE2NET_BE2=y +CONFIG_BE2NET_BE3=y +CONFIG_BE2NET_LANCER=y +CONFIG_BE2NET_SKYHAWK=y +CONFIG_NET_VENDOR_EZCHIP=y +CONFIG_NET_VENDOR_FUJITSU=y +CONFIG_PCMCIA_FMVJ18X=m +CONFIG_NET_VENDOR_GOOGLE=y +CONFIG_GVE=m +CONFIG_NET_VENDOR_HP=y +CONFIG_HP100=m +CONFIG_NET_VENDOR_HUAWEI=y +CONFIG_HINIC=m +CONFIG_NET_VENDOR_I825XX=y +CONFIG_NET_VENDOR_INTEL=y +CONFIG_E100=m +CONFIG_E1000=m +CONFIG_E1000E=m +CONFIG_E1000E_HWTS=y +CONFIG_IGB=m +CONFIG_IGB_HWMON=y +CONFIG_IGB_DCA=y +CONFIG_IGBVF=m +CONFIG_IXGB=m +CONFIG_IXGBE=m +CONFIG_IXGBE_HWMON=y +CONFIG_IXGBE_DCA=y +CONFIG_IXGBE_DCB=y +CONFIG_IXGBE_IPSEC=y +CONFIG_IXGBEVF=m +CONFIG_IXGBEVF_IPSEC=y +CONFIG_I40E=m +CONFIG_I40E_DCB=y +CONFIG_IAVF=m +CONFIG_I40EVF=m +CONFIG_ICE=m +CONFIG_FM10K=m +CONFIG_IGC=m +CONFIG_JME=m +CONFIG_NET_VENDOR_MARVELL=y +CONFIG_MVMDIO=m +CONFIG_SKGE=m +# CONFIG_SKGE_DEBUG is not set +CONFIG_SKGE_GENESIS=y +CONFIG_SKY2=m +# CONFIG_SKY2_DEBUG is not set +CONFIG_NET_VENDOR_MELLANOX=y +CONFIG_MLX4_EN=m +CONFIG_MLX4_EN_DCB=y +CONFIG_MLX4_CORE=m +# CONFIG_MLX4_DEBUG is not set +CONFIG_MLX4_CORE_GEN2=y +CONFIG_MLX5_CORE=m +CONFIG_MLX5_ACCEL=y +CONFIG_MLX5_FPGA=y +CONFIG_MLX5_CORE_EN=y +CONFIG_MLX5_EN_ARFS=y +CONFIG_MLX5_EN_RXNFC=y +CONFIG_MLX5_MPFS=y +CONFIG_MLX5_ESWITCH=y +CONFIG_MLX5_CORE_EN_DCB=y +# CONFIG_MLX5_CORE_IPOIB is not set +CONFIG_MLX5_FPGA_IPSEC=y +# CONFIG_MLX5_EN_IPSEC is not set +CONFIG_MLX5_SW_STEERING=y +CONFIG_MLXSW_CORE=m +CONFIG_MLXSW_CORE_HWMON=y +CONFIG_MLXSW_CORE_THERMAL=y +CONFIG_MLXSW_PCI=m +CONFIG_MLXSW_I2C=m +CONFIG_MLXSW_SWITCHIB=m +CONFIG_MLXSW_SWITCHX2=m +CONFIG_MLXSW_SPECTRUM=m +CONFIG_MLXSW_SPECTRUM_DCB=y +CONFIG_MLXSW_MINIMAL=m +CONFIG_MLXFW=m +CONFIG_NET_VENDOR_MICREL=y +CONFIG_KS8842=m +CONFIG_KS8851=m +# CONFIG_KS8851_MLL is not set +CONFIG_KSZ884X_PCI=m +CONFIG_NET_VENDOR_MICROCHIP=y +CONFIG_ENC28J60=m +# CONFIG_ENC28J60_WRITEVERIFY is not set +CONFIG_ENCX24J600=m +CONFIG_LAN743X=m +CONFIG_NET_VENDOR_MICROSEMI=y +CONFIG_MSCC_OCELOT_SWITCH=m +CONFIG_NET_VENDOR_MYRI=y +CONFIG_MYRI10GE=m +CONFIG_MYRI10GE_DCA=y +CONFIG_FEALNX=m +CONFIG_NET_VENDOR_NATSEMI=y +CONFIG_NATSEMI=m +CONFIG_NS83820=m +CONFIG_NET_VENDOR_NETERION=y +CONFIG_S2IO=m +CONFIG_VXGE=m +# CONFIG_VXGE_DEBUG_TRACE_ALL is not set +CONFIG_NET_VENDOR_NETRONOME=y +CONFIG_NFP=m +# CONFIG_NFP_APP_FLOWER is not set +CONFIG_NFP_APP_ABM_NIC=y +# CONFIG_NFP_DEBUG is not set +CONFIG_NET_VENDOR_NI=y +CONFIG_NI_XGE_MANAGEMENT_ENET=m +CONFIG_NET_VENDOR_8390=y +CONFIG_PCMCIA_AXNET=m +CONFIG_NE2K_PCI=m +CONFIG_PCMCIA_PCNET=m +CONFIG_NET_VENDOR_NVIDIA=y +CONFIG_FORCEDETH=m +CONFIG_NET_VENDOR_OKI=y +CONFIG_ETHOC=m +CONFIG_NET_VENDOR_PACKET_ENGINES=y +CONFIG_HAMACHI=m +CONFIG_YELLOWFIN=m +CONFIG_NET_VENDOR_PENSANDO=y +CONFIG_IONIC=m +CONFIG_NET_VENDOR_QLOGIC=y +CONFIG_QLA3XXX=m +CONFIG_QLCNIC=m +CONFIG_QLCNIC_SRIOV=y +CONFIG_QLCNIC_DCB=y +CONFIG_QLCNIC_HWMON=y +CONFIG_NETXEN_NIC=m +CONFIG_QED=m +CONFIG_QED_LL2=y +CONFIG_QED_SRIOV=y +CONFIG_QEDE=m +CONFIG_QED_RDMA=y +CONFIG_QED_ISCSI=y +CONFIG_QED_FCOE=y +CONFIG_QED_OOO=y +CONFIG_NET_VENDOR_QUALCOMM=y +CONFIG_QCOM_EMAC=m +CONFIG_RMNET=m +CONFIG_NET_VENDOR_RDC=y +CONFIG_R6040=m +CONFIG_NET_VENDOR_REALTEK=y +CONFIG_ATP=m +CONFIG_8139CP=m +CONFIG_8139TOO=m +# CONFIG_8139TOO_PIO is not set +# CONFIG_8139TOO_TUNE_TWISTER is not set +CONFIG_8139TOO_8129=y +# CONFIG_8139_OLD_RX_RESET is not set +CONFIG_R8169=m +CONFIG_NET_VENDOR_RENESAS=y +CONFIG_NET_VENDOR_ROCKER=y +# CONFIG_ROCKER is not set +CONFIG_NET_VENDOR_SAMSUNG=y +CONFIG_SXGBE_ETH=m +CONFIG_NET_VENDOR_SEEQ=y +CONFIG_NET_VENDOR_SOLARFLARE=y +CONFIG_SFC=m +CONFIG_SFC_MTD=y +CONFIG_SFC_MCDI_MON=y +CONFIG_SFC_SRIOV=y +CONFIG_SFC_MCDI_LOGGING=y +CONFIG_SFC_FALCON=m +CONFIG_SFC_FALCON_MTD=y +CONFIG_NET_VENDOR_SILAN=y +CONFIG_SC92031=m +CONFIG_NET_VENDOR_SIS=y +CONFIG_SIS900=m +CONFIG_SIS190=m +CONFIG_NET_VENDOR_SMSC=y +CONFIG_PCMCIA_SMC91C92=m +CONFIG_EPIC100=m +CONFIG_SMSC911X=m +CONFIG_SMSC9420=m +CONFIG_NET_VENDOR_SOCIONEXT=y +CONFIG_NET_VENDOR_STMICRO=y +CONFIG_STMMAC_ETH=m +# CONFIG_STMMAC_SELFTESTS is not set +CONFIG_STMMAC_PLATFORM=m +CONFIG_DWMAC_GENERIC=m +# CONFIG_STMMAC_PCI is not set +CONFIG_NET_VENDOR_SUN=y +CONFIG_HAPPYMEAL=m +CONFIG_SUNGEM=m +CONFIG_CASSINI=m +CONFIG_NIU=m +CONFIG_NET_VENDOR_SYNOPSYS=y +CONFIG_DWC_XLGMAC=m +CONFIG_DWC_XLGMAC_PCI=m +CONFIG_NET_VENDOR_TEHUTI=y +CONFIG_TEHUTI=m +CONFIG_NET_VENDOR_TI=y +# CONFIG_TI_CPSW_PHY_SEL is not set +CONFIG_TLAN=m +CONFIG_NET_VENDOR_VIA=y +CONFIG_VIA_RHINE=m +# CONFIG_VIA_RHINE_MMIO is not set +CONFIG_VIA_VELOCITY=m +CONFIG_NET_VENDOR_WIZNET=y +CONFIG_WIZNET_W5100=m +CONFIG_WIZNET_W5300=m +# CONFIG_WIZNET_BUS_DIRECT is not set +# CONFIG_WIZNET_BUS_INDIRECT is not set +CONFIG_WIZNET_BUS_ANY=y +CONFIG_WIZNET_W5100_SPI=m +CONFIG_NET_VENDOR_XILINX=y +CONFIG_XILINX_AXI_EMAC=m +# CONFIG_XILINX_LL_TEMAC is not set +CONFIG_NET_VENDOR_XIRCOM=y +CONFIG_PCMCIA_XIRC2PS=m +CONFIG_FDDI=y +CONFIG_DEFXX=m +# CONFIG_DEFXX_MMIO is not set +CONFIG_SKFP=m +# CONFIG_HIPPI is not set +CONFIG_NET_SB1000=m +CONFIG_MDIO_DEVICE=m +CONFIG_MDIO_BUS=m +CONFIG_MDIO_BCM_UNIMAC=m +CONFIG_MDIO_BITBANG=m +CONFIG_MDIO_CAVIUM=m +CONFIG_MDIO_GPIO=m +CONFIG_MDIO_I2C=m +CONFIG_MDIO_MSCC_MIIM=m +CONFIG_MDIO_THUNDER=m +CONFIG_PHYLINK=m +CONFIG_PHYLIB=m +CONFIG_SWPHY=y +# CONFIG_LED_TRIGGER_PHY is not set + +# +# MII PHY device drivers +# +CONFIG_SFP=m +CONFIG_ADIN_PHY=m +CONFIG_AMD_PHY=m +CONFIG_AQUANTIA_PHY=m +# CONFIG_AX88796B_PHY is not set +CONFIG_AT803X_PHY=m +CONFIG_BCM7XXX_PHY=m +CONFIG_BCM87XX_PHY=m +CONFIG_BCM_NET_PHYLIB=m +CONFIG_BROADCOM_PHY=m +CONFIG_CICADA_PHY=m +CONFIG_CORTINA_PHY=m +CONFIG_DAVICOM_PHY=m +# CONFIG_DP83822_PHY is not set +# CONFIG_DP83TC811_PHY is not set +CONFIG_DP83848_PHY=m +CONFIG_DP83867_PHY=m +CONFIG_FIXED_PHY=m +CONFIG_ICPLUS_PHY=m +CONFIG_INTEL_XWAY_PHY=m +CONFIG_LSI_ET1011C_PHY=m +CONFIG_LXT_PHY=m +CONFIG_MARVELL_PHY=m +CONFIG_MARVELL_10G_PHY=m +CONFIG_MICREL_PHY=m +CONFIG_MICROCHIP_PHY=m +CONFIG_MICROCHIP_T1_PHY=m +CONFIG_MICROSEMI_PHY=m +CONFIG_NATIONAL_PHY=m +CONFIG_NXP_TJA11XX_PHY=m +CONFIG_QSEMI_PHY=m +CONFIG_REALTEK_PHY=m +# CONFIG_RENESAS_PHY is not set +CONFIG_ROCKCHIP_PHY=m +CONFIG_SMSC_PHY=m +CONFIG_STE10XP=m +CONFIG_TERANETICS_PHY=m +CONFIG_VITESSE_PHY=m +CONFIG_XILINX_GMII2RGMII=m +CONFIG_MICREL_KS8995MA=m +CONFIG_PLIP=m +CONFIG_PPP=m +CONFIG_PPP_BSDCOMP=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_FILTER=y +CONFIG_PPP_MPPE=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPPOATM=m +CONFIG_PPPOE=m +CONFIG_PPTP=m +CONFIG_PPPOL2TP=m +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_SLIP=m +CONFIG_SLHC=m +CONFIG_SLIP_COMPRESSED=y +CONFIG_SLIP_SMART=y +CONFIG_SLIP_MODE_SLIP6=y + +# +# Host-side USB support is needed for USB Network Adapter support +# +CONFIG_USB_NET_DRIVERS=m +CONFIG_USB_CATC=m +CONFIG_USB_KAWETH=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_RTL8152=m +CONFIG_USB_LAN78XX=m +CONFIG_USB_USBNET=m +CONFIG_USB_NET_AX8817X=m +CONFIG_USB_NET_AX88179_178A=m +CONFIG_USB_NET_CDCETHER=m +CONFIG_USB_NET_CDC_EEM=m +CONFIG_USB_NET_CDC_NCM=m +CONFIG_USB_NET_HUAWEI_CDC_NCM=m +CONFIG_USB_NET_CDC_MBIM=m +CONFIG_USB_NET_DM9601=m +CONFIG_USB_NET_SR9700=m +CONFIG_USB_NET_SR9800=m +CONFIG_USB_NET_SMSC75XX=m +CONFIG_USB_NET_SMSC95XX=m +CONFIG_USB_NET_GL620A=m +CONFIG_USB_NET_NET1080=m +CONFIG_USB_NET_PLUSB=m +CONFIG_USB_NET_MCS7830=m +CONFIG_USB_NET_RNDIS_HOST=m +CONFIG_USB_NET_CDC_SUBSET_ENABLE=m +CONFIG_USB_NET_CDC_SUBSET=m +CONFIG_USB_ALI_M5632=y +CONFIG_USB_AN2720=y +CONFIG_USB_BELKIN=y +CONFIG_USB_ARMLINUX=y +CONFIG_USB_EPSON2888=y +CONFIG_USB_KC2190=y +CONFIG_USB_NET_ZAURUS=m +CONFIG_USB_NET_CX82310_ETH=m +CONFIG_USB_NET_KALMIA=m +CONFIG_USB_NET_QMI_WWAN=m +CONFIG_USB_HSO=m +CONFIG_USB_NET_INT51X1=m +CONFIG_USB_CDC_PHONET=m +CONFIG_USB_IPHETH=m +CONFIG_USB_SIERRA_NET=m +CONFIG_USB_VL600=m +CONFIG_USB_NET_CH9200=m +CONFIG_USB_NET_AQC111=m +CONFIG_WLAN=y +# CONFIG_WIRELESS_WDS is not set +CONFIG_WLAN_VENDOR_ADMTEK=y +CONFIG_ADM8211=m +CONFIG_ATH_COMMON=m +CONFIG_WLAN_VENDOR_ATH=y +CONFIG_ATH_DEBUG=y +# CONFIG_ATH_TRACEPOINTS is not set +CONFIG_ATH5K=m +CONFIG_ATH5K_DEBUG=y +# CONFIG_ATH5K_TRACER is not set +CONFIG_ATH5K_PCI=y +CONFIG_ATH9K_HW=m +CONFIG_ATH9K_COMMON=m +CONFIG_ATH9K_BTCOEX_SUPPORT=y +CONFIG_ATH9K=m +CONFIG_ATH9K_PCI=y +CONFIG_ATH9K_AHB=y +# CONFIG_ATH9K_DEBUGFS is not set +# CONFIG_ATH9K_DYNACK is not set +CONFIG_ATH9K_WOW=y +CONFIG_ATH9K_RFKILL=y +# CONFIG_ATH9K_CHANNEL_CONTEXT is not set +CONFIG_ATH9K_PCOEM=y +CONFIG_ATH9K_PCI_NO_EEPROM=m +CONFIG_ATH9K_HTC=m +# CONFIG_ATH9K_HTC_DEBUGFS is not set +CONFIG_ATH9K_HWRNG=y +CONFIG_CARL9170=m +CONFIG_CARL9170_LEDS=y +CONFIG_CARL9170_WPC=y +CONFIG_CARL9170_HWRNG=y +CONFIG_ATH6KL=m +CONFIG_ATH6KL_SDIO=m +CONFIG_ATH6KL_USB=m +# CONFIG_ATH6KL_DEBUG is not set +# CONFIG_ATH6KL_TRACING is not set +CONFIG_AR5523=m +CONFIG_WIL6210=m +CONFIG_WIL6210_ISR_COR=y +CONFIG_WIL6210_TRACING=y +# CONFIG_WIL6210_DEBUGFS is not set +CONFIG_ATH10K=m +CONFIG_ATH10K_CE=y +CONFIG_ATH10K_PCI=m +CONFIG_ATH10K_SDIO=m +CONFIG_ATH10K_USB=m +CONFIG_ATH10K_DEBUG=y +# CONFIG_ATH10K_DEBUGFS is not set +# CONFIG_ATH10K_TRACING is not set +CONFIG_WCN36XX=m +# CONFIG_WCN36XX_DEBUGFS is not set +CONFIG_WLAN_VENDOR_ATMEL=y +CONFIG_ATMEL=m +CONFIG_PCI_ATMEL=m +CONFIG_PCMCIA_ATMEL=m +CONFIG_AT76C50X_USB=m +CONFIG_WLAN_VENDOR_BROADCOM=y +CONFIG_B43=m +CONFIG_B43_BCMA=y +CONFIG_B43_SSB=y +CONFIG_B43_BUSES_BCMA_AND_SSB=y +# CONFIG_B43_BUSES_BCMA is not set +# CONFIG_B43_BUSES_SSB is not set +CONFIG_B43_PCI_AUTOSELECT=y +CONFIG_B43_PCICORE_AUTOSELECT=y +CONFIG_B43_SDIO=y +CONFIG_B43_BCMA_PIO=y +CONFIG_B43_PIO=y +CONFIG_B43_PHY_G=y +CONFIG_B43_PHY_N=y +CONFIG_B43_PHY_LP=y +CONFIG_B43_PHY_HT=y +CONFIG_B43_LEDS=y +CONFIG_B43_HWRNG=y +CONFIG_B43_DEBUG=y +CONFIG_B43LEGACY=m +CONFIG_B43LEGACY_PCI_AUTOSELECT=y +CONFIG_B43LEGACY_PCICORE_AUTOSELECT=y +CONFIG_B43LEGACY_LEDS=y +CONFIG_B43LEGACY_HWRNG=y +CONFIG_B43LEGACY_DEBUG=y +CONFIG_B43LEGACY_DMA=y +CONFIG_B43LEGACY_PIO=y +CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y +# CONFIG_B43LEGACY_DMA_MODE is not set +# CONFIG_B43LEGACY_PIO_MODE is not set +CONFIG_BRCMUTIL=m +CONFIG_BRCMSMAC=m +CONFIG_BRCMFMAC=m +CONFIG_BRCMFMAC_PROTO_BCDC=y +CONFIG_BRCMFMAC_PROTO_MSGBUF=y +CONFIG_BRCMFMAC_SDIO=y +CONFIG_BRCMFMAC_USB=y +CONFIG_BRCMFMAC_PCIE=y +# CONFIG_BRCM_TRACING is not set +# CONFIG_BRCMDBG is not set +CONFIG_WLAN_VENDOR_CISCO=y +CONFIG_AIRO=m +CONFIG_AIRO_CS=m +CONFIG_WLAN_VENDOR_INTEL=y +CONFIG_IPW2100=m +CONFIG_IPW2100_MONITOR=y +# CONFIG_IPW2100_DEBUG is not set +CONFIG_IPW2200=m +CONFIG_IPW2200_MONITOR=y +CONFIG_IPW2200_RADIOTAP=y +CONFIG_IPW2200_PROMISCUOUS=y +CONFIG_IPW2200_QOS=y +# CONFIG_IPW2200_DEBUG is not set +CONFIG_LIBIPW=m +# CONFIG_LIBIPW_DEBUG is not set +CONFIG_IWLEGACY=m +CONFIG_IWL4965=m +CONFIG_IWL3945=m + +# +# iwl3945 / iwl4965 Debugging Options +# +# CONFIG_IWLEGACY_DEBUG is not set +# end of iwl3945 / iwl4965 Debugging Options + +CONFIG_IWLWIFI=m +CONFIG_IWLWIFI_LEDS=y +CONFIG_IWLDVM=m +CONFIG_IWLMVM=m +CONFIG_IWLWIFI_OPMODE_MODULAR=y +# CONFIG_IWLWIFI_BCAST_FILTERING is not set + +# +# Debugging Options +# +CONFIG_IWLWIFI_DEBUG=y +# CONFIG_IWLWIFI_DEVICE_TRACING is not set +# end of Debugging Options + +CONFIG_WLAN_VENDOR_INTERSIL=y +CONFIG_HOSTAP=m +CONFIG_HOSTAP_FIRMWARE=y +CONFIG_HOSTAP_FIRMWARE_NVRAM=y +CONFIG_HOSTAP_PLX=m +CONFIG_HOSTAP_PCI=m +CONFIG_HOSTAP_CS=m +CONFIG_HERMES=m +CONFIG_HERMES_PRISM=y +CONFIG_HERMES_CACHE_FW_ON_INIT=y +CONFIG_PLX_HERMES=m +CONFIG_TMD_HERMES=m +CONFIG_NORTEL_HERMES=m +CONFIG_PCI_HERMES=m +CONFIG_PCMCIA_HERMES=m +CONFIG_PCMCIA_SPECTRUM=m +CONFIG_ORINOCO_USB=m +CONFIG_P54_COMMON=m +CONFIG_P54_USB=m +CONFIG_P54_PCI=m +CONFIG_P54_SPI=m +CONFIG_P54_SPI_DEFAULT_EEPROM=y +CONFIG_P54_LEDS=y +CONFIG_PRISM54=m +CONFIG_WLAN_VENDOR_MARVELL=y +CONFIG_LIBERTAS=m +CONFIG_LIBERTAS_USB=m +CONFIG_LIBERTAS_CS=m +CONFIG_LIBERTAS_SDIO=m +CONFIG_LIBERTAS_SPI=m +# CONFIG_LIBERTAS_DEBUG is not set +CONFIG_LIBERTAS_MESH=y +# CONFIG_LIBERTAS_THINFIRM is not set +CONFIG_MWIFIEX=m +CONFIG_MWIFIEX_SDIO=m +CONFIG_MWIFIEX_PCIE=m +CONFIG_MWIFIEX_USB=m +CONFIG_MWL8K=m +CONFIG_WLAN_VENDOR_MEDIATEK=y +CONFIG_MT7601U=m +CONFIG_MT76_CORE=m +CONFIG_MT76_LEDS=y +CONFIG_MT76_USB=m +CONFIG_MT76x02_LIB=m +CONFIG_MT76x02_USB=m +CONFIG_MT76x0_COMMON=m +CONFIG_MT76x0U=m +CONFIG_MT76x0E=m +CONFIG_MT76x2_COMMON=m +CONFIG_MT76x2E=m +CONFIG_MT76x2U=m +CONFIG_MT7603E=m +CONFIG_MT7615E=m +CONFIG_WLAN_VENDOR_RALINK=y +CONFIG_RT2X00=m +CONFIG_RT2400PCI=m +CONFIG_RT2500PCI=m +CONFIG_RT61PCI=m +CONFIG_RT2800PCI=m +CONFIG_RT2800PCI_RT33XX=y +CONFIG_RT2800PCI_RT35XX=y +CONFIG_RT2800PCI_RT53XX=y +CONFIG_RT2800PCI_RT3290=y +CONFIG_RT2500USB=m +CONFIG_RT73USB=m +CONFIG_RT2800USB=m +CONFIG_RT2800USB_RT33XX=y +CONFIG_RT2800USB_RT35XX=y +CONFIG_RT2800USB_RT3573=y +CONFIG_RT2800USB_RT53XX=y +CONFIG_RT2800USB_RT55XX=y +CONFIG_RT2800USB_UNKNOWN=y +CONFIG_RT2800_LIB=m +CONFIG_RT2800_LIB_MMIO=m +CONFIG_RT2X00_LIB_MMIO=m +CONFIG_RT2X00_LIB_PCI=m +CONFIG_RT2X00_LIB_USB=m +CONFIG_RT2X00_LIB=m +CONFIG_RT2X00_LIB_FIRMWARE=y +CONFIG_RT2X00_LIB_CRYPTO=y +CONFIG_RT2X00_LIB_LEDS=y +# CONFIG_RT2X00_DEBUG is not set +CONFIG_WLAN_VENDOR_REALTEK=y +CONFIG_RTL8180=m +CONFIG_RTL8187=m +CONFIG_RTL8187_LEDS=y +CONFIG_RTL_CARDS=m +CONFIG_RTL8192CE=m +CONFIG_RTL8192SE=m +CONFIG_RTL8192DE=m +CONFIG_RTL8723AE=m +CONFIG_RTL8723BE=m +CONFIG_RTL8188EE=m +CONFIG_RTL8192EE=m +CONFIG_RTL8821AE=m +CONFIG_RTL8192CU=m +CONFIG_RTLWIFI=m +CONFIG_RTLWIFI_PCI=m +CONFIG_RTLWIFI_USB=m +CONFIG_RTLWIFI_DEBUG=y +CONFIG_RTL8192C_COMMON=m +CONFIG_RTL8723_COMMON=m +CONFIG_RTLBTCOEXIST=m +CONFIG_RTL8XXXU=m +# CONFIG_RTL8XXXU_UNTESTED is not set +CONFIG_RTW88=m +CONFIG_RTW88_CORE=m +CONFIG_RTW88_PCI=m +CONFIG_RTW88_8822BE=y +CONFIG_RTW88_8822CE=y +CONFIG_RTW88_DEBUG=y +CONFIG_RTW88_DEBUGFS=y +CONFIG_WLAN_VENDOR_RSI=y +CONFIG_RSI_91X=m +CONFIG_RSI_DEBUGFS=y +CONFIG_RSI_SDIO=m +CONFIG_RSI_USB=m +CONFIG_RSI_COEX=y +CONFIG_WLAN_VENDOR_ST=y +CONFIG_CW1200=m +CONFIG_CW1200_WLAN_SDIO=m +CONFIG_CW1200_WLAN_SPI=m +CONFIG_WLAN_VENDOR_TI=y +CONFIG_WL1251=m +CONFIG_WL1251_SPI=m +CONFIG_WL1251_SDIO=m +CONFIG_WL12XX=m +CONFIG_WL18XX=m +CONFIG_WLCORE=m +CONFIG_WLCORE_SDIO=m +CONFIG_WILINK_PLATFORM_DATA=y +CONFIG_WLAN_VENDOR_ZYDAS=y +CONFIG_USB_ZD1201=m +CONFIG_ZD1211RW=m +# CONFIG_ZD1211RW_DEBUG is not set +CONFIG_WLAN_VENDOR_QUANTENNA=y +CONFIG_QTNFMAC=m +CONFIG_QTNFMAC_PCIE=m +CONFIG_PCMCIA_RAYCS=m +CONFIG_PCMCIA_WL3501=m +CONFIG_MAC80211_HWSIM=m +CONFIG_USB_NET_RNDIS_WLAN=m +# CONFIG_VIRT_WIFI is not set + +# +# WiMAX Wireless Broadband devices +# +CONFIG_WIMAX_I2400M=m +CONFIG_WIMAX_I2400M_USB=m +CONFIG_WIMAX_I2400M_DEBUG_LEVEL=8 +# end of WiMAX Wireless Broadband devices + +CONFIG_WAN=y +CONFIG_LANMEDIA=m +CONFIG_HDLC=m +CONFIG_HDLC_RAW=m +CONFIG_HDLC_RAW_ETH=m +CONFIG_HDLC_CISCO=m +CONFIG_HDLC_FR=m +CONFIG_HDLC_PPP=m +CONFIG_HDLC_X25=m +CONFIG_PCI200SYN=m +CONFIG_WANXL=m +CONFIG_PC300TOO=m +CONFIG_FARSYNC=m +CONFIG_DLCI=m +CONFIG_DLCI_MAX=8 +CONFIG_LAPBETHER=m +CONFIG_X25_ASY=m +CONFIG_SBNI=m +CONFIG_SBNI_MULTILINE=y +CONFIG_IEEE802154_DRIVERS=m +CONFIG_IEEE802154_FAKELB=m +CONFIG_IEEE802154_AT86RF230=m +# CONFIG_IEEE802154_AT86RF230_DEBUGFS is not set +CONFIG_IEEE802154_MRF24J40=m +CONFIG_IEEE802154_CC2520=m +CONFIG_IEEE802154_ATUSB=m +CONFIG_IEEE802154_ADF7242=m +CONFIG_IEEE802154_CA8210=m +# CONFIG_IEEE802154_CA8210_DEBUGFS is not set +# CONFIG_IEEE802154_MCR20A is not set +# CONFIG_IEEE802154_HWSIM is not set +CONFIG_XEN_NETDEV_FRONTEND=m +CONFIG_XEN_NETDEV_BACKEND=m +CONFIG_VMXNET3=m +CONFIG_FUJITSU_ES=m +CONFIG_THUNDERBOLT_NET=m +CONFIG_HYPERV_NET=m +# CONFIG_NETDEVSIM is not set +CONFIG_NET_FAILOVER=m +CONFIG_ISDN=y +CONFIG_ISDN_CAPI=m +# CONFIG_CAPI_TRACE is not set +CONFIG_ISDN_CAPI_CAPI20=m +CONFIG_ISDN_CAPI_MIDDLEWARE=y +CONFIG_MISDN=m +CONFIG_MISDN_DSP=m +CONFIG_MISDN_L1OIP=m + +# +# mISDN hardware drivers +# +CONFIG_MISDN_HFCPCI=m +CONFIG_MISDN_HFCMULTI=m +CONFIG_MISDN_HFCUSB=m +CONFIG_MISDN_AVMFRITZ=m +CONFIG_MISDN_SPEEDFAX=m +CONFIG_MISDN_INFINEON=m +CONFIG_MISDN_W6692=m +CONFIG_MISDN_NETJET=m +CONFIG_MISDN_HDLC=m +CONFIG_MISDN_IPAC=m +CONFIG_MISDN_ISAR=m +CONFIG_NVM=y +# CONFIG_NVM_PBLK is not set + +# +# Input device support +# +CONFIG_INPUT=y +CONFIG_INPUT_LEDS=m +CONFIG_INPUT_FF_MEMLESS=m +CONFIG_INPUT_POLLDEV=m +CONFIG_INPUT_SPARSEKMAP=m +CONFIG_INPUT_MATRIXKMAP=m + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +CONFIG_INPUT_JOYDEV=m +CONFIG_INPUT_EVDEV=m +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ADC is not set +CONFIG_KEYBOARD_ADP5520=m +# CONFIG_KEYBOARD_ADP5588 is not set +# CONFIG_KEYBOARD_ADP5589 is not set +CONFIG_KEYBOARD_APPLESPI=m +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_QT1050 is not set +# CONFIG_KEYBOARD_QT1070 is not set +CONFIG_KEYBOARD_QT2160=m +CONFIG_KEYBOARD_DLINK_DIR685=m +CONFIG_KEYBOARD_LKKBD=m +CONFIG_KEYBOARD_GPIO=m +CONFIG_KEYBOARD_GPIO_POLLED=m +CONFIG_KEYBOARD_TCA6416=m +CONFIG_KEYBOARD_TCA8418=m +# CONFIG_KEYBOARD_MATRIX is not set +# CONFIG_KEYBOARD_LM8323 is not set +# CONFIG_KEYBOARD_LM8333 is not set +# CONFIG_KEYBOARD_MAX7359 is not set +# CONFIG_KEYBOARD_MCS is not set +# CONFIG_KEYBOARD_MPR121 is not set +CONFIG_KEYBOARD_NEWTON=m +# CONFIG_KEYBOARD_OPENCORES is not set +CONFIG_KEYBOARD_SAMSUNG=m +CONFIG_KEYBOARD_STOWAWAY=m +CONFIG_KEYBOARD_SUNKBD=m +# CONFIG_KEYBOARD_TM2_TOUCHKEY is not set +CONFIG_KEYBOARD_TWL4030=m +CONFIG_KEYBOARD_XTKBD=m +CONFIG_KEYBOARD_CROS_EC=m +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=m +CONFIG_MOUSE_PS2_ALPS=y +CONFIG_MOUSE_PS2_BYD=y +CONFIG_MOUSE_PS2_LOGIPS2PP=y +CONFIG_MOUSE_PS2_SYNAPTICS=y +CONFIG_MOUSE_PS2_SYNAPTICS_SMBUS=y +CONFIG_MOUSE_PS2_CYPRESS=y +CONFIG_MOUSE_PS2_LIFEBOOK=y +CONFIG_MOUSE_PS2_TRACKPOINT=y +CONFIG_MOUSE_PS2_ELANTECH=y +CONFIG_MOUSE_PS2_ELANTECH_SMBUS=y +CONFIG_MOUSE_PS2_SENTELIC=y +CONFIG_MOUSE_PS2_TOUCHKIT=y +CONFIG_MOUSE_PS2_FOCALTECH=y +CONFIG_MOUSE_PS2_VMMOUSE=y +CONFIG_MOUSE_PS2_SMBUS=y +CONFIG_MOUSE_SERIAL=m +CONFIG_MOUSE_APPLETOUCH=m +CONFIG_MOUSE_BCM5974=m +CONFIG_MOUSE_CYAPA=m +CONFIG_MOUSE_ELAN_I2C=m +CONFIG_MOUSE_ELAN_I2C_I2C=y +CONFIG_MOUSE_ELAN_I2C_SMBUS=y +CONFIG_MOUSE_VSXXXAA=m +# CONFIG_MOUSE_GPIO is not set +# CONFIG_MOUSE_SYNAPTICS_I2C is not set +CONFIG_MOUSE_SYNAPTICS_USB=m +CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_ANALOG=m +CONFIG_JOYSTICK_A3D=m +CONFIG_JOYSTICK_ADI=m +CONFIG_JOYSTICK_COBRA=m +CONFIG_JOYSTICK_GF2K=m +CONFIG_JOYSTICK_GRIP=m +CONFIG_JOYSTICK_GRIP_MP=m +CONFIG_JOYSTICK_GUILLEMOT=m +CONFIG_JOYSTICK_INTERACT=m +CONFIG_JOYSTICK_SIDEWINDER=m +CONFIG_JOYSTICK_TMDC=m +CONFIG_JOYSTICK_IFORCE=m +CONFIG_JOYSTICK_IFORCE_USB=m +CONFIG_JOYSTICK_IFORCE_232=m +CONFIG_JOYSTICK_WARRIOR=m +CONFIG_JOYSTICK_MAGELLAN=m +CONFIG_JOYSTICK_SPACEORB=m +CONFIG_JOYSTICK_SPACEBALL=m +CONFIG_JOYSTICK_STINGER=m +CONFIG_JOYSTICK_TWIDJOY=m +CONFIG_JOYSTICK_ZHENHUA=m +CONFIG_JOYSTICK_DB9=m +CONFIG_JOYSTICK_GAMECON=m +CONFIG_JOYSTICK_TURBOGRAFX=m +CONFIG_JOYSTICK_AS5011=m +CONFIG_JOYSTICK_JOYDUMP=m +CONFIG_JOYSTICK_XPAD=m +CONFIG_JOYSTICK_XPAD_FF=y +CONFIG_JOYSTICK_XPAD_LEDS=y +CONFIG_JOYSTICK_WALKERA0701=m +# CONFIG_JOYSTICK_PSXPAD_SPI is not set +CONFIG_JOYSTICK_PXRC=m +# CONFIG_JOYSTICK_FSIA6B is not set +CONFIG_INPUT_TABLET=y +CONFIG_TABLET_USB_ACECAD=m +CONFIG_TABLET_USB_AIPTEK=m +CONFIG_TABLET_USB_GTCO=m +CONFIG_TABLET_USB_HANWANG=m +CONFIG_TABLET_USB_KBTAB=m +CONFIG_TABLET_USB_PEGASUS=m +CONFIG_TABLET_SERIAL_WACOM4=m +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_PROPERTIES=y +CONFIG_TOUCHSCREEN_88PM860X=m +CONFIG_TOUCHSCREEN_ADS7846=m +CONFIG_TOUCHSCREEN_AD7877=m +CONFIG_TOUCHSCREEN_AD7879=m +CONFIG_TOUCHSCREEN_AD7879_I2C=m +CONFIG_TOUCHSCREEN_AD7879_SPI=m +CONFIG_TOUCHSCREEN_ADC=m +CONFIG_TOUCHSCREEN_ATMEL_MXT=m +# CONFIG_TOUCHSCREEN_ATMEL_MXT_T37 is not set +CONFIG_TOUCHSCREEN_AUO_PIXCIR=m +CONFIG_TOUCHSCREEN_BU21013=m +CONFIG_TOUCHSCREEN_BU21029=m +# CONFIG_TOUCHSCREEN_CHIPONE_ICN8505 is not set +CONFIG_TOUCHSCREEN_CY8CTMG110=m +CONFIG_TOUCHSCREEN_CYTTSP_CORE=m +CONFIG_TOUCHSCREEN_CYTTSP_I2C=m +CONFIG_TOUCHSCREEN_CYTTSP_SPI=m +CONFIG_TOUCHSCREEN_CYTTSP4_CORE=m +CONFIG_TOUCHSCREEN_CYTTSP4_I2C=m +CONFIG_TOUCHSCREEN_CYTTSP4_SPI=m +CONFIG_TOUCHSCREEN_DA9034=m +CONFIG_TOUCHSCREEN_DA9052=m +CONFIG_TOUCHSCREEN_DYNAPRO=m +CONFIG_TOUCHSCREEN_HAMPSHIRE=m +CONFIG_TOUCHSCREEN_EETI=m +CONFIG_TOUCHSCREEN_EGALAX_SERIAL=m +# CONFIG_TOUCHSCREEN_EXC3000 is not set +CONFIG_TOUCHSCREEN_FUJITSU=m +CONFIG_TOUCHSCREEN_GOODIX=m +# CONFIG_TOUCHSCREEN_HIDEEP is not set +CONFIG_TOUCHSCREEN_ILI210X=m +# CONFIG_TOUCHSCREEN_S6SY761 is not set +CONFIG_TOUCHSCREEN_GUNZE=m +CONFIG_TOUCHSCREEN_EKTF2127=m +CONFIG_TOUCHSCREEN_ELAN=m +CONFIG_TOUCHSCREEN_ELO=m +CONFIG_TOUCHSCREEN_WACOM_W8001=m +CONFIG_TOUCHSCREEN_WACOM_I2C=m +CONFIG_TOUCHSCREEN_MAX11801=m +CONFIG_TOUCHSCREEN_MCS5000=m +CONFIG_TOUCHSCREEN_MMS114=m +CONFIG_TOUCHSCREEN_MELFAS_MIP4=m +CONFIG_TOUCHSCREEN_MTOUCH=m +CONFIG_TOUCHSCREEN_INEXIO=m +CONFIG_TOUCHSCREEN_MK712=m +CONFIG_TOUCHSCREEN_PENMOUNT=m +CONFIG_TOUCHSCREEN_EDT_FT5X06=m +CONFIG_TOUCHSCREEN_TOUCHRIGHT=m +CONFIG_TOUCHSCREEN_TOUCHWIN=m +CONFIG_TOUCHSCREEN_TI_AM335X_TSC=m +CONFIG_TOUCHSCREEN_PIXCIR=m +CONFIG_TOUCHSCREEN_WDT87XX_I2C=m +CONFIG_TOUCHSCREEN_WM831X=m +CONFIG_TOUCHSCREEN_WM97XX=m +CONFIG_TOUCHSCREEN_WM9705=y +CONFIG_TOUCHSCREEN_WM9712=y +CONFIG_TOUCHSCREEN_WM9713=y +CONFIG_TOUCHSCREEN_USB_COMPOSITE=m +CONFIG_TOUCHSCREEN_MC13783=m +CONFIG_TOUCHSCREEN_USB_EGALAX=y +CONFIG_TOUCHSCREEN_USB_PANJIT=y +CONFIG_TOUCHSCREEN_USB_3M=y +CONFIG_TOUCHSCREEN_USB_ITM=y +CONFIG_TOUCHSCREEN_USB_ETURBO=y +CONFIG_TOUCHSCREEN_USB_GUNZE=y +CONFIG_TOUCHSCREEN_USB_DMC_TSC10=y +CONFIG_TOUCHSCREEN_USB_IRTOUCH=y +CONFIG_TOUCHSCREEN_USB_IDEALTEK=y +CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH=y +CONFIG_TOUCHSCREEN_USB_GOTOP=y +CONFIG_TOUCHSCREEN_USB_JASTEC=y +CONFIG_TOUCHSCREEN_USB_ELO=y +CONFIG_TOUCHSCREEN_USB_E2I=y +CONFIG_TOUCHSCREEN_USB_ZYTRONIC=y +CONFIG_TOUCHSCREEN_USB_ETT_TC45USB=y +CONFIG_TOUCHSCREEN_USB_NEXIO=y +CONFIG_TOUCHSCREEN_USB_EASYTOUCH=y +CONFIG_TOUCHSCREEN_TOUCHIT213=m +CONFIG_TOUCHSCREEN_TSC_SERIO=m +CONFIG_TOUCHSCREEN_TSC200X_CORE=m +CONFIG_TOUCHSCREEN_TSC2004=m +CONFIG_TOUCHSCREEN_TSC2005=m +CONFIG_TOUCHSCREEN_TSC2007=m +# CONFIG_TOUCHSCREEN_TSC2007_IIO is not set +CONFIG_TOUCHSCREEN_PCAP=m +CONFIG_TOUCHSCREEN_RM_TS=m +CONFIG_TOUCHSCREEN_SILEAD=m +CONFIG_TOUCHSCREEN_SIS_I2C=m +CONFIG_TOUCHSCREEN_ST1232=m +CONFIG_TOUCHSCREEN_STMFTS=m +CONFIG_TOUCHSCREEN_SUR40=m +CONFIG_TOUCHSCREEN_SURFACE3_SPI=m +# CONFIG_TOUCHSCREEN_SX8654 is not set +CONFIG_TOUCHSCREEN_TPS6507X=m +CONFIG_TOUCHSCREEN_ZET6223=m +CONFIG_TOUCHSCREEN_ZFORCE=m +CONFIG_TOUCHSCREEN_ROHM_BU21023=m +# CONFIG_TOUCHSCREEN_IQS5XX is not set +CONFIG_INPUT_MISC=y +CONFIG_INPUT_88PM860X_ONKEY=m +CONFIG_INPUT_88PM80X_ONKEY=m +CONFIG_INPUT_AD714X=m +CONFIG_INPUT_AD714X_I2C=m +CONFIG_INPUT_AD714X_SPI=m +# CONFIG_INPUT_ARIZONA_HAPTICS is not set +CONFIG_INPUT_BMA150=m +# CONFIG_INPUT_E3X0_BUTTON is not set +# CONFIG_INPUT_MSM_VIBRATOR is not set +CONFIG_INPUT_PCSPKR=m +CONFIG_INPUT_MAX77693_HAPTIC=m +CONFIG_INPUT_MAX8925_ONKEY=m +CONFIG_INPUT_MAX8997_HAPTIC=m +CONFIG_INPUT_MC13783_PWRBUTTON=m +# CONFIG_INPUT_MMA8450 is not set +CONFIG_INPUT_APANEL=m +CONFIG_INPUT_GP2A=m +CONFIG_INPUT_GPIO_BEEPER=m +# CONFIG_INPUT_GPIO_DECODER is not set +# CONFIG_INPUT_GPIO_VIBRA is not set +CONFIG_INPUT_ATLAS_BTNS=m +CONFIG_INPUT_ATI_REMOTE2=m +CONFIG_INPUT_KEYSPAN_REMOTE=m +# CONFIG_INPUT_KXTJ9 is not set +CONFIG_INPUT_POWERMATE=m +CONFIG_INPUT_YEALINK=m +CONFIG_INPUT_CM109=m +CONFIG_INPUT_REGULATOR_HAPTIC=m +CONFIG_INPUT_RETU_PWRBUTTON=m +# CONFIG_INPUT_AXP20X_PEK is not set +CONFIG_INPUT_TWL4030_PWRBUTTON=m +CONFIG_INPUT_TWL4030_VIBRA=m +CONFIG_INPUT_TWL6040_VIBRA=m +CONFIG_INPUT_UINPUT=m +CONFIG_INPUT_PALMAS_PWRBUTTON=m +CONFIG_INPUT_PCF8574=m +CONFIG_INPUT_PWM_BEEPER=m +CONFIG_INPUT_PWM_VIBRA=m +CONFIG_INPUT_GPIO_ROTARY_ENCODER=m +CONFIG_INPUT_DA9052_ONKEY=m +CONFIG_INPUT_DA9055_ONKEY=m +CONFIG_INPUT_DA9063_ONKEY=m +CONFIG_INPUT_WM831X_ON=m +CONFIG_INPUT_PCAP=m +# CONFIG_INPUT_ADXL34X is not set +CONFIG_INPUT_IMS_PCU=m +CONFIG_INPUT_CMA3000=m +CONFIG_INPUT_CMA3000_I2C=m +CONFIG_INPUT_XEN_KBDDEV_FRONTEND=y +CONFIG_INPUT_IDEAPAD_SLIDEBAR=m +CONFIG_INPUT_SOC_BUTTON_ARRAY=m +CONFIG_INPUT_DRV260X_HAPTICS=m +CONFIG_INPUT_DRV2665_HAPTICS=m +CONFIG_INPUT_DRV2667_HAPTICS=m +CONFIG_RMI4_CORE=m +CONFIG_RMI4_I2C=m +CONFIG_RMI4_SPI=m +CONFIG_RMI4_SMB=m +CONFIG_RMI4_F03=y +CONFIG_RMI4_F03_SERIO=m +CONFIG_RMI4_2D_SENSOR=y +CONFIG_RMI4_F11=y +CONFIG_RMI4_F12=y +CONFIG_RMI4_F30=y +CONFIG_RMI4_F34=y +CONFIG_RMI4_F54=y +CONFIG_RMI4_F55=y + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=m +CONFIG_SERIO_CT82C710=m +CONFIG_SERIO_PARKBD=m +CONFIG_SERIO_PCIPS2=m +CONFIG_SERIO_LIBPS2=y +CONFIG_SERIO_RAW=m +CONFIG_SERIO_ALTERA_PS2=m +CONFIG_SERIO_PS2MULT=m +CONFIG_SERIO_ARC_PS2=m +CONFIG_HYPERV_KEYBOARD=m +CONFIG_SERIO_GPIO_PS2=m +CONFIG_USERIO=m +CONFIG_GAMEPORT=m +CONFIG_GAMEPORT_NS558=m +CONFIG_GAMEPORT_L4=m +CONFIG_GAMEPORT_EMU10K1=m +CONFIG_GAMEPORT_FM801=m +# end of Hardware I/O ports +# end of Input device support + +# +# Character devices +# +CONFIG_TTY=y +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_VT_CONSOLE_SLEEP=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=0 +CONFIG_SERIAL_NONSTANDARD=y +CONFIG_ROCKETPORT=m +CONFIG_CYCLADES=m +# CONFIG_CYZ_INTR is not set +CONFIG_MOXA_INTELLIO=m +CONFIG_MOXA_SMARTIO=m +CONFIG_SYNCLINK=m +CONFIG_SYNCLINKMP=m +CONFIG_SYNCLINK_GT=m +CONFIG_NOZOMI=m +CONFIG_ISI=m +CONFIG_N_HDLC=m +CONFIG_N_GSM=m +CONFIG_TRACE_ROUTER=m +CONFIG_TRACE_SINK=m +# CONFIG_NULL_TTY is not set +CONFIG_LDISC_AUTOLOAD=y +CONFIG_DEVMEM=y +# CONFIG_DEVKMEM is not set + +# +# Serial drivers +# +CONFIG_SERIAL_EARLYCON=y +CONFIG_SERIAL_8250=y +# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set +CONFIG_SERIAL_8250_PNP=y +CONFIG_SERIAL_8250_FINTEK=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_DMA=y +CONFIG_SERIAL_8250_PCI=y +CONFIG_SERIAL_8250_EXAR=y +CONFIG_SERIAL_8250_CS=m +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +CONFIG_SERIAL_8250_EXTENDED=y +# CONFIG_SERIAL_8250_MANY_PORTS is not set +CONFIG_SERIAL_8250_SHARE_IRQ=y +# CONFIG_SERIAL_8250_DETECT_IRQ is not set +CONFIG_SERIAL_8250_RSA=y +CONFIG_SERIAL_8250_DWLIB=y +CONFIG_SERIAL_8250_DW=m +CONFIG_SERIAL_8250_RT288X=y +CONFIG_SERIAL_8250_LPSS=m +CONFIG_SERIAL_8250_MID=m + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_MAX3100=m +CONFIG_SERIAL_MAX310X=m +CONFIG_SERIAL_UARTLITE=m +CONFIG_SERIAL_UARTLITE_NR_UARTS=1 +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_SERIAL_JSM=m +CONFIG_SERIAL_SCCNXP=m +CONFIG_SERIAL_SC16IS7XX_CORE=m +CONFIG_SERIAL_SC16IS7XX=m +CONFIG_SERIAL_SC16IS7XX_I2C=y +# CONFIG_SERIAL_SC16IS7XX_SPI is not set +CONFIG_SERIAL_ALTERA_JTAGUART=m +CONFIG_SERIAL_ALTERA_UART=m +CONFIG_SERIAL_ALTERA_UART_MAXPORTS=4 +CONFIG_SERIAL_ALTERA_UART_BAUDRATE=115200 +CONFIG_SERIAL_IFX6X60=m +CONFIG_SERIAL_ARC=m +CONFIG_SERIAL_ARC_NR_PORTS=1 +CONFIG_SERIAL_RP2=m +CONFIG_SERIAL_RP2_NR_UARTS=32 +CONFIG_SERIAL_FSL_LPUART=m +# CONFIG_SERIAL_FSL_LINFLEXUART is not set +# end of Serial drivers + +CONFIG_SERIAL_MCTRL_GPIO=y +CONFIG_SERIAL_DEV_BUS=m +# CONFIG_TTY_PRINTK is not set +CONFIG_PRINTER=m +CONFIG_LP_CONSOLE=y +CONFIG_PPDEV=m +CONFIG_HVC_DRIVER=y +CONFIG_HVC_IRQ=y +CONFIG_HVC_XEN=y +CONFIG_HVC_XEN_FRONTEND=y +CONFIG_VIRTIO_CONSOLE=m +CONFIG_IPMI_HANDLER=m +CONFIG_IPMI_DMI_DECODE=y +CONFIG_IPMI_PLAT_DATA=y +CONFIG_IPMI_PANIC_EVENT=y +CONFIG_IPMI_PANIC_STRING=y +CONFIG_IPMI_DEVICE_INTERFACE=m +CONFIG_IPMI_SI=m +CONFIG_IPMI_SSIF=m +CONFIG_IPMI_WATCHDOG=m +CONFIG_IPMI_POWEROFF=m +CONFIG_IPMB_DEVICE_INTERFACE=m +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_TIMERIOMEM=m +CONFIG_HW_RANDOM_INTEL=m +CONFIG_HW_RANDOM_AMD=m +CONFIG_HW_RANDOM_VIA=m +CONFIG_HW_RANDOM_VIRTIO=m +CONFIG_NVRAM=m +CONFIG_APPLICOM=m + +# +# PCMCIA character devices +# +CONFIG_SYNCLINK_CS=m +CONFIG_CARDMAN_4000=m +CONFIG_CARDMAN_4040=m +CONFIG_SCR24X=m +CONFIG_IPWIRELESS=m +# end of PCMCIA character devices + +CONFIG_MWAVE=m +CONFIG_RAW_DRIVER=m +CONFIG_MAX_RAW_DEVS=256 +CONFIG_HPET=y +CONFIG_HPET_MMAP=y +CONFIG_HPET_MMAP_DEFAULT=y +CONFIG_HANGCHECK_TIMER=m +CONFIG_TCG_TPM=m +CONFIG_HW_RANDOM_TPM=y +CONFIG_TCG_TIS_CORE=m +CONFIG_TCG_TIS=m +CONFIG_TCG_TIS_SPI=m +CONFIG_TCG_TIS_I2C_ATMEL=m +CONFIG_TCG_TIS_I2C_INFINEON=m +CONFIG_TCG_TIS_I2C_NUVOTON=m +CONFIG_TCG_NSC=m +CONFIG_TCG_ATMEL=m +CONFIG_TCG_INFINEON=m +CONFIG_TCG_XEN=m +CONFIG_TCG_CRB=m +CONFIG_TCG_VTPM_PROXY=m +CONFIG_TCG_TIS_ST33ZP24=m +CONFIG_TCG_TIS_ST33ZP24_I2C=m +CONFIG_TCG_TIS_ST33ZP24_SPI=m +CONFIG_TELCLOCK=m +CONFIG_DEVPORT=y +CONFIG_XILLYBUS=m +CONFIG_XILLYBUS_PCIE=m +# end of Character devices + +CONFIG_RANDOM_TRUST_CPU=y +CONFIG_RANDOM_TRUST_BOOTLOADER=y + +# +# I2C support +# +CONFIG_I2C=y +CONFIG_ACPI_I2C_OPREGION=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_COMPAT=y +CONFIG_I2C_CHARDEV=m +CONFIG_I2C_MUX=m + +# +# Multiplexer I2C Chip support +# +CONFIG_I2C_MUX_GPIO=m +CONFIG_I2C_MUX_LTC4306=m +CONFIG_I2C_MUX_PCA9541=m +CONFIG_I2C_MUX_PCA954x=m +CONFIG_I2C_MUX_REG=m +CONFIG_I2C_MUX_MLXCPLD=m +# end of Multiplexer I2C Chip support + +CONFIG_I2C_HELPER_AUTO=y +CONFIG_I2C_SMBUS=m +CONFIG_I2C_ALGOBIT=m + +# +# I2C Hardware Bus support +# + +# +# PC SMBus host controller drivers +# +CONFIG_I2C_ALI1535=m +CONFIG_I2C_ALI1563=m +CONFIG_I2C_ALI15X3=m +CONFIG_I2C_AMD756=m +CONFIG_I2C_AMD756_S4882=m +CONFIG_I2C_AMD8111=m +CONFIG_I2C_AMD_MP2=m +CONFIG_I2C_I801=m +CONFIG_I2C_ISCH=m +CONFIG_I2C_ISMT=m +CONFIG_I2C_PIIX4=m +CONFIG_I2C_CHT_WC=m +CONFIG_I2C_NFORCE2=m +CONFIG_I2C_NFORCE2_S4985=m +CONFIG_I2C_NVIDIA_GPU=m +CONFIG_I2C_SIS5595=m +CONFIG_I2C_SIS630=m +CONFIG_I2C_SIS96X=m +CONFIG_I2C_VIA=m +CONFIG_I2C_VIAPRO=m + +# +# ACPI drivers +# +CONFIG_I2C_SCMI=m + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +CONFIG_I2C_CBUS_GPIO=m +CONFIG_I2C_DESIGNWARE_CORE=y +CONFIG_I2C_DESIGNWARE_PLATFORM=y +CONFIG_I2C_DESIGNWARE_SLAVE=y +CONFIG_I2C_DESIGNWARE_PCI=m +CONFIG_I2C_DESIGNWARE_BAYTRAIL=y +CONFIG_I2C_EMEV2=m +# CONFIG_I2C_GPIO is not set +CONFIG_I2C_KEMPLD=m +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_SIMTEC is not set +CONFIG_I2C_XILINX=m + +# +# External I2C/SMBus adapter drivers +# +CONFIG_I2C_DIOLAN_U2C=m +CONFIG_I2C_DLN2=m +CONFIG_I2C_PARPORT=m +CONFIG_I2C_PARPORT_LIGHT=m +CONFIG_I2C_ROBOTFUZZ_OSIF=m +CONFIG_I2C_TAOS_EVM=m +CONFIG_I2C_TINY_USB=m +CONFIG_I2C_VIPERBOARD=m + +# +# Other I2C/SMBus bus drivers +# +CONFIG_I2C_MLXCPLD=m +CONFIG_I2C_CROS_EC_TUNNEL=m +# end of I2C Hardware Bus support + +# CONFIG_I2C_STUB is not set +CONFIG_I2C_SLAVE=y +CONFIG_I2C_SLAVE_EEPROM=m +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# end of I2C support + +CONFIG_I3C=m +CONFIG_CDNS_I3C_MASTER=m +CONFIG_DW_I3C_MASTER=m +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y +CONFIG_SPI_MEM=y + +# +# SPI Master Controller Drivers +# +CONFIG_SPI_ALTERA=m +CONFIG_SPI_AXI_SPI_ENGINE=m +CONFIG_SPI_BITBANG=m +CONFIG_SPI_BUTTERFLY=m +# CONFIG_SPI_CADENCE is not set +CONFIG_SPI_DESIGNWARE=m +CONFIG_SPI_DW_PCI=m +CONFIG_SPI_DW_MID_DMA=y +CONFIG_SPI_DW_MMIO=m +# CONFIG_SPI_DLN2 is not set +# CONFIG_SPI_NXP_FLEXSPI is not set +CONFIG_SPI_GPIO=m +CONFIG_SPI_LM70_LLP=m +CONFIG_SPI_OC_TINY=m +CONFIG_SPI_PXA2XX=m +CONFIG_SPI_PXA2XX_PCI=m +CONFIG_SPI_ROCKCHIP=m +CONFIG_SPI_SC18IS602=m +# CONFIG_SPI_SIFIVE is not set +# CONFIG_SPI_MXIC is not set +CONFIG_SPI_XCOMM=m +CONFIG_SPI_XILINX=m +CONFIG_SPI_ZYNQMP_GQSPI=m + +# +# SPI Protocol Masters +# +CONFIG_SPI_SPIDEV=m +CONFIG_SPI_LOOPBACK_TEST=m +CONFIG_SPI_TLE62X0=m +# CONFIG_SPI_SLAVE is not set +CONFIG_SPMI=m +CONFIG_HSI=m +CONFIG_HSI_BOARDINFO=y + +# +# HSI controllers +# + +# +# HSI clients +# +CONFIG_HSI_CHAR=m +CONFIG_PPS=m +# CONFIG_PPS_DEBUG is not set + +# +# PPS clients support +# +CONFIG_PPS_CLIENT_KTIMER=m +CONFIG_PPS_CLIENT_LDISC=m +CONFIG_PPS_CLIENT_PARPORT=m +CONFIG_PPS_CLIENT_GPIO=m + +# +# PPS generators support +# + +# +# PTP clock support +# +CONFIG_PTP_1588_CLOCK=m + +# +# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks. +# +CONFIG_PTP_1588_CLOCK_KVM=m +# end of PTP clock support + +CONFIG_PINCTRL=y +CONFIG_PINMUX=y +CONFIG_PINCONF=y +CONFIG_GENERIC_PINCONF=y +# CONFIG_DEBUG_PINCTRL is not set +CONFIG_PINCTRL_AMD=y +# CONFIG_PINCTRL_MCP23S08 is not set +CONFIG_PINCTRL_SX150X=y +CONFIG_PINCTRL_BAYTRAIL=y +CONFIG_PINCTRL_CHERRYVIEW=m +CONFIG_PINCTRL_INTEL=m +CONFIG_PINCTRL_BROXTON=m +CONFIG_PINCTRL_CANNONLAKE=m +CONFIG_PINCTRL_CEDARFORK=m +CONFIG_PINCTRL_DENVERTON=m +CONFIG_PINCTRL_GEMINILAKE=m +CONFIG_PINCTRL_ICELAKE=m +CONFIG_PINCTRL_LEWISBURG=m +CONFIG_PINCTRL_SUNRISEPOINT=m +CONFIG_PINCTRL_MADERA=m +CONFIG_PINCTRL_CS47L15=y +CONFIG_PINCTRL_CS47L35=y +CONFIG_PINCTRL_CS47L85=y +CONFIG_PINCTRL_CS47L90=y +CONFIG_PINCTRL_CS47L92=y +CONFIG_GPIOLIB=y +CONFIG_GPIOLIB_FASTPATH_LIMIT=512 +CONFIG_GPIO_ACPI=y +CONFIG_GPIOLIB_IRQCHIP=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y +CONFIG_GPIO_GENERIC=m +CONFIG_GPIO_MAX730X=m + +# +# Memory mapped GPIO drivers +# +CONFIG_GPIO_AMDPT=m +# CONFIG_GPIO_DWAPB is not set +CONFIG_GPIO_EXAR=m +CONFIG_GPIO_GENERIC_PLATFORM=m +CONFIG_GPIO_ICH=m +CONFIG_GPIO_LYNXPOINT=y +# CONFIG_GPIO_MB86S7X is not set +CONFIG_GPIO_VX855=m +CONFIG_GPIO_XILINX=m +CONFIG_GPIO_AMD_FCH=m +# end of Memory mapped GPIO drivers + +# +# Port-mapped I/O GPIO drivers +# +CONFIG_GPIO_F7188X=m +CONFIG_GPIO_IT87=m +CONFIG_GPIO_SCH=m +CONFIG_GPIO_SCH311X=m +CONFIG_GPIO_WINBOND=m +CONFIG_GPIO_WS16C48=m +# end of Port-mapped I/O GPIO drivers + +# +# I2C GPIO expanders +# +CONFIG_GPIO_ADP5588=m +CONFIG_GPIO_MAX7300=m +CONFIG_GPIO_MAX732X=m +CONFIG_GPIO_PCA953X=m +CONFIG_GPIO_PCF857X=m +CONFIG_GPIO_TPIC2810=m +# end of I2C GPIO expanders + +# +# MFD GPIO expanders +# +CONFIG_GPIO_ADP5520=m +CONFIG_GPIO_ARIZONA=m +CONFIG_GPIO_BD9571MWV=m +CONFIG_GPIO_CRYSTAL_COVE=y +CONFIG_GPIO_DA9052=m +CONFIG_GPIO_DA9055=m +CONFIG_GPIO_DLN2=m +CONFIG_GPIO_KEMPLD=m +CONFIG_GPIO_LP3943=m +CONFIG_GPIO_MADERA=m +CONFIG_GPIO_PALMAS=y +CONFIG_GPIO_RC5T583=y +CONFIG_GPIO_TPS65086=m +CONFIG_GPIO_TPS6586X=y +CONFIG_GPIO_TPS65910=y +CONFIG_GPIO_TPS65912=m +CONFIG_GPIO_TPS68470=y +CONFIG_GPIO_TWL4030=m +CONFIG_GPIO_TWL6040=m +CONFIG_GPIO_WHISKEY_COVE=m +CONFIG_GPIO_WM831X=m +CONFIG_GPIO_WM8350=m +CONFIG_GPIO_WM8994=m +# end of MFD GPIO expanders + +# +# PCI GPIO expanders +# +CONFIG_GPIO_AMD8111=m +CONFIG_GPIO_ML_IOH=m +CONFIG_GPIO_PCI_IDIO_16=m +# CONFIG_GPIO_PCIE_IDIO_24 is not set +CONFIG_GPIO_RDC321X=m +# end of PCI GPIO expanders + +# +# SPI GPIO expanders +# +# CONFIG_GPIO_MAX3191X is not set +CONFIG_GPIO_MAX7301=m +CONFIG_GPIO_MC33880=m +CONFIG_GPIO_PISOSR=m +# CONFIG_GPIO_XRA1403 is not set +# end of SPI GPIO expanders + +# +# USB GPIO expanders +# +CONFIG_GPIO_VIPERBOARD=m +# end of USB GPIO expanders + +# CONFIG_GPIO_MOCKUP is not set +CONFIG_W1=m +CONFIG_W1_CON=y + +# +# 1-wire Bus Masters +# +CONFIG_W1_MASTER_MATROX=m +CONFIG_W1_MASTER_DS2490=m +CONFIG_W1_MASTER_DS2482=m +CONFIG_W1_MASTER_DS1WM=m +# CONFIG_W1_MASTER_GPIO is not set +CONFIG_W1_MASTER_SGI=m +# end of 1-wire Bus Masters + +# +# 1-wire Slaves +# +CONFIG_W1_SLAVE_THERM=m +CONFIG_W1_SLAVE_SMEM=m +# CONFIG_W1_SLAVE_DS2405 is not set +CONFIG_W1_SLAVE_DS2408=m +CONFIG_W1_SLAVE_DS2408_READBACK=y +CONFIG_W1_SLAVE_DS2413=m +CONFIG_W1_SLAVE_DS2406=m +CONFIG_W1_SLAVE_DS2423=m +# CONFIG_W1_SLAVE_DS2805 is not set +CONFIG_W1_SLAVE_DS2431=m +CONFIG_W1_SLAVE_DS2433=m +# CONFIG_W1_SLAVE_DS2433_CRC is not set +# CONFIG_W1_SLAVE_DS2438 is not set +# CONFIG_W1_SLAVE_DS250X is not set +CONFIG_W1_SLAVE_DS2780=m +CONFIG_W1_SLAVE_DS2781=m +CONFIG_W1_SLAVE_DS28E04=m +# CONFIG_W1_SLAVE_DS28E17 is not set +# end of 1-wire Slaves + +CONFIG_POWER_AVS=y +# CONFIG_POWER_RESET is not set +CONFIG_POWER_SUPPLY=y +# CONFIG_POWER_SUPPLY_DEBUG is not set +CONFIG_POWER_SUPPLY_HWMON=y +# CONFIG_PDA_POWER is not set +CONFIG_GENERIC_ADC_BATTERY=m +CONFIG_MAX8925_POWER=m +CONFIG_WM831X_BACKUP=m +CONFIG_WM831X_POWER=m +CONFIG_WM8350_POWER=m +# CONFIG_TEST_POWER is not set +CONFIG_BATTERY_88PM860X=m +CONFIG_CHARGER_ADP5061=m +CONFIG_BATTERY_DS2760=m +CONFIG_BATTERY_DS2780=m +CONFIG_BATTERY_DS2781=m +CONFIG_BATTERY_DS2782=m +CONFIG_BATTERY_SBS=m +CONFIG_CHARGER_SBS=m +# CONFIG_MANAGER_SBS is not set +CONFIG_BATTERY_BQ27XXX=m +CONFIG_BATTERY_BQ27XXX_I2C=m +CONFIG_BATTERY_BQ27XXX_HDQ=m +# CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVM is not set +CONFIG_BATTERY_DA9030=m +CONFIG_BATTERY_DA9052=m +CONFIG_AXP20X_POWER=m +CONFIG_AXP288_CHARGER=m +CONFIG_AXP288_FUEL_GAUGE=m +# CONFIG_BATTERY_MAX17040 is not set +CONFIG_BATTERY_MAX17042=m +# CONFIG_BATTERY_MAX1721X is not set +CONFIG_BATTERY_TWL4030_MADC=m +CONFIG_CHARGER_88PM860X=m +CONFIG_BATTERY_RX51=m +CONFIG_CHARGER_ISP1704=m +CONFIG_CHARGER_MAX8903=m +CONFIG_CHARGER_TWL4030=m +CONFIG_CHARGER_LP8727=m +CONFIG_CHARGER_LP8788=m +CONFIG_CHARGER_GPIO=m +CONFIG_CHARGER_MANAGER=y +CONFIG_CHARGER_LT3651=m +CONFIG_CHARGER_MAX14577=m +# CONFIG_CHARGER_MAX77693 is not set +CONFIG_CHARGER_MAX8997=m +CONFIG_CHARGER_MAX8998=m +CONFIG_CHARGER_BQ2415X=m +CONFIG_CHARGER_BQ24190=m +CONFIG_CHARGER_BQ24257=m +CONFIG_CHARGER_BQ24735=m +CONFIG_CHARGER_BQ25890=m +CONFIG_CHARGER_SMB347=m +CONFIG_CHARGER_TPS65090=m +# CONFIG_BATTERY_GAUGE_LTC2941 is not set +CONFIG_CHARGER_RT9455=m +CONFIG_CHARGER_CROS_USBPD=m +CONFIG_CHARGER_WILCO=m +CONFIG_HWMON=y +CONFIG_HWMON_VID=m +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Native drivers +# +CONFIG_SENSORS_ABITUGURU=m +CONFIG_SENSORS_ABITUGURU3=m +CONFIG_SENSORS_AD7314=m +CONFIG_SENSORS_AD7414=m +CONFIG_SENSORS_AD7418=m +CONFIG_SENSORS_ADM1021=m +CONFIG_SENSORS_ADM1025=m +CONFIG_SENSORS_ADM1026=m +CONFIG_SENSORS_ADM1029=m +CONFIG_SENSORS_ADM1031=m +CONFIG_SENSORS_ADM9240=m +CONFIG_SENSORS_ADT7X10=m +CONFIG_SENSORS_ADT7310=m +CONFIG_SENSORS_ADT7410=m +CONFIG_SENSORS_ADT7411=m +CONFIG_SENSORS_ADT7462=m +CONFIG_SENSORS_ADT7470=m +CONFIG_SENSORS_ADT7475=m +CONFIG_SENSORS_AS370=m +CONFIG_SENSORS_ASC7621=m +CONFIG_SENSORS_K8TEMP=m +CONFIG_SENSORS_K10TEMP=m +CONFIG_SENSORS_FAM15H_POWER=m +CONFIG_SENSORS_APPLESMC=m +CONFIG_SENSORS_ASB100=m +CONFIG_SENSORS_ASPEED=m +CONFIG_SENSORS_ATXP1=m +CONFIG_SENSORS_DS620=m +CONFIG_SENSORS_DS1621=m +CONFIG_SENSORS_DELL_SMM=m +CONFIG_SENSORS_DA9052_ADC=m +CONFIG_SENSORS_DA9055=m +CONFIG_SENSORS_I5K_AMB=m +CONFIG_SENSORS_F71805F=m +CONFIG_SENSORS_F71882FG=m +CONFIG_SENSORS_F75375S=m +CONFIG_SENSORS_MC13783_ADC=m +CONFIG_SENSORS_FSCHMD=m +CONFIG_SENSORS_FTSTEUTATES=m +CONFIG_SENSORS_GL518SM=m +CONFIG_SENSORS_GL520SM=m +# CONFIG_SENSORS_G760A is not set +CONFIG_SENSORS_G762=m +CONFIG_SENSORS_HIH6130=m +CONFIG_SENSORS_IBMAEM=m +CONFIG_SENSORS_IBMPEX=m +CONFIG_SENSORS_IIO_HWMON=m +CONFIG_SENSORS_I5500=m +CONFIG_SENSORS_CORETEMP=m +CONFIG_SENSORS_IT87=m +CONFIG_SENSORS_JC42=m +CONFIG_SENSORS_POWR1220=m +CONFIG_SENSORS_LINEAGE=m +CONFIG_SENSORS_LTC2945=m +CONFIG_SENSORS_LTC2990=m +CONFIG_SENSORS_LTC4151=m +# CONFIG_SENSORS_LTC4215 is not set +CONFIG_SENSORS_LTC4222=m +CONFIG_SENSORS_LTC4245=m +CONFIG_SENSORS_LTC4260=m +CONFIG_SENSORS_LTC4261=m +CONFIG_SENSORS_MAX1111=m +CONFIG_SENSORS_MAX16065=m +CONFIG_SENSORS_MAX1619=m +CONFIG_SENSORS_MAX1668=m +CONFIG_SENSORS_MAX197=m +CONFIG_SENSORS_MAX31722=m +# CONFIG_SENSORS_MAX6621 is not set +CONFIG_SENSORS_MAX6639=m +CONFIG_SENSORS_MAX6642=m +CONFIG_SENSORS_MAX6650=m +# CONFIG_SENSORS_MAX6697 is not set +CONFIG_SENSORS_MAX31790=m +CONFIG_SENSORS_MCP3021=m +CONFIG_SENSORS_MLXREG_FAN=m +CONFIG_SENSORS_TC654=m +CONFIG_SENSORS_MENF21BMC_HWMON=m +CONFIG_SENSORS_ADCXX=m +CONFIG_SENSORS_LM63=m +CONFIG_SENSORS_LM70=m +CONFIG_SENSORS_LM73=m +CONFIG_SENSORS_LM75=m +CONFIG_SENSORS_LM77=m +CONFIG_SENSORS_LM78=m +CONFIG_SENSORS_LM80=m +CONFIG_SENSORS_LM83=m +CONFIG_SENSORS_LM85=m +CONFIG_SENSORS_LM87=m +CONFIG_SENSORS_LM90=m +CONFIG_SENSORS_LM92=m +CONFIG_SENSORS_LM93=m +CONFIG_SENSORS_LM95234=m +CONFIG_SENSORS_LM95241=m +CONFIG_SENSORS_LM95245=m +CONFIG_SENSORS_PC87360=m +CONFIG_SENSORS_PC87427=m +CONFIG_SENSORS_NTC_THERMISTOR=m +CONFIG_SENSORS_NCT6683=m +CONFIG_SENSORS_NCT6775=m +CONFIG_SENSORS_NCT7802=m +CONFIG_SENSORS_NCT7904=m +CONFIG_SENSORS_NPCM7XX=m +CONFIG_SENSORS_PCF8591=m +CONFIG_PMBUS=m +CONFIG_SENSORS_PMBUS=m +CONFIG_SENSORS_ADM1275=m +CONFIG_SENSORS_IBM_CFFPS=m +CONFIG_SENSORS_INSPUR_IPSPS=m +CONFIG_SENSORS_IR35221=m +CONFIG_SENSORS_IR38064=m +CONFIG_SENSORS_IRPS5401=m +CONFIG_SENSORS_ISL68137=m +CONFIG_SENSORS_LM25066=m +CONFIG_SENSORS_LTC2978=m +CONFIG_SENSORS_LTC2978_REGULATOR=y +CONFIG_SENSORS_LTC3815=m +CONFIG_SENSORS_MAX16064=m +CONFIG_SENSORS_MAX20751=m +# CONFIG_SENSORS_MAX31785 is not set +CONFIG_SENSORS_MAX34440=m +CONFIG_SENSORS_MAX8688=m +CONFIG_SENSORS_PXE1610=m +CONFIG_SENSORS_TPS40422=m +CONFIG_SENSORS_TPS53679=m +CONFIG_SENSORS_UCD9000=m +CONFIG_SENSORS_UCD9200=m +CONFIG_SENSORS_ZL6100=m +# CONFIG_SENSORS_SHT15 is not set +# CONFIG_SENSORS_SHT21 is not set +# CONFIG_SENSORS_SHT3x is not set +CONFIG_SENSORS_SHTC1=m +CONFIG_SENSORS_SIS5595=m +CONFIG_SENSORS_DME1737=m +CONFIG_SENSORS_EMC1403=m +CONFIG_SENSORS_EMC2103=m +CONFIG_SENSORS_EMC6W201=m +CONFIG_SENSORS_SMSC47M1=m +CONFIG_SENSORS_SMSC47M192=m +CONFIG_SENSORS_SMSC47B397=m +CONFIG_SENSORS_SCH56XX_COMMON=m +CONFIG_SENSORS_SCH5627=m +CONFIG_SENSORS_SCH5636=m +CONFIG_SENSORS_STTS751=m +CONFIG_SENSORS_SMM665=m +CONFIG_SENSORS_ADC128D818=m +# CONFIG_SENSORS_ADS7828 is not set +CONFIG_SENSORS_ADS7871=m +# CONFIG_SENSORS_AMC6821 is not set +CONFIG_SENSORS_INA209=m +# CONFIG_SENSORS_INA2XX is not set +# CONFIG_SENSORS_INA3221 is not set +CONFIG_SENSORS_TC74=m +CONFIG_SENSORS_THMC50=m +CONFIG_SENSORS_TMP102=m +CONFIG_SENSORS_TMP103=m +CONFIG_SENSORS_TMP108=m +CONFIG_SENSORS_TMP401=m +CONFIG_SENSORS_TMP421=m +CONFIG_SENSORS_VIA_CPUTEMP=m +CONFIG_SENSORS_VIA686A=m +CONFIG_SENSORS_VT1211=m +CONFIG_SENSORS_VT8231=m +CONFIG_SENSORS_W83773G=m +CONFIG_SENSORS_W83781D=m +CONFIG_SENSORS_W83791D=m +CONFIG_SENSORS_W83792D=m +CONFIG_SENSORS_W83793=m +CONFIG_SENSORS_W83795=m +# CONFIG_SENSORS_W83795_FANCTRL is not set +CONFIG_SENSORS_W83L785TS=m +CONFIG_SENSORS_W83L786NG=m +CONFIG_SENSORS_W83627HF=m +CONFIG_SENSORS_W83627EHF=m +CONFIG_SENSORS_WM831X=m +CONFIG_SENSORS_WM8350=m +CONFIG_SENSORS_XGENE=m + +# +# ACPI drivers +# +CONFIG_SENSORS_ACPI_POWER=m +CONFIG_SENSORS_ATK0110=m +CONFIG_THERMAL=y +# CONFIG_THERMAL_STATISTICS is not set +CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 +CONFIG_THERMAL_HWMON=y +CONFIG_THERMAL_WRITABLE_TRIPS=y +CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y +# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set +# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set +# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set +CONFIG_THERMAL_GOV_FAIR_SHARE=y +CONFIG_THERMAL_GOV_STEP_WISE=y +CONFIG_THERMAL_GOV_BANG_BANG=y +CONFIG_THERMAL_GOV_USER_SPACE=y +CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y +CONFIG_CLOCK_THERMAL=y +CONFIG_DEVFREQ_THERMAL=y +CONFIG_THERMAL_EMULATION=y + +# +# Intel thermal drivers +# +CONFIG_INTEL_POWERCLAMP=m +CONFIG_X86_PKG_TEMP_THERMAL=m +CONFIG_INTEL_SOC_DTS_IOSF_CORE=m +CONFIG_INTEL_SOC_DTS_THERMAL=m + +# +# ACPI INT340X thermal drivers +# +CONFIG_INT340X_THERMAL=m +CONFIG_ACPI_THERMAL_REL=m +CONFIG_INT3406_THERMAL=m +CONFIG_PROC_THERMAL_MMIO_RAPL=y +# end of ACPI INT340X thermal drivers + +CONFIG_INTEL_BXT_PMIC_THERMAL=m +CONFIG_INTEL_PCH_THERMAL=m +# end of Intel thermal drivers + +CONFIG_GENERIC_ADC_THERMAL=m +CONFIG_WATCHDOG=y +CONFIG_WATCHDOG_CORE=y +CONFIG_WATCHDOG_NOWAYOUT=y +CONFIG_WATCHDOG_HANDLE_BOOT_ENABLED=y +CONFIG_WATCHDOG_OPEN_TIMEOUT=0 +CONFIG_WATCHDOG_SYSFS=y + +# +# Watchdog Pretimeout Governors +# +# CONFIG_WATCHDOG_PRETIMEOUT_GOV is not set + +# +# Watchdog Device Drivers +# +CONFIG_SOFT_WATCHDOG=m +CONFIG_DA9052_WATCHDOG=m +CONFIG_DA9055_WATCHDOG=m +CONFIG_DA9063_WATCHDOG=m +CONFIG_DA9062_WATCHDOG=m +CONFIG_MENF21BMC_WATCHDOG=m +CONFIG_WDAT_WDT=m +CONFIG_WM831X_WATCHDOG=m +CONFIG_WM8350_WATCHDOG=m +# CONFIG_XILINX_WATCHDOG is not set +CONFIG_ZIIRAVE_WATCHDOG=m +CONFIG_MLX_WDT=m +# CONFIG_CADENCE_WATCHDOG is not set +CONFIG_DW_WATCHDOG=m +CONFIG_TWL4030_WATCHDOG=m +CONFIG_MAX63XX_WATCHDOG=m +CONFIG_RETU_WATCHDOG=m +CONFIG_ACQUIRE_WDT=m +CONFIG_ADVANTECH_WDT=m +CONFIG_ALIM1535_WDT=m +CONFIG_ALIM7101_WDT=m +CONFIG_EBC_C384_WDT=m +CONFIG_F71808E_WDT=m +CONFIG_SP5100_TCO=m +CONFIG_SBC_FITPC2_WATCHDOG=m +CONFIG_EUROTECH_WDT=m +CONFIG_IB700_WDT=m +CONFIG_IBMASR=m +CONFIG_WAFER_WDT=m +CONFIG_I6300ESB_WDT=m +CONFIG_IE6XX_WDT=m +CONFIG_ITCO_WDT=m +CONFIG_ITCO_VENDOR_SUPPORT=y +CONFIG_IT8712F_WDT=m +CONFIG_IT87_WDT=m +CONFIG_HP_WATCHDOG=m +# CONFIG_HPWDT_NMI_DECODING is not set +CONFIG_KEMPLD_WDT=m +CONFIG_SC1200_WDT=m +CONFIG_PC87413_WDT=m +CONFIG_NV_TCO=m +CONFIG_60XX_WDT=m +CONFIG_CPU5_WDT=m +CONFIG_SMSC_SCH311X_WDT=m +CONFIG_SMSC37B787_WDT=m +# CONFIG_TQMX86_WDT is not set +CONFIG_VIA_WDT=m +CONFIG_W83627HF_WDT=m +CONFIG_W83877F_WDT=m +CONFIG_W83977F_WDT=m +CONFIG_MACHZ_WDT=m +CONFIG_SBC_EPX_C3_WATCHDOG=m +CONFIG_INTEL_MEI_WDT=m +CONFIG_NI903X_WDT=m +CONFIG_NIC7018_WDT=m +CONFIG_MEN_A21_WDT=m +CONFIG_XEN_WDT=m + +# +# PCI-based Watchdog Cards +# +CONFIG_PCIPCWATCHDOG=m +CONFIG_WDTPCI=m + +# +# USB-based Watchdog Cards +# +CONFIG_USBPCWATCHDOG=m +CONFIG_SSB_POSSIBLE=y +CONFIG_SSB=m +CONFIG_SSB_SPROM=y +CONFIG_SSB_BLOCKIO=y +CONFIG_SSB_PCIHOST_POSSIBLE=y +CONFIG_SSB_PCIHOST=y +CONFIG_SSB_B43_PCI_BRIDGE=y +CONFIG_SSB_PCMCIAHOST_POSSIBLE=y +CONFIG_SSB_PCMCIAHOST=y +CONFIG_SSB_SDIOHOST_POSSIBLE=y +CONFIG_SSB_SDIOHOST=y +CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y +CONFIG_SSB_DRIVER_PCICORE=y +CONFIG_SSB_DRIVER_GPIO=y +CONFIG_BCMA_POSSIBLE=y +CONFIG_BCMA=m +CONFIG_BCMA_BLOCKIO=y +CONFIG_BCMA_HOST_PCI_POSSIBLE=y +CONFIG_BCMA_HOST_PCI=y +CONFIG_BCMA_HOST_SOC=y +CONFIG_BCMA_DRIVER_PCI=y +CONFIG_BCMA_SFLASH=y +CONFIG_BCMA_DRIVER_GMAC_CMN=y +CONFIG_BCMA_DRIVER_GPIO=y +# CONFIG_BCMA_DEBUG is not set + +# +# Multifunction device drivers +# +CONFIG_MFD_CORE=y +CONFIG_MFD_AS3711=y +CONFIG_PMIC_ADP5520=y +CONFIG_MFD_AAT2870_CORE=y +CONFIG_MFD_BCM590XX=m +CONFIG_MFD_BD9571MWV=m +CONFIG_MFD_AXP20X=m +CONFIG_MFD_AXP20X_I2C=m +CONFIG_MFD_CROS_EC_DEV=m +CONFIG_MFD_MADERA=m +CONFIG_MFD_MADERA_I2C=m +CONFIG_MFD_MADERA_SPI=m +CONFIG_MFD_CS47L15=y +CONFIG_MFD_CS47L35=y +CONFIG_MFD_CS47L85=y +CONFIG_MFD_CS47L90=y +CONFIG_MFD_CS47L92=y +CONFIG_PMIC_DA903X=y +CONFIG_PMIC_DA9052=y +CONFIG_MFD_DA9052_SPI=y +CONFIG_MFD_DA9052_I2C=y +CONFIG_MFD_DA9055=y +CONFIG_MFD_DA9062=m +CONFIG_MFD_DA9063=y +# CONFIG_MFD_DA9150 is not set +CONFIG_MFD_DLN2=m +CONFIG_MFD_MC13XXX=m +CONFIG_MFD_MC13XXX_SPI=m +# CONFIG_MFD_MC13XXX_I2C is not set +# CONFIG_HTC_PASIC3 is not set +CONFIG_HTC_I2CPLD=y +CONFIG_MFD_INTEL_QUARK_I2C_GPIO=m +CONFIG_LPC_ICH=m +CONFIG_LPC_SCH=m +CONFIG_INTEL_SOC_PMIC=y +CONFIG_INTEL_SOC_PMIC_BXTWC=m +CONFIG_INTEL_SOC_PMIC_CHTWC=y +CONFIG_INTEL_SOC_PMIC_CHTDC_TI=m +CONFIG_MFD_INTEL_LPSS=m +CONFIG_MFD_INTEL_LPSS_ACPI=m +CONFIG_MFD_INTEL_LPSS_PCI=m +# CONFIG_MFD_JANZ_CMODIO is not set +CONFIG_MFD_KEMPLD=m +CONFIG_MFD_88PM800=m +CONFIG_MFD_88PM805=m +CONFIG_MFD_88PM860X=y +CONFIG_MFD_MAX14577=y +CONFIG_MFD_MAX77693=y +# CONFIG_MFD_MAX77843 is not set +CONFIG_MFD_MAX8907=m +CONFIG_MFD_MAX8925=y +CONFIG_MFD_MAX8997=y +CONFIG_MFD_MAX8998=y +# CONFIG_MFD_MT6397 is not set +CONFIG_MFD_MENF21BMC=m +CONFIG_EZX_PCAP=y +CONFIG_MFD_VIPERBOARD=m +CONFIG_MFD_RETU=m +# CONFIG_MFD_PCF50633 is not set +# CONFIG_UCB1400_CORE is not set +CONFIG_MFD_RDC321X=m +# CONFIG_MFD_RT5033 is not set +CONFIG_MFD_RC5T583=y +CONFIG_MFD_SEC_CORE=y +CONFIG_MFD_SI476X_CORE=m +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_SKY81452 is not set +CONFIG_MFD_SMSC=y +# CONFIG_ABX500_CORE is not set +CONFIG_MFD_SYSCON=y +CONFIG_MFD_TI_AM335X_TSCADC=m +CONFIG_MFD_LP3943=m +CONFIG_MFD_LP8788=y +CONFIG_MFD_TI_LMU=m +CONFIG_MFD_PALMAS=y +# CONFIG_TPS6105X is not set +# CONFIG_TPS65010 is not set +# CONFIG_TPS6507X is not set +CONFIG_MFD_TPS65086=m +CONFIG_MFD_TPS65090=y +CONFIG_MFD_TPS68470=y +# CONFIG_MFD_TI_LP873X is not set +CONFIG_MFD_TPS6586X=y +CONFIG_MFD_TPS65910=y +CONFIG_MFD_TPS65912=y +CONFIG_MFD_TPS65912_I2C=y +CONFIG_MFD_TPS65912_SPI=y +CONFIG_MFD_TPS80031=y +CONFIG_TWL4030_CORE=y +CONFIG_MFD_TWL4030_AUDIO=y +CONFIG_TWL6040_CORE=y +CONFIG_MFD_WL1273_CORE=m +# CONFIG_MFD_LM3533 is not set +# CONFIG_MFD_TQMX86 is not set +CONFIG_MFD_VX855=m +CONFIG_MFD_ARIZONA=y +CONFIG_MFD_ARIZONA_I2C=m +CONFIG_MFD_ARIZONA_SPI=m +CONFIG_MFD_CS47L24=y +CONFIG_MFD_WM5102=y +CONFIG_MFD_WM5110=y +CONFIG_MFD_WM8997=y +# CONFIG_MFD_WM8998 is not set +CONFIG_MFD_WM8400=y +CONFIG_MFD_WM831X=y +CONFIG_MFD_WM831X_I2C=y +CONFIG_MFD_WM831X_SPI=y +CONFIG_MFD_WM8350=y +CONFIG_MFD_WM8350_I2C=y +CONFIG_MFD_WM8994=y +# CONFIG_RAVE_SP_CORE is not set +# end of Multifunction device drivers + +CONFIG_REGULATOR=y +# CONFIG_REGULATOR_DEBUG is not set +CONFIG_REGULATOR_FIXED_VOLTAGE=m +CONFIG_REGULATOR_VIRTUAL_CONSUMER=m +CONFIG_REGULATOR_USERSPACE_CONSUMER=m +# CONFIG_REGULATOR_88PG86X is not set +CONFIG_REGULATOR_88PM800=m +CONFIG_REGULATOR_88PM8607=m +CONFIG_REGULATOR_ACT8865=m +CONFIG_REGULATOR_AD5398=m +CONFIG_REGULATOR_ANATOP=m +CONFIG_REGULATOR_AAT2870=m +# CONFIG_REGULATOR_ARIZONA_LDO1 is not set +# CONFIG_REGULATOR_ARIZONA_MICSUPP is not set +CONFIG_REGULATOR_AS3711=m +CONFIG_REGULATOR_AXP20X=m +CONFIG_REGULATOR_BCM590XX=m +CONFIG_REGULATOR_BD9571MWV=m +CONFIG_REGULATOR_DA903X=m +CONFIG_REGULATOR_DA9052=m +CONFIG_REGULATOR_DA9055=m +CONFIG_REGULATOR_DA9062=m +CONFIG_REGULATOR_DA9210=m +CONFIG_REGULATOR_DA9211=m +CONFIG_REGULATOR_FAN53555=m +CONFIG_REGULATOR_GPIO=m +CONFIG_REGULATOR_ISL9305=m +CONFIG_REGULATOR_ISL6271A=m +# CONFIG_REGULATOR_LM363X is not set +CONFIG_REGULATOR_LP3971=m +CONFIG_REGULATOR_LP3972=m +CONFIG_REGULATOR_LP872X=m +CONFIG_REGULATOR_LP8755=m +CONFIG_REGULATOR_LP8788=m +CONFIG_REGULATOR_LTC3589=m +# CONFIG_REGULATOR_LTC3676 is not set +CONFIG_REGULATOR_MAX14577=m +CONFIG_REGULATOR_MAX1586=m +CONFIG_REGULATOR_MAX8649=m +CONFIG_REGULATOR_MAX8660=m +CONFIG_REGULATOR_MAX8907=m +CONFIG_REGULATOR_MAX8925=m +CONFIG_REGULATOR_MAX8952=m +CONFIG_REGULATOR_MAX8997=m +CONFIG_REGULATOR_MAX8998=m +CONFIG_REGULATOR_MAX77693=m +CONFIG_REGULATOR_MC13XXX_CORE=m +CONFIG_REGULATOR_MC13783=m +CONFIG_REGULATOR_MC13892=m +CONFIG_REGULATOR_MT6311=m +CONFIG_REGULATOR_PALMAS=m +CONFIG_REGULATOR_PCAP=m +CONFIG_REGULATOR_PFUZE100=m +CONFIG_REGULATOR_PV88060=m +CONFIG_REGULATOR_PV88080=m +CONFIG_REGULATOR_PV88090=m +CONFIG_REGULATOR_PWM=m +CONFIG_REGULATOR_QCOM_SPMI=m +CONFIG_REGULATOR_RC5T583=m +CONFIG_REGULATOR_S2MPA01=m +CONFIG_REGULATOR_S2MPS11=m +CONFIG_REGULATOR_S5M8767=m +# CONFIG_REGULATOR_SLG51000 is not set +CONFIG_REGULATOR_TPS51632=m +CONFIG_REGULATOR_TPS62360=m +CONFIG_REGULATOR_TPS65023=m +CONFIG_REGULATOR_TPS6507X=m +CONFIG_REGULATOR_TPS65086=m +CONFIG_REGULATOR_TPS65090=m +# CONFIG_REGULATOR_TPS65132 is not set +CONFIG_REGULATOR_TPS6524X=m +CONFIG_REGULATOR_TPS6586X=m +CONFIG_REGULATOR_TPS65910=m +CONFIG_REGULATOR_TPS65912=m +CONFIG_REGULATOR_TPS80031=m +CONFIG_REGULATOR_TWL4030=m +CONFIG_REGULATOR_WM831X=m +CONFIG_REGULATOR_WM8350=m +CONFIG_REGULATOR_WM8400=m +CONFIG_REGULATOR_WM8994=m +CONFIG_CEC_CORE=y +CONFIG_CEC_NOTIFIER=y +CONFIG_RC_CORE=m +CONFIG_RC_MAP=m +CONFIG_LIRC=y +CONFIG_RC_DECODERS=y +CONFIG_IR_NEC_DECODER=m +CONFIG_IR_RC5_DECODER=m +CONFIG_IR_RC6_DECODER=m +CONFIG_IR_JVC_DECODER=m +CONFIG_IR_SONY_DECODER=m +CONFIG_IR_SANYO_DECODER=m +CONFIG_IR_SHARP_DECODER=m +CONFIG_IR_MCE_KBD_DECODER=m +CONFIG_IR_XMP_DECODER=m +CONFIG_IR_IMON_DECODER=m +CONFIG_IR_RCMM_DECODER=m +CONFIG_RC_DEVICES=y +CONFIG_RC_ATI_REMOTE=m +CONFIG_IR_ENE=m +CONFIG_IR_IMON=m +CONFIG_IR_IMON_RAW=m +CONFIG_IR_MCEUSB=m +CONFIG_IR_ITE_CIR=m +CONFIG_IR_FINTEK=m +CONFIG_IR_NUVOTON=m +CONFIG_IR_REDRAT3=m +CONFIG_IR_STREAMZAP=m +CONFIG_IR_WINBOND_CIR=m +CONFIG_IR_IGORPLUGUSB=m +CONFIG_IR_IGUANA=m +CONFIG_IR_TTUSBIR=m +CONFIG_RC_LOOPBACK=m +# CONFIG_IR_SERIAL is not set +CONFIG_IR_SIR=m +CONFIG_RC_XBOX_DVD=m +CONFIG_MEDIA_SUPPORT=m + +# +# Multimedia core support +# +CONFIG_MEDIA_CAMERA_SUPPORT=y +CONFIG_MEDIA_ANALOG_TV_SUPPORT=y +CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y +CONFIG_MEDIA_RADIO_SUPPORT=y +CONFIG_MEDIA_SDR_SUPPORT=y +CONFIG_MEDIA_CEC_SUPPORT=y +CONFIG_MEDIA_CONTROLLER=y +CONFIG_MEDIA_CONTROLLER_DVB=y +CONFIG_MEDIA_CONTROLLER_REQUEST_API=y +CONFIG_VIDEO_DEV=m +# CONFIG_VIDEO_V4L2_SUBDEV_API is not set +CONFIG_VIDEO_V4L2=m +CONFIG_VIDEO_V4L2_I2C=y +# CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set +CONFIG_VIDEO_TUNER=m +CONFIG_V4L2_MEM2MEM_DEV=m +CONFIG_V4L2_FWNODE=m +CONFIG_VIDEOBUF_GEN=m +CONFIG_VIDEOBUF_DMA_SG=m +CONFIG_VIDEOBUF_VMALLOC=m +CONFIG_DVB_CORE=m +# CONFIG_DVB_MMAP is not set +CONFIG_DVB_NET=y +CONFIG_TTPCI_EEPROM=m +CONFIG_DVB_MAX_ADAPTERS=8 +# CONFIG_DVB_DYNAMIC_MINORS is not set +# CONFIG_DVB_DEMUX_SECTION_LOSS_LOG is not set +# CONFIG_DVB_ULE_DEBUG is not set + +# +# Media drivers +# +CONFIG_MEDIA_USB_SUPPORT=y + +# +# Webcam devices +# +CONFIG_USB_VIDEO_CLASS=m +CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y +CONFIG_USB_GSPCA=m +CONFIG_USB_M5602=m +CONFIG_USB_STV06XX=m +CONFIG_USB_GL860=m +CONFIG_USB_GSPCA_BENQ=m +CONFIG_USB_GSPCA_CONEX=m +CONFIG_USB_GSPCA_CPIA1=m +CONFIG_USB_GSPCA_DTCS033=m +CONFIG_USB_GSPCA_ETOMS=m +CONFIG_USB_GSPCA_FINEPIX=m +CONFIG_USB_GSPCA_JEILINJ=m +CONFIG_USB_GSPCA_JL2005BCD=m +CONFIG_USB_GSPCA_KINECT=m +CONFIG_USB_GSPCA_KONICA=m +CONFIG_USB_GSPCA_MARS=m +CONFIG_USB_GSPCA_MR97310A=m +CONFIG_USB_GSPCA_NW80X=m +CONFIG_USB_GSPCA_OV519=m +CONFIG_USB_GSPCA_OV534=m +CONFIG_USB_GSPCA_OV534_9=m +CONFIG_USB_GSPCA_PAC207=m +CONFIG_USB_GSPCA_PAC7302=m +CONFIG_USB_GSPCA_PAC7311=m +CONFIG_USB_GSPCA_SE401=m +CONFIG_USB_GSPCA_SN9C2028=m +CONFIG_USB_GSPCA_SN9C20X=m +CONFIG_USB_GSPCA_SONIXB=m +CONFIG_USB_GSPCA_SONIXJ=m +CONFIG_USB_GSPCA_SPCA500=m +CONFIG_USB_GSPCA_SPCA501=m +CONFIG_USB_GSPCA_SPCA505=m +CONFIG_USB_GSPCA_SPCA506=m +CONFIG_USB_GSPCA_SPCA508=m +CONFIG_USB_GSPCA_SPCA561=m +CONFIG_USB_GSPCA_SPCA1528=m +CONFIG_USB_GSPCA_SQ905=m +CONFIG_USB_GSPCA_SQ905C=m +CONFIG_USB_GSPCA_SQ930X=m +CONFIG_USB_GSPCA_STK014=m +CONFIG_USB_GSPCA_STK1135=m +CONFIG_USB_GSPCA_STV0680=m +CONFIG_USB_GSPCA_SUNPLUS=m +CONFIG_USB_GSPCA_T613=m +CONFIG_USB_GSPCA_TOPRO=m +CONFIG_USB_GSPCA_TOUPTEK=m +CONFIG_USB_GSPCA_TV8532=m +CONFIG_USB_GSPCA_VC032X=m +CONFIG_USB_GSPCA_VICAM=m +CONFIG_USB_GSPCA_XIRLINK_CIT=m +CONFIG_USB_GSPCA_ZC3XX=m +CONFIG_USB_PWC=m +# CONFIG_USB_PWC_DEBUG is not set +CONFIG_USB_PWC_INPUT_EVDEV=y +CONFIG_VIDEO_CPIA2=m +CONFIG_USB_ZR364XX=m +CONFIG_USB_STKWEBCAM=m +CONFIG_USB_S2255=m +CONFIG_VIDEO_USBTV=m + +# +# Analog TV USB devices +# +CONFIG_VIDEO_PVRUSB2=m +CONFIG_VIDEO_PVRUSB2_SYSFS=y +CONFIG_VIDEO_PVRUSB2_DVB=y +# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set +CONFIG_VIDEO_HDPVR=m +CONFIG_VIDEO_USBVISION=m +CONFIG_VIDEO_STK1160_COMMON=m +CONFIG_VIDEO_STK1160=m +CONFIG_VIDEO_GO7007=m +CONFIG_VIDEO_GO7007_USB=m +CONFIG_VIDEO_GO7007_LOADER=m +CONFIG_VIDEO_GO7007_USB_S2250_BOARD=m + +# +# Analog/digital TV USB devices +# +CONFIG_VIDEO_AU0828=m +CONFIG_VIDEO_AU0828_V4L2=y +CONFIG_VIDEO_AU0828_RC=y +CONFIG_VIDEO_CX231XX=m +CONFIG_VIDEO_CX231XX_RC=y +CONFIG_VIDEO_CX231XX_ALSA=m +CONFIG_VIDEO_CX231XX_DVB=m +CONFIG_VIDEO_TM6000=m +CONFIG_VIDEO_TM6000_ALSA=m +CONFIG_VIDEO_TM6000_DVB=m + +# +# Digital TV USB devices +# +CONFIG_DVB_USB=m +# CONFIG_DVB_USB_DEBUG is not set +CONFIG_DVB_USB_DIB3000MC=m +CONFIG_DVB_USB_A800=m +CONFIG_DVB_USB_DIBUSB_MB=m +# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set +CONFIG_DVB_USB_DIBUSB_MC=m +CONFIG_DVB_USB_DIB0700=m +CONFIG_DVB_USB_UMT_010=m +CONFIG_DVB_USB_CXUSB=m +# CONFIG_DVB_USB_CXUSB_ANALOG is not set +CONFIG_DVB_USB_M920X=m +CONFIG_DVB_USB_DIGITV=m +CONFIG_DVB_USB_VP7045=m +CONFIG_DVB_USB_VP702X=m +CONFIG_DVB_USB_GP8PSK=m +CONFIG_DVB_USB_NOVA_T_USB2=m +CONFIG_DVB_USB_TTUSB2=m +CONFIG_DVB_USB_DTT200U=m +CONFIG_DVB_USB_OPERA1=m +CONFIG_DVB_USB_AF9005=m +CONFIG_DVB_USB_AF9005_REMOTE=m +CONFIG_DVB_USB_PCTV452E=m +CONFIG_DVB_USB_DW2102=m +CONFIG_DVB_USB_CINERGY_T2=m +CONFIG_DVB_USB_DTV5100=m +CONFIG_DVB_USB_AZ6027=m +CONFIG_DVB_USB_TECHNISAT_USB2=m +CONFIG_DVB_USB_V2=m +CONFIG_DVB_USB_AF9015=m +CONFIG_DVB_USB_AF9035=m +CONFIG_DVB_USB_ANYSEE=m +CONFIG_DVB_USB_AU6610=m +CONFIG_DVB_USB_AZ6007=m +CONFIG_DVB_USB_CE6230=m +CONFIG_DVB_USB_EC168=m +CONFIG_DVB_USB_GL861=m +CONFIG_DVB_USB_LME2510=m +CONFIG_DVB_USB_MXL111SF=m +CONFIG_DVB_USB_RTL28XXU=m +CONFIG_DVB_USB_DVBSKY=m +CONFIG_DVB_USB_ZD1301=m +CONFIG_DVB_TTUSB_BUDGET=m +# CONFIG_DVB_TTUSB_DEC is not set +CONFIG_SMS_USB_DRV=m +CONFIG_DVB_B2C2_FLEXCOP_USB=m +# CONFIG_DVB_B2C2_FLEXCOP_USB_DEBUG is not set +CONFIG_DVB_AS102=m + +# +# Webcam, TV (analog/digital) USB devices +# +CONFIG_VIDEO_EM28XX=m +CONFIG_VIDEO_EM28XX_V4L2=m +CONFIG_VIDEO_EM28XX_ALSA=m +CONFIG_VIDEO_EM28XX_DVB=m +CONFIG_VIDEO_EM28XX_RC=m + +# +# Software defined radio USB devices +# +CONFIG_USB_AIRSPY=m +CONFIG_USB_HACKRF=m +CONFIG_USB_MSI2500=m + +# +# USB HDMI CEC adapters +# +CONFIG_USB_PULSE8_CEC=m +CONFIG_USB_RAINSHADOW_CEC=m +CONFIG_MEDIA_PCI_SUPPORT=y + +# +# Media capture support +# +CONFIG_VIDEO_MEYE=m +CONFIG_VIDEO_SOLO6X10=m +CONFIG_VIDEO_TW5864=m +CONFIG_VIDEO_TW68=m +CONFIG_VIDEO_TW686X=m + +# +# Media capture/analog TV support +# +CONFIG_VIDEO_IVTV=m +# CONFIG_VIDEO_IVTV_DEPRECATED_IOCTLS is not set +CONFIG_VIDEO_IVTV_ALSA=m +CONFIG_VIDEO_FB_IVTV=m +# CONFIG_VIDEO_FB_IVTV_FORCE_PAT is not set +CONFIG_VIDEO_HEXIUM_GEMINI=m +CONFIG_VIDEO_HEXIUM_ORION=m +CONFIG_VIDEO_MXB=m +CONFIG_VIDEO_DT3155=m + +# +# Media capture/analog/hybrid TV support +# +CONFIG_VIDEO_CX18=m +CONFIG_VIDEO_CX18_ALSA=m +CONFIG_VIDEO_CX23885=m +CONFIG_MEDIA_ALTERA_CI=m +CONFIG_VIDEO_CX25821=m +CONFIG_VIDEO_CX25821_ALSA=m +CONFIG_VIDEO_CX88=m +CONFIG_VIDEO_CX88_ALSA=m +CONFIG_VIDEO_CX88_BLACKBIRD=m +CONFIG_VIDEO_CX88_DVB=m +CONFIG_VIDEO_CX88_ENABLE_VP3054=y +CONFIG_VIDEO_CX88_VP3054=m +CONFIG_VIDEO_CX88_MPEG=m +CONFIG_VIDEO_BT848=m +CONFIG_DVB_BT8XX=m +CONFIG_VIDEO_SAA7134=m +CONFIG_VIDEO_SAA7134_ALSA=m +CONFIG_VIDEO_SAA7134_RC=y +CONFIG_VIDEO_SAA7134_DVB=m +CONFIG_VIDEO_SAA7134_GO7007=m +CONFIG_VIDEO_SAA7164=m + +# +# Media digital TV PCI Adapters +# +CONFIG_DVB_AV7110_IR=y +CONFIG_DVB_AV7110=m +CONFIG_DVB_AV7110_OSD=y +CONFIG_DVB_BUDGET_CORE=m +CONFIG_DVB_BUDGET=m +CONFIG_DVB_BUDGET_CI=m +CONFIG_DVB_BUDGET_AV=m +CONFIG_DVB_BUDGET_PATCH=m +CONFIG_DVB_B2C2_FLEXCOP_PCI=m +# CONFIG_DVB_B2C2_FLEXCOP_PCI_DEBUG is not set +CONFIG_DVB_PLUTO2=m +CONFIG_DVB_DM1105=m +CONFIG_DVB_PT1=m +CONFIG_DVB_PT3=m +CONFIG_MANTIS_CORE=m +CONFIG_DVB_MANTIS=m +CONFIG_DVB_HOPPER=m +CONFIG_DVB_NGENE=m +CONFIG_DVB_DDBRIDGE=m +# CONFIG_DVB_DDBRIDGE_MSIENABLE is not set +CONFIG_DVB_SMIPCIE=m +CONFIG_DVB_NETUP_UNIDVB=m +CONFIG_V4L_PLATFORM_DRIVERS=y +CONFIG_VIDEO_CAFE_CCIC=m +CONFIG_VIDEO_VIA_CAMERA=m +CONFIG_VIDEO_CADENCE=y +CONFIG_VIDEO_ASPEED=m +CONFIG_V4L_MEM2MEM_DRIVERS=y +CONFIG_VIDEO_MEM2MEM_DEINTERLACE=m +CONFIG_VIDEO_SH_VEU=m +CONFIG_V4L_TEST_DRIVERS=y +CONFIG_VIDEO_VIVID=m +# CONFIG_VIDEO_VIVID_CEC is not set +CONFIG_VIDEO_VIVID_MAX_DEVS=64 +CONFIG_VIDEO_VIM2M=m +CONFIG_VIDEO_VICODEC=m +CONFIG_DVB_PLATFORM_DRIVERS=y +CONFIG_CEC_PLATFORM_DRIVERS=y +CONFIG_VIDEO_CROS_EC_CEC=m +# CONFIG_VIDEO_SECO_CEC is not set +# CONFIG_SDR_PLATFORM_DRIVERS is not set + +# +# Supported MMC/SDIO adapters +# +CONFIG_SMS_SDIO_DRV=m +CONFIG_RADIO_ADAPTERS=y +CONFIG_RADIO_TEA575X=m +CONFIG_RADIO_SI470X=m +CONFIG_USB_SI470X=m +# CONFIG_I2C_SI470X is not set +# CONFIG_RADIO_SI4713 is not set +# CONFIG_RADIO_SI476X is not set +CONFIG_USB_MR800=m +CONFIG_USB_DSBR=m +CONFIG_RADIO_MAXIRADIO=m +CONFIG_RADIO_SHARK=m +CONFIG_RADIO_SHARK2=m +CONFIG_USB_KEENE=m +CONFIG_USB_RAREMONO=m +CONFIG_USB_MA901=m +CONFIG_RADIO_TEA5764=m +CONFIG_RADIO_SAA7706H=m +CONFIG_RADIO_TEF6862=m +CONFIG_RADIO_WL1273=m + +# +# Texas Instruments WL128x FM driver (ST based) +# +CONFIG_RADIO_WL128X=m +# end of Texas Instruments WL128x FM driver (ST based) + +# +# Supported FireWire (IEEE 1394) Adapters +# +CONFIG_DVB_FIREDTV=m +CONFIG_DVB_FIREDTV_INPUT=y +CONFIG_MEDIA_COMMON_OPTIONS=y + +# +# common driver options +# +CONFIG_VIDEO_CX2341X=m +CONFIG_VIDEO_TVEEPROM=m +CONFIG_CYPRESS_FIRMWARE=m +CONFIG_VIDEOBUF2_CORE=m +CONFIG_VIDEOBUF2_V4L2=m +CONFIG_VIDEOBUF2_MEMOPS=m +CONFIG_VIDEOBUF2_DMA_CONTIG=m +CONFIG_VIDEOBUF2_VMALLOC=m +CONFIG_VIDEOBUF2_DMA_SG=m +CONFIG_VIDEOBUF2_DVB=m +CONFIG_DVB_B2C2_FLEXCOP=m +CONFIG_VIDEO_SAA7146=m +CONFIG_VIDEO_SAA7146_VV=m +CONFIG_SMS_SIANO_MDTV=m +CONFIG_SMS_SIANO_RC=y +# CONFIG_SMS_SIANO_DEBUGFS is not set +CONFIG_VIDEO_V4L2_TPG=m + +# +# Media ancillary drivers (tuners, sensors, i2c, spi, frontends) +# +CONFIG_MEDIA_SUBDRV_AUTOSELECT=y +CONFIG_MEDIA_ATTACH=y +CONFIG_VIDEO_IR_I2C=m + +# +# I2C Encoders, decoders, sensors and other helper chips +# + +# +# Audio decoders, processors and mixers +# +CONFIG_VIDEO_TVAUDIO=m +CONFIG_VIDEO_TDA7432=m +CONFIG_VIDEO_TDA9840=m +CONFIG_VIDEO_TEA6415C=m +CONFIG_VIDEO_TEA6420=m +CONFIG_VIDEO_MSP3400=m +CONFIG_VIDEO_CS3308=m +CONFIG_VIDEO_CS5345=m +CONFIG_VIDEO_CS53L32A=m +CONFIG_VIDEO_TLV320AIC23B=m +CONFIG_VIDEO_UDA1342=m +CONFIG_VIDEO_WM8775=m +CONFIG_VIDEO_WM8739=m +CONFIG_VIDEO_VP27SMPX=m +CONFIG_VIDEO_SONY_BTF_MPX=m + +# +# RDS decoders +# +CONFIG_VIDEO_SAA6588=m + +# +# Video decoders +# +CONFIG_VIDEO_ADV7183=m +CONFIG_VIDEO_BT819=m +CONFIG_VIDEO_BT856=m +CONFIG_VIDEO_BT866=m +CONFIG_VIDEO_KS0127=m +CONFIG_VIDEO_ML86V7667=m +CONFIG_VIDEO_SAA7110=m +CONFIG_VIDEO_SAA711X=m +CONFIG_VIDEO_TVP514X=m +CONFIG_VIDEO_TVP5150=m +CONFIG_VIDEO_TVP7002=m +CONFIG_VIDEO_TW2804=m +CONFIG_VIDEO_TW9903=m +CONFIG_VIDEO_TW9906=m +CONFIG_VIDEO_TW9910=m +CONFIG_VIDEO_VPX3220=m + +# +# Video and audio decoders +# +CONFIG_VIDEO_SAA717X=m +CONFIG_VIDEO_CX25840=m + +# +# Video encoders +# +CONFIG_VIDEO_SAA7127=m +CONFIG_VIDEO_SAA7185=m +CONFIG_VIDEO_ADV7170=m +CONFIG_VIDEO_ADV7175=m +CONFIG_VIDEO_ADV7343=m +CONFIG_VIDEO_ADV7393=m +CONFIG_VIDEO_AK881X=m +CONFIG_VIDEO_THS8200=m + +# +# Camera sensor devices +# +CONFIG_VIDEO_OV2640=m +CONFIG_VIDEO_OV2659=m +CONFIG_VIDEO_OV2680=m +CONFIG_VIDEO_OV2685=m +CONFIG_VIDEO_OV6650=m +CONFIG_VIDEO_OV5695=m +CONFIG_VIDEO_OV772X=m +CONFIG_VIDEO_OV7640=m +CONFIG_VIDEO_OV7670=m +CONFIG_VIDEO_OV7740=m +CONFIG_VIDEO_OV9640=m +CONFIG_VIDEO_VS6624=m +CONFIG_VIDEO_MT9M111=m +CONFIG_VIDEO_MT9T112=m +CONFIG_VIDEO_MT9V011=m +CONFIG_VIDEO_MT9V111=m +CONFIG_VIDEO_SR030PC30=m +CONFIG_VIDEO_RJ54N1=m + +# +# Lens drivers +# +# CONFIG_VIDEO_AD5820 is not set + +# +# Flash devices +# +# CONFIG_VIDEO_ADP1653 is not set +# CONFIG_VIDEO_LM3560 is not set +# CONFIG_VIDEO_LM3646 is not set + +# +# Video improvement chips +# +CONFIG_VIDEO_UPD64031A=m +CONFIG_VIDEO_UPD64083=m + +# +# Audio/Video compression chips +# +CONFIG_VIDEO_SAA6752HS=m + +# +# SDR tuner chips +# +CONFIG_SDR_MAX2175=m + +# +# Miscellaneous helper chips +# +CONFIG_VIDEO_THS7303=m +CONFIG_VIDEO_M52790=m +CONFIG_VIDEO_I2C=m +# end of I2C Encoders, decoders, sensors and other helper chips + +# +# SPI helper chips +# +# end of SPI helper chips + +# +# Media SPI Adapters +# +# CONFIG_CXD2880_SPI_DRV is not set +# end of Media SPI Adapters + +CONFIG_MEDIA_TUNER=m + +# +# Customize TV tuners +# +CONFIG_MEDIA_TUNER_SIMPLE=m +CONFIG_MEDIA_TUNER_TDA18250=m +CONFIG_MEDIA_TUNER_TDA8290=m +CONFIG_MEDIA_TUNER_TDA827X=m +CONFIG_MEDIA_TUNER_TDA18271=m +CONFIG_MEDIA_TUNER_TDA9887=m +CONFIG_MEDIA_TUNER_TEA5761=m +CONFIG_MEDIA_TUNER_TEA5767=m +CONFIG_MEDIA_TUNER_MSI001=m +CONFIG_MEDIA_TUNER_MT20XX=m +CONFIG_MEDIA_TUNER_MT2060=m +CONFIG_MEDIA_TUNER_MT2063=m +CONFIG_MEDIA_TUNER_MT2266=m +CONFIG_MEDIA_TUNER_MT2131=m +CONFIG_MEDIA_TUNER_QT1010=m +CONFIG_MEDIA_TUNER_XC2028=m +CONFIG_MEDIA_TUNER_XC5000=m +CONFIG_MEDIA_TUNER_XC4000=m +CONFIG_MEDIA_TUNER_MXL5005S=m +CONFIG_MEDIA_TUNER_MXL5007T=m +CONFIG_MEDIA_TUNER_MC44S803=m +CONFIG_MEDIA_TUNER_MAX2165=m +CONFIG_MEDIA_TUNER_TDA18218=m +CONFIG_MEDIA_TUNER_FC0011=m +CONFIG_MEDIA_TUNER_FC0012=m +CONFIG_MEDIA_TUNER_FC0013=m +CONFIG_MEDIA_TUNER_TDA18212=m +CONFIG_MEDIA_TUNER_E4000=m +CONFIG_MEDIA_TUNER_FC2580=m +CONFIG_MEDIA_TUNER_M88RS6000T=m +CONFIG_MEDIA_TUNER_TUA9001=m +CONFIG_MEDIA_TUNER_SI2157=m +CONFIG_MEDIA_TUNER_IT913X=m +CONFIG_MEDIA_TUNER_R820T=m +CONFIG_MEDIA_TUNER_MXL301RF=m +CONFIG_MEDIA_TUNER_QM1D1C0042=m +CONFIG_MEDIA_TUNER_QM1D1B0004=m +# end of Customize TV tuners + +# +# Customise DVB Frontends +# + +# +# Multistandard (satellite) frontends +# +CONFIG_DVB_STB0899=m +CONFIG_DVB_STB6100=m +CONFIG_DVB_STV090x=m +CONFIG_DVB_STV0910=m +CONFIG_DVB_STV6110x=m +CONFIG_DVB_STV6111=m +CONFIG_DVB_MXL5XX=m +CONFIG_DVB_M88DS3103=m + +# +# Multistandard (cable + terrestrial) frontends +# +CONFIG_DVB_DRXK=m +CONFIG_DVB_TDA18271C2DD=m +CONFIG_DVB_SI2165=m +CONFIG_DVB_MN88472=m +CONFIG_DVB_MN88473=m + +# +# DVB-S (satellite) frontends +# +CONFIG_DVB_CX24110=m +CONFIG_DVB_CX24123=m +CONFIG_DVB_MT312=m +CONFIG_DVB_ZL10036=m +CONFIG_DVB_ZL10039=m +CONFIG_DVB_S5H1420=m +CONFIG_DVB_STV0288=m +CONFIG_DVB_STB6000=m +CONFIG_DVB_STV0299=m +CONFIG_DVB_STV6110=m +CONFIG_DVB_STV0900=m +CONFIG_DVB_TDA8083=m +CONFIG_DVB_TDA10086=m +CONFIG_DVB_TDA8261=m +CONFIG_DVB_VES1X93=m +CONFIG_DVB_TUNER_ITD1000=m +CONFIG_DVB_TUNER_CX24113=m +CONFIG_DVB_TDA826X=m +CONFIG_DVB_TUA6100=m +CONFIG_DVB_CX24116=m +CONFIG_DVB_CX24117=m +CONFIG_DVB_CX24120=m +CONFIG_DVB_SI21XX=m +CONFIG_DVB_TS2020=m +CONFIG_DVB_DS3000=m +CONFIG_DVB_MB86A16=m +CONFIG_DVB_TDA10071=m + +# +# DVB-T (terrestrial) frontends +# +CONFIG_DVB_SP8870=m +CONFIG_DVB_SP887X=m +CONFIG_DVB_CX22700=m +CONFIG_DVB_CX22702=m +CONFIG_DVB_S5H1432=m +CONFIG_DVB_DRXD=m +CONFIG_DVB_L64781=m +CONFIG_DVB_TDA1004X=m +CONFIG_DVB_NXT6000=m +CONFIG_DVB_MT352=m +CONFIG_DVB_ZL10353=m +CONFIG_DVB_DIB3000MB=m +CONFIG_DVB_DIB3000MC=m +CONFIG_DVB_DIB7000M=m +CONFIG_DVB_DIB7000P=m +CONFIG_DVB_DIB9000=m +CONFIG_DVB_TDA10048=m +CONFIG_DVB_AF9013=m +CONFIG_DVB_EC100=m +CONFIG_DVB_STV0367=m +CONFIG_DVB_CXD2820R=m +CONFIG_DVB_CXD2841ER=m +CONFIG_DVB_RTL2830=m +CONFIG_DVB_RTL2832=m +CONFIG_DVB_RTL2832_SDR=m +CONFIG_DVB_SI2168=m +CONFIG_DVB_AS102_FE=m +CONFIG_DVB_ZD1301_DEMOD=m +CONFIG_DVB_GP8PSK_FE=m +CONFIG_DVB_CXD2880=m + +# +# DVB-C (cable) frontends +# +CONFIG_DVB_VES1820=m +CONFIG_DVB_TDA10021=m +CONFIG_DVB_TDA10023=m +CONFIG_DVB_STV0297=m + +# +# ATSC (North American/Korean Terrestrial/Cable DTV) frontends +# +CONFIG_DVB_NXT200X=m +CONFIG_DVB_OR51211=m +CONFIG_DVB_OR51132=m +CONFIG_DVB_BCM3510=m +CONFIG_DVB_LGDT330X=m +CONFIG_DVB_LGDT3305=m +CONFIG_DVB_LGDT3306A=m +CONFIG_DVB_LG2160=m +CONFIG_DVB_S5H1409=m +CONFIG_DVB_AU8522=m +CONFIG_DVB_AU8522_DTV=m +CONFIG_DVB_AU8522_V4L=m +CONFIG_DVB_S5H1411=m + +# +# ISDB-T (terrestrial) frontends +# +CONFIG_DVB_S921=m +CONFIG_DVB_DIB8000=m +CONFIG_DVB_MB86A20S=m + +# +# ISDB-S (satellite) & ISDB-T (terrestrial) frontends +# +CONFIG_DVB_TC90522=m +CONFIG_DVB_MN88443X=m + +# +# Digital terrestrial only tuners/PLL +# +CONFIG_DVB_PLL=m +CONFIG_DVB_TUNER_DIB0070=m +CONFIG_DVB_TUNER_DIB0090=m + +# +# SEC control devices for DVB-S +# +CONFIG_DVB_DRX39XYJ=m +CONFIG_DVB_LNBH25=m +# CONFIG_DVB_LNBH29 is not set +CONFIG_DVB_LNBP21=m +CONFIG_DVB_LNBP22=m +CONFIG_DVB_ISL6405=m +CONFIG_DVB_ISL6421=m +CONFIG_DVB_ISL6423=m +CONFIG_DVB_A8293=m +CONFIG_DVB_LGS8GL5=m +CONFIG_DVB_LGS8GXX=m +CONFIG_DVB_ATBM8830=m +CONFIG_DVB_TDA665x=m +CONFIG_DVB_IX2505V=m +CONFIG_DVB_M88RS2000=m +CONFIG_DVB_AF9033=m +CONFIG_DVB_HORUS3A=m +CONFIG_DVB_ASCOT2E=m +CONFIG_DVB_HELENE=m + +# +# Common Interface (EN50221) controller drivers +# +CONFIG_DVB_CXD2099=m +CONFIG_DVB_SP2=m + +# +# Tools to develop new frontends +# +CONFIG_DVB_DUMMY_FE=m +# end of Customise DVB Frontends + +# +# Graphics support +# +CONFIG_AGP=y +CONFIG_AGP_AMD64=y +CONFIG_AGP_INTEL=y +CONFIG_AGP_SIS=y +CONFIG_AGP_VIA=y +CONFIG_INTEL_GTT=y +CONFIG_VGA_ARB=y +CONFIG_VGA_ARB_MAX_GPUS=16 +CONFIG_VGA_SWITCHEROO=y +CONFIG_DRM=m +CONFIG_DRM_MIPI_DSI=y +# CONFIG_DRM_DP_AUX_CHARDEV is not set +# CONFIG_DRM_DEBUG_SELFTEST is not set +CONFIG_DRM_KMS_HELPER=m +CONFIG_DRM_KMS_FB_HELPER=y +CONFIG_DRM_FBDEV_EMULATION=y +CONFIG_DRM_FBDEV_OVERALLOC=100 +# CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM is not set +# CONFIG_DRM_LOAD_EDID_FIRMWARE is not set +CONFIG_DRM_DP_CEC=y +CONFIG_DRM_TTM=m +CONFIG_DRM_VRAM_HELPER=m +CONFIG_DRM_GEM_SHMEM_HELPER=y +CONFIG_DRM_VM=y +CONFIG_DRM_SCHED=m + +# +# I2C encoder or helper chips +# +CONFIG_DRM_I2C_CH7006=m +CONFIG_DRM_I2C_SIL164=m +CONFIG_DRM_I2C_NXP_TDA998X=m +CONFIG_DRM_I2C_NXP_TDA9950=m +# end of I2C encoder or helper chips + +# +# ARM devices +# +# end of ARM devices + +CONFIG_DRM_RADEON=m +CONFIG_DRM_RADEON_USERPTR=y +CONFIG_DRM_AMDGPU=m +CONFIG_DRM_AMDGPU_SI=y +CONFIG_DRM_AMDGPU_CIK=y +CONFIG_DRM_AMDGPU_USERPTR=y +# CONFIG_DRM_AMDGPU_GART_DEBUGFS is not set + +# +# ACP (Audio CoProcessor) Configuration +# +CONFIG_DRM_AMD_ACP=y +# end of ACP (Audio CoProcessor) Configuration + +# +# Display Engine Configuration +# +CONFIG_DRM_AMD_DC=y +CONFIG_DRM_AMD_DC_DCN1_0=y +CONFIG_DRM_AMD_DC_DCN2_0=y +CONFIG_DRM_AMD_DC_DCN2_1=y +CONFIG_DRM_AMD_DC_DSC_SUPPORT=y +# CONFIG_DEBUG_KERNEL_DC is not set +# end of Display Engine Configuration + +CONFIG_HSA_AMD=y +CONFIG_DRM_NOUVEAU=m +# CONFIG_NOUVEAU_LEGACY_CTX_SUPPORT is not set +CONFIG_NOUVEAU_DEBUG=5 +CONFIG_NOUVEAU_DEBUG_DEFAULT=3 +# CONFIG_NOUVEAU_DEBUG_MMU is not set +CONFIG_DRM_NOUVEAU_BACKLIGHT=y +CONFIG_DRM_I915=m +CONFIG_DRM_I915_ALPHA_SUPPORT=y +CONFIG_DRM_I915_FORCE_PROBE="*" +CONFIG_DRM_I915_CAPTURE_ERROR=y +CONFIG_DRM_I915_COMPRESS_ERROR=y +CONFIG_DRM_I915_USERPTR=y +# CONFIG_DRM_I915_GVT is not set + +# +# drm/i915 Debugging +# +# CONFIG_DRM_I915_WERROR is not set +# CONFIG_DRM_I915_DEBUG is not set +# CONFIG_DRM_I915_DEBUG_MMIO is not set +# CONFIG_DRM_I915_SW_FENCE_DEBUG_OBJECTS is not set +# CONFIG_DRM_I915_SW_FENCE_CHECK_DAG is not set +# CONFIG_DRM_I915_DEBUG_GUC is not set +# CONFIG_DRM_I915_SELFTEST is not set +# CONFIG_DRM_I915_LOW_LEVEL_TRACEPOINTS is not set +# CONFIG_DRM_I915_DEBUG_VBLANK_EVADE is not set +# CONFIG_DRM_I915_DEBUG_RUNTIME_PM is not set +# end of drm/i915 Debugging + +# +# drm/i915 Profile Guided Optimisation +# +CONFIG_DRM_I915_USERFAULT_AUTOSUSPEND=250 +CONFIG_DRM_I915_SPIN_REQUEST=5 +# end of drm/i915 Profile Guided Optimisation + +CONFIG_DRM_VGEM=m +# CONFIG_DRM_VKMS is not set +CONFIG_DRM_ATI_PCIGART=y +CONFIG_DRM_VMWGFX=m +# CONFIG_DRM_VMWGFX_FBCON is not set +CONFIG_DRM_GMA500=m +CONFIG_DRM_GMA600=y +CONFIG_DRM_GMA3600=y +CONFIG_DRM_UDL=m +CONFIG_DRM_AST=m +CONFIG_DRM_MGAG200=m +CONFIG_DRM_CIRRUS_QEMU=m +CONFIG_DRM_QXL=m +CONFIG_DRM_BOCHS=m +CONFIG_DRM_VIRTIO_GPU=m +CONFIG_DRM_PANEL=y + +# +# Display Panels +# +# CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN is not set +# end of Display Panels + +CONFIG_DRM_BRIDGE=y +CONFIG_DRM_PANEL_BRIDGE=y + +# +# Display Interface Bridges +# +# CONFIG_DRM_ANALOGIX_ANX78XX is not set +# end of Display Interface Bridges + +# CONFIG_DRM_ETNAVIV is not set +CONFIG_DRM_GM12U320=m +# CONFIG_TINYDRM_HX8357D is not set +# CONFIG_TINYDRM_ILI9225 is not set +# CONFIG_TINYDRM_ILI9341 is not set +# CONFIG_TINYDRM_MI0283QT is not set +# CONFIG_TINYDRM_REPAPER is not set +# CONFIG_TINYDRM_ST7586 is not set +# CONFIG_TINYDRM_ST7735R is not set +CONFIG_DRM_XEN=y +CONFIG_DRM_XEN_FRONTEND=m +CONFIG_DRM_VBOXVIDEO=m +CONFIG_DRM_LEGACY=y +CONFIG_DRM_TDFX=m +CONFIG_DRM_R128=m +CONFIG_DRM_I810=m +CONFIG_DRM_MGA=m +CONFIG_DRM_SIS=m +# CONFIG_DRM_VIA is not set +CONFIG_DRM_SAVAGE=m +CONFIG_DRM_PANEL_ORIENTATION_QUIRKS=y + +# +# Frame buffer Devices +# +CONFIG_FB_CMDLINE=y +CONFIG_FB_NOTIFY=y +CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +CONFIG_FB_DDC=m +CONFIG_FB_BOOT_VESA_SUPPORT=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +CONFIG_FB_SYS_FILLRECT=y +CONFIG_FB_SYS_COPYAREA=y +CONFIG_FB_SYS_IMAGEBLIT=y +CONFIG_FB_FOREIGN_ENDIAN=y +CONFIG_FB_BOTH_ENDIAN=y +# CONFIG_FB_BIG_ENDIAN is not set +# CONFIG_FB_LITTLE_ENDIAN is not set +CONFIG_FB_SYS_FOPS=y +CONFIG_FB_DEFERRED_IO=y +CONFIG_FB_SVGALIB=m +CONFIG_FB_BACKLIGHT=m +CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_TILEBLITTING=y + +# +# Frame buffer hardware drivers +# +CONFIG_FB_CIRRUS=m +CONFIG_FB_PM2=m +# CONFIG_FB_PM2_FIFO_DISCONNECT is not set +CONFIG_FB_CYBER2000=m +CONFIG_FB_CYBER2000_DDC=y +CONFIG_FB_ARC=m +# CONFIG_FB_ASILIANT is not set +# CONFIG_FB_IMSTT is not set +CONFIG_FB_VGA16=m +CONFIG_FB_UVESA=m +CONFIG_FB_VESA=y +CONFIG_FB_EFI=y +# CONFIG_FB_N411 is not set +# CONFIG_FB_HGA is not set +CONFIG_FB_OPENCORES=m +# CONFIG_FB_S1D13XXX is not set +CONFIG_FB_NVIDIA=m +CONFIG_FB_NVIDIA_I2C=y +# CONFIG_FB_NVIDIA_DEBUG is not set +CONFIG_FB_NVIDIA_BACKLIGHT=y +CONFIG_FB_RIVA=m +# CONFIG_FB_RIVA_I2C is not set +# CONFIG_FB_RIVA_DEBUG is not set +CONFIG_FB_RIVA_BACKLIGHT=y +CONFIG_FB_I740=m +CONFIG_FB_LE80578=m +CONFIG_FB_CARILLO_RANCH=m +CONFIG_FB_INTEL=m +# CONFIG_FB_INTEL_DEBUG is not set +CONFIG_FB_INTEL_I2C=y +CONFIG_FB_MATROX=m +CONFIG_FB_MATROX_MILLENIUM=y +CONFIG_FB_MATROX_MYSTIQUE=y +CONFIG_FB_MATROX_G=y +CONFIG_FB_MATROX_I2C=m +CONFIG_FB_MATROX_MAVEN=m +CONFIG_FB_RADEON=m +CONFIG_FB_RADEON_I2C=y +CONFIG_FB_RADEON_BACKLIGHT=y +# CONFIG_FB_RADEON_DEBUG is not set +CONFIG_FB_ATY128=m +CONFIG_FB_ATY128_BACKLIGHT=y +CONFIG_FB_ATY=m +CONFIG_FB_ATY_CT=y +CONFIG_FB_ATY_GENERIC_LCD=y +CONFIG_FB_ATY_GX=y +CONFIG_FB_ATY_BACKLIGHT=y +CONFIG_FB_S3=m +CONFIG_FB_S3_DDC=y +CONFIG_FB_SAVAGE=m +CONFIG_FB_SAVAGE_I2C=y +CONFIG_FB_SAVAGE_ACCEL=y +CONFIG_FB_SIS=m +CONFIG_FB_SIS_300=y +CONFIG_FB_SIS_315=y +CONFIG_FB_VIA=m +# CONFIG_FB_VIA_DIRECT_PROCFS is not set +# CONFIG_FB_VIA_X_COMPATIBILITY is not set +CONFIG_FB_NEOMAGIC=m +CONFIG_FB_KYRO=m +CONFIG_FB_3DFX=m +# CONFIG_FB_3DFX_ACCEL is not set +CONFIG_FB_3DFX_I2C=y +CONFIG_FB_VOODOO1=m +CONFIG_FB_VT8623=m +CONFIG_FB_TRIDENT=m +CONFIG_FB_ARK=m +CONFIG_FB_PM3=m +CONFIG_FB_CARMINE=m +CONFIG_FB_CARMINE_DRAM_EVAL=y +# CONFIG_CARMINE_DRAM_CUSTOM is not set +CONFIG_FB_SMSCUFX=m +CONFIG_FB_UDL=m +CONFIG_FB_IBM_GXT4500=m +# CONFIG_FB_VIRTUAL is not set +CONFIG_XEN_FBDEV_FRONTEND=y +# CONFIG_FB_METRONOME is not set +CONFIG_FB_MB862XX=m +CONFIG_FB_MB862XX_PCI_GDC=y +CONFIG_FB_MB862XX_I2C=y +CONFIG_FB_HYPERV=m +CONFIG_FB_SIMPLE=y +CONFIG_FB_SM712=m +# end of Frame buffer Devices + +# +# Backlight & LCD device support +# +CONFIG_LCD_CLASS_DEVICE=m +CONFIG_LCD_L4F00242T03=m +CONFIG_LCD_LMS283GF05=m +CONFIG_LCD_LTV350QV=m +CONFIG_LCD_ILI922X=m +CONFIG_LCD_ILI9320=m +CONFIG_LCD_TDO24M=m +CONFIG_LCD_VGG2432A4=m +# CONFIG_LCD_PLATFORM is not set +CONFIG_LCD_AMS369FG06=m +CONFIG_LCD_LMS501KF03=m +CONFIG_LCD_HX8357=m +# CONFIG_LCD_OTM3225A is not set +CONFIG_BACKLIGHT_CLASS_DEVICE=y +# CONFIG_BACKLIGHT_GENERIC is not set +CONFIG_BACKLIGHT_CARILLO_RANCH=m +CONFIG_BACKLIGHT_PWM=m +CONFIG_BACKLIGHT_DA903X=m +CONFIG_BACKLIGHT_DA9052=m +CONFIG_BACKLIGHT_MAX8925=m +CONFIG_BACKLIGHT_APPLE=m +CONFIG_BACKLIGHT_PM8941_WLED=m +CONFIG_BACKLIGHT_SAHARA=m +CONFIG_BACKLIGHT_WM831X=m +CONFIG_BACKLIGHT_ADP5520=m +CONFIG_BACKLIGHT_ADP8860=m +CONFIG_BACKLIGHT_ADP8870=m +CONFIG_BACKLIGHT_88PM860X=m +CONFIG_BACKLIGHT_AAT2870=m +CONFIG_BACKLIGHT_LM3630A=m +CONFIG_BACKLIGHT_LM3639=m +CONFIG_BACKLIGHT_LP855X=m +CONFIG_BACKLIGHT_LP8788=m +CONFIG_BACKLIGHT_PANDORA=m +CONFIG_BACKLIGHT_AS3711=m +CONFIG_BACKLIGHT_GPIO=m +CONFIG_BACKLIGHT_LV5207LP=m +CONFIG_BACKLIGHT_BD6107=m +CONFIG_BACKLIGHT_ARCXCNN=m +# end of Backlight & LCD device support + +CONFIG_VGASTATE=m +CONFIG_VIDEOMODE_HELPERS=y +CONFIG_HDMI=y + +# +# Console display driver support +# +CONFIG_VGA_CONSOLE=y +# CONFIG_VGACON_SOFT_SCROLLBACK is not set +CONFIG_DUMMY_CONSOLE=y +CONFIG_DUMMY_CONSOLE_COLUMNS=80 +CONFIG_DUMMY_CONSOLE_ROWS=25 +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y +# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set +# CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER is not set +# end of Console display driver support + +# CONFIG_LOGO is not set +# end of Graphics support + +CONFIG_SOUND=m +CONFIG_SOUND_OSS_CORE=y +# CONFIG_SOUND_OSS_CORE_PRECLAIM is not set +CONFIG_SND=m +CONFIG_SND_TIMER=m +CONFIG_SND_PCM=m +CONFIG_SND_PCM_ELD=y +CONFIG_SND_PCM_IEC958=y +CONFIG_SND_HWDEP=m +CONFIG_SND_SEQ_DEVICE=m +CONFIG_SND_RAWMIDI=m +CONFIG_SND_COMPRESS_OFFLOAD=m +CONFIG_SND_JACK=y +CONFIG_SND_JACK_INPUT_DEV=y +CONFIG_SND_OSSEMUL=y +CONFIG_SND_MIXER_OSS=m +CONFIG_SND_PCM_OSS=m +CONFIG_SND_PCM_OSS_PLUGINS=y +CONFIG_SND_PCM_TIMER=y +CONFIG_SND_HRTIMER=m +CONFIG_SND_DYNAMIC_MINORS=y +CONFIG_SND_MAX_CARDS=32 +CONFIG_SND_SUPPORT_OLD_API=y +CONFIG_SND_PROC_FS=y +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +CONFIG_SND_DEBUG=y +# CONFIG_SND_DEBUG_VERBOSE is not set +CONFIG_SND_PCM_XRUN_DEBUG=y +CONFIG_SND_VMASTER=y +CONFIG_SND_DMA_SGBUF=y +CONFIG_SND_SEQUENCER=m +CONFIG_SND_SEQ_DUMMY=m +CONFIG_SND_SEQUENCER_OSS=m +CONFIG_SND_SEQ_HRTIMER_DEFAULT=y +CONFIG_SND_SEQ_MIDI_EVENT=m +CONFIG_SND_SEQ_MIDI=m +CONFIG_SND_SEQ_MIDI_EMUL=m +CONFIG_SND_SEQ_VIRMIDI=m +CONFIG_SND_MPU401_UART=m +CONFIG_SND_OPL3_LIB=m +CONFIG_SND_OPL3_LIB_SEQ=m +CONFIG_SND_VX_LIB=m +CONFIG_SND_AC97_CODEC=m +CONFIG_SND_DRIVERS=y +# CONFIG_SND_PCSP is not set +CONFIG_SND_DUMMY=m +CONFIG_SND_ALOOP=m +CONFIG_SND_VIRMIDI=m +CONFIG_SND_MTPAV=m +CONFIG_SND_MTS64=m +CONFIG_SND_SERIAL_U16550=m +CONFIG_SND_MPU401=m +CONFIG_SND_PORTMAN2X4=m +CONFIG_SND_AC97_POWER_SAVE=y +CONFIG_SND_AC97_POWER_SAVE_DEFAULT=0 +CONFIG_SND_SB_COMMON=m +CONFIG_SND_PCI=y +CONFIG_SND_AD1889=m +CONFIG_SND_ALS300=m +CONFIG_SND_ALS4000=m +CONFIG_SND_ALI5451=m +CONFIG_SND_ASIHPI=m +CONFIG_SND_ATIIXP=m +CONFIG_SND_ATIIXP_MODEM=m +CONFIG_SND_AU8810=m +CONFIG_SND_AU8820=m +CONFIG_SND_AU8830=m +CONFIG_SND_AW2=m +CONFIG_SND_AZT3328=m +CONFIG_SND_BT87X=m +# CONFIG_SND_BT87X_OVERCLOCK is not set +CONFIG_SND_CA0106=m +CONFIG_SND_CMIPCI=m +CONFIG_SND_OXYGEN_LIB=m +CONFIG_SND_OXYGEN=m +CONFIG_SND_CS4281=m +CONFIG_SND_CS46XX=m +CONFIG_SND_CS46XX_NEW_DSP=y +CONFIG_SND_CTXFI=m +CONFIG_SND_DARLA20=m +CONFIG_SND_GINA20=m +CONFIG_SND_LAYLA20=m +CONFIG_SND_DARLA24=m +CONFIG_SND_GINA24=m +CONFIG_SND_LAYLA24=m +CONFIG_SND_MONA=m +CONFIG_SND_MIA=m +CONFIG_SND_ECHO3G=m +CONFIG_SND_INDIGO=m +CONFIG_SND_INDIGOIO=m +CONFIG_SND_INDIGODJ=m +CONFIG_SND_INDIGOIOX=m +CONFIG_SND_INDIGODJX=m +CONFIG_SND_EMU10K1=m +CONFIG_SND_EMU10K1_SEQ=m +CONFIG_SND_EMU10K1X=m +CONFIG_SND_ENS1370=m +CONFIG_SND_ENS1371=m +CONFIG_SND_ES1938=m +CONFIG_SND_ES1968=m +CONFIG_SND_ES1968_INPUT=y +CONFIG_SND_ES1968_RADIO=y +CONFIG_SND_FM801=m +CONFIG_SND_FM801_TEA575X_BOOL=y +CONFIG_SND_HDSP=m +CONFIG_SND_HDSPM=m +CONFIG_SND_ICE1712=m +CONFIG_SND_ICE1724=m +CONFIG_SND_INTEL8X0=m +CONFIG_SND_INTEL8X0M=m +CONFIG_SND_KORG1212=m +CONFIG_SND_LOLA=m +CONFIG_SND_LX6464ES=m +CONFIG_SND_MAESTRO3=m +CONFIG_SND_MAESTRO3_INPUT=y +CONFIG_SND_MIXART=m +CONFIG_SND_NM256=m +CONFIG_SND_PCXHR=m +CONFIG_SND_RIPTIDE=m +CONFIG_SND_RME32=m +CONFIG_SND_RME96=m +CONFIG_SND_RME9652=m +CONFIG_SND_SONICVIBES=m +CONFIG_SND_TRIDENT=m +CONFIG_SND_VIA82XX=m +CONFIG_SND_VIA82XX_MODEM=m +CONFIG_SND_VIRTUOSO=m +CONFIG_SND_VX222=m +CONFIG_SND_YMFPCI=m + +# +# HD-Audio +# +CONFIG_SND_HDA=m +CONFIG_SND_HDA_INTEL=m +# CONFIG_SND_HDA_INTEL_DETECT_DMIC is not set +CONFIG_SND_HDA_HWDEP=y +CONFIG_SND_HDA_RECONFIG=y +CONFIG_SND_HDA_INPUT_BEEP=y +CONFIG_SND_HDA_INPUT_BEEP_MODE=1 +CONFIG_SND_HDA_PATCH_LOADER=y +CONFIG_SND_HDA_CODEC_REALTEK=m +CONFIG_SND_HDA_CODEC_ANALOG=m +CONFIG_SND_HDA_CODEC_SIGMATEL=m +CONFIG_SND_HDA_CODEC_VIA=m +CONFIG_SND_HDA_CODEC_HDMI=m +CONFIG_SND_HDA_CODEC_CIRRUS=m +CONFIG_SND_HDA_CODEC_CONEXANT=m +CONFIG_SND_HDA_CODEC_CA0110=m +CONFIG_SND_HDA_CODEC_CA0132=m +CONFIG_SND_HDA_CODEC_CA0132_DSP=y +CONFIG_SND_HDA_CODEC_CMEDIA=m +CONFIG_SND_HDA_CODEC_SI3054=m +CONFIG_SND_HDA_GENERIC=m +CONFIG_SND_HDA_POWER_SAVE_DEFAULT=0 +# end of HD-Audio + +CONFIG_SND_HDA_CORE=m +CONFIG_SND_HDA_DSP_LOADER=y +CONFIG_SND_HDA_COMPONENT=y +CONFIG_SND_HDA_I915=y +CONFIG_SND_HDA_EXT_CORE=m +CONFIG_SND_HDA_PREALLOC_SIZE=2048 +CONFIG_SND_INTEL_NHLT=m +CONFIG_SND_SPI=y +CONFIG_SND_USB=y +CONFIG_SND_USB_AUDIO=m +CONFIG_SND_USB_AUDIO_USE_MEDIA_CONTROLLER=y +CONFIG_SND_USB_UA101=m +CONFIG_SND_USB_USX2Y=m +CONFIG_SND_USB_CAIAQ=m +CONFIG_SND_USB_CAIAQ_INPUT=y +CONFIG_SND_USB_US122L=m +CONFIG_SND_USB_6FIRE=m +CONFIG_SND_USB_HIFACE=m +CONFIG_SND_BCD2000=m +CONFIG_SND_USB_LINE6=m +# CONFIG_SND_USB_POD is not set +# CONFIG_SND_USB_PODHD is not set +# CONFIG_SND_USB_TONEPORT is not set +CONFIG_SND_USB_VARIAX=m +CONFIG_SND_FIREWIRE=y +CONFIG_SND_FIREWIRE_LIB=m +CONFIG_SND_DICE=m +CONFIG_SND_OXFW=m +CONFIG_SND_ISIGHT=m +CONFIG_SND_FIREWORKS=m +CONFIG_SND_BEBOB=m +CONFIG_SND_FIREWIRE_DIGI00X=m +CONFIG_SND_FIREWIRE_TASCAM=m +CONFIG_SND_FIREWIRE_MOTU=m +CONFIG_SND_FIREFACE=m +CONFIG_SND_PCMCIA=y +CONFIG_SND_VXPOCKET=m +CONFIG_SND_PDAUDIOCF=m +CONFIG_SND_SOC=m +CONFIG_SND_SOC_AC97_BUS=y +CONFIG_SND_SOC_COMPRESS=y +CONFIG_SND_SOC_TOPOLOGY=y +CONFIG_SND_SOC_ACPI=m +CONFIG_SND_SOC_AMD_ACP=m +CONFIG_SND_SOC_AMD_CZ_DA7219MX98357_MACH=m +CONFIG_SND_SOC_AMD_CZ_RT5645_MACH=m +CONFIG_SND_SOC_AMD_ACP3x=m +# CONFIG_SND_ATMEL_SOC is not set +# CONFIG_SND_DESIGNWARE_I2S is not set + +# +# SoC Audio for Freescale CPUs +# + +# +# Common SoC Audio options for Freescale CPUs: +# +# CONFIG_SND_SOC_FSL_ASRC is not set +# CONFIG_SND_SOC_FSL_SAI is not set +# CONFIG_SND_SOC_FSL_AUDMIX is not set +# CONFIG_SND_SOC_FSL_SSI is not set +# CONFIG_SND_SOC_FSL_SPDIF is not set +# CONFIG_SND_SOC_FSL_ESAI is not set +# CONFIG_SND_SOC_FSL_MICFIL is not set +# CONFIG_SND_SOC_IMX_AUDMUX is not set +# end of SoC Audio for Freescale CPUs + +# CONFIG_SND_I2S_HI6210_I2S is not set +# CONFIG_SND_SOC_IMG is not set +CONFIG_SND_SOC_INTEL_SST_TOPLEVEL=y +CONFIG_SND_SST_IPC=m +CONFIG_SND_SST_IPC_PCI=m +CONFIG_SND_SST_IPC_ACPI=m +CONFIG_SND_SOC_INTEL_SST_ACPI=m +CONFIG_SND_SOC_INTEL_SST=m +CONFIG_SND_SOC_INTEL_SST_FIRMWARE=m +CONFIG_SND_SOC_INTEL_HASWELL=m +CONFIG_SND_SST_ATOM_HIFI2_PLATFORM=m +CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_PCI=m +CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_ACPI=m +CONFIG_SND_SOC_INTEL_SKYLAKE=m +CONFIG_SND_SOC_INTEL_SKL=m +CONFIG_SND_SOC_INTEL_APL=m +CONFIG_SND_SOC_INTEL_KBL=m +CONFIG_SND_SOC_INTEL_GLK=m +CONFIG_SND_SOC_INTEL_CNL=m +CONFIG_SND_SOC_INTEL_CFL=m +CONFIG_SND_SOC_INTEL_CML_H=m +CONFIG_SND_SOC_INTEL_CML_LP=m +CONFIG_SND_SOC_INTEL_SKYLAKE_FAMILY=m +CONFIG_SND_SOC_INTEL_SKYLAKE_SSP_CLK=m +CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC=y +CONFIG_SND_SOC_INTEL_SKYLAKE_COMMON=m +CONFIG_SND_SOC_ACPI_INTEL_MATCH=m +CONFIG_SND_SOC_INTEL_MACH=y +CONFIG_SND_SOC_INTEL_HASWELL_MACH=m +CONFIG_SND_SOC_INTEL_BDW_RT5677_MACH=m +CONFIG_SND_SOC_INTEL_BROADWELL_MACH=m +CONFIG_SND_SOC_INTEL_BYTCR_RT5640_MACH=m +CONFIG_SND_SOC_INTEL_BYTCR_RT5651_MACH=m +CONFIG_SND_SOC_INTEL_CHT_BSW_RT5672_MACH=m +CONFIG_SND_SOC_INTEL_CHT_BSW_RT5645_MACH=m +CONFIG_SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH=m +CONFIG_SND_SOC_INTEL_CHT_BSW_NAU8824_MACH=m +CONFIG_SND_SOC_INTEL_BYT_CHT_CX2072X_MACH=m +CONFIG_SND_SOC_INTEL_BYT_CHT_DA7213_MACH=m +CONFIG_SND_SOC_INTEL_BYT_CHT_ES8316_MACH=m +CONFIG_SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH=m +CONFIG_SND_SOC_INTEL_SKL_RT286_MACH=m +CONFIG_SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH=m +CONFIG_SND_SOC_INTEL_SKL_NAU88L25_MAX98357A_MACH=m +CONFIG_SND_SOC_INTEL_DA7219_MAX98357A_GENERIC=m +CONFIG_SND_SOC_INTEL_BXT_DA7219_MAX98357A_MACH=m +CONFIG_SND_SOC_INTEL_BXT_RT298_MACH=m +CONFIG_SND_SOC_INTEL_KBL_RT5663_MAX98927_MACH=m +CONFIG_SND_SOC_INTEL_KBL_RT5663_RT5514_MAX98927_MACH=m +CONFIG_SND_SOC_INTEL_KBL_DA7219_MAX98357A_MACH=m +CONFIG_SND_SOC_INTEL_KBL_DA7219_MAX98927_MACH=m +CONFIG_SND_SOC_INTEL_KBL_RT5660_MACH=m +CONFIG_SND_SOC_INTEL_GLK_RT5682_MAX98357A_MACH=m +CONFIG_SND_SOC_INTEL_SKL_HDA_DSP_GENERIC_MACH=m +CONFIG_SND_SOC_INTEL_SOF_RT5682_MACH=m +CONFIG_SND_SOC_INTEL_CML_LP_DA7219_MAX98357A_MACH=m +CONFIG_SND_SOC_MTK_BTCVSD=m +CONFIG_SND_SOC_SOF_TOPLEVEL=y +CONFIG_SND_SOC_SOF_PCI=m +CONFIG_SND_SOC_SOF_ACPI=m +CONFIG_SND_SOC_SOF_OPTIONS=m +# CONFIG_SND_SOC_SOF_NOCODEC_SUPPORT is not set +# CONFIG_SND_SOC_SOF_STRICT_ABI_CHECKS is not set +# CONFIG_SND_SOC_SOF_DEBUG is not set +CONFIG_SND_SOC_SOF=m +CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE=y +CONFIG_SND_SOC_SOF_INTEL_TOPLEVEL=y +CONFIG_SND_SOC_SOF_INTEL_ACPI=m +CONFIG_SND_SOC_SOF_INTEL_PCI=m +CONFIG_SND_SOC_SOF_INTEL_HIFI_EP_IPC=m +CONFIG_SND_SOC_SOF_INTEL_ATOM_HIFI_EP=m +CONFIG_SND_SOC_SOF_INTEL_COMMON=m +CONFIG_SND_SOC_SOF_BAYTRAIL_SUPPORT=y +CONFIG_SND_SOC_SOF_BAYTRAIL=m +CONFIG_SND_SOC_SOF_BROADWELL_SUPPORT=y +CONFIG_SND_SOC_SOF_BROADWELL=m +CONFIG_SND_SOC_SOF_MERRIFIELD_SUPPORT=y +CONFIG_SND_SOC_SOF_MERRIFIELD=m +CONFIG_SND_SOC_SOF_APOLLOLAKE_SUPPORT=y +CONFIG_SND_SOC_SOF_APOLLOLAKE=m +CONFIG_SND_SOC_SOF_GEMINILAKE_SUPPORT=y +CONFIG_SND_SOC_SOF_GEMINILAKE=m +CONFIG_SND_SOC_SOF_CANNONLAKE_SUPPORT=y +CONFIG_SND_SOC_SOF_CANNONLAKE=m +CONFIG_SND_SOC_SOF_COFFEELAKE_SUPPORT=y +CONFIG_SND_SOC_SOF_COFFEELAKE=m +CONFIG_SND_SOC_SOF_ICELAKE_SUPPORT=y +CONFIG_SND_SOC_SOF_ICELAKE=m +CONFIG_SND_SOC_SOF_COMETLAKE_LP=m +CONFIG_SND_SOC_SOF_COMETLAKE_LP_SUPPORT=y +CONFIG_SND_SOC_SOF_COMETLAKE_H=m +CONFIG_SND_SOC_SOF_COMETLAKE_H_SUPPORT=y +CONFIG_SND_SOC_SOF_TIGERLAKE_SUPPORT=y +CONFIG_SND_SOC_SOF_TIGERLAKE=m +CONFIG_SND_SOC_SOF_ELKHARTLAKE_SUPPORT=y +CONFIG_SND_SOC_SOF_ELKHARTLAKE=m +CONFIG_SND_SOC_SOF_HDA_COMMON=m +CONFIG_SND_SOC_SOF_HDA_LINK=y +CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC=y +# CONFIG_SND_SOC_SOF_HDA_ALWAYS_ENABLE_DMI_L1 is not set +CONFIG_SND_SOC_SOF_HDA_LINK_BASELINE=m +CONFIG_SND_SOC_SOF_HDA=m +CONFIG_SND_SOC_SOF_XTENSA=m + +# +# STMicroelectronics STM32 SOC audio support +# +# end of STMicroelectronics STM32 SOC audio support + +CONFIG_SND_SOC_XILINX_I2S=m +# CONFIG_SND_SOC_XILINX_AUDIO_FORMATTER is not set +# CONFIG_SND_SOC_XILINX_SPDIF is not set +# CONFIG_SND_SOC_XTFPGA_I2S is not set +# CONFIG_ZX_TDM is not set +CONFIG_SND_SOC_I2C_AND_SPI=m + +# +# CODEC drivers +# +CONFIG_SND_SOC_AC97_CODEC=m +CONFIG_SND_SOC_ADAU_UTILS=m +# CONFIG_SND_SOC_ADAU1701 is not set +CONFIG_SND_SOC_ADAU17X1=m +CONFIG_SND_SOC_ADAU1761=m +CONFIG_SND_SOC_ADAU1761_I2C=m +CONFIG_SND_SOC_ADAU1761_SPI=m +CONFIG_SND_SOC_ADAU7002=m +# CONFIG_SND_SOC_AK4104 is not set +# CONFIG_SND_SOC_AK4118 is not set +# CONFIG_SND_SOC_AK4458 is not set +# CONFIG_SND_SOC_AK4554 is not set +# CONFIG_SND_SOC_AK4613 is not set +# CONFIG_SND_SOC_AK4642 is not set +# CONFIG_SND_SOC_AK5386 is not set +# CONFIG_SND_SOC_AK5558 is not set +# CONFIG_SND_SOC_ALC5623 is not set +# CONFIG_SND_SOC_BD28623 is not set +# CONFIG_SND_SOC_BT_SCO is not set +# CONFIG_SND_SOC_CROS_EC_CODEC is not set +# CONFIG_SND_SOC_CS35L32 is not set +# CONFIG_SND_SOC_CS35L33 is not set +CONFIG_SND_SOC_CS35L34=m +CONFIG_SND_SOC_CS35L35=m +CONFIG_SND_SOC_CS35L36=m +CONFIG_SND_SOC_CS42L42=m +# CONFIG_SND_SOC_CS42L51_I2C is not set +# CONFIG_SND_SOC_CS42L52 is not set +# CONFIG_SND_SOC_CS42L56 is not set +# CONFIG_SND_SOC_CS42L73 is not set +# CONFIG_SND_SOC_CS4265 is not set +# CONFIG_SND_SOC_CS4270 is not set +# CONFIG_SND_SOC_CS4271_I2C is not set +# CONFIG_SND_SOC_CS4271_SPI is not set +# CONFIG_SND_SOC_CS42XX8_I2C is not set +CONFIG_SND_SOC_CS43130=m +CONFIG_SND_SOC_CS4341=m +# CONFIG_SND_SOC_CS4349 is not set +# CONFIG_SND_SOC_CS53L30 is not set +CONFIG_SND_SOC_CX2072X=m +CONFIG_SND_SOC_DA7213=m +CONFIG_SND_SOC_DA7219=m +CONFIG_SND_SOC_DMIC=m +CONFIG_SND_SOC_HDMI_CODEC=m +# CONFIG_SND_SOC_ES7134 is not set +# CONFIG_SND_SOC_ES7241 is not set +CONFIG_SND_SOC_ES8316=m +# CONFIG_SND_SOC_ES8328_I2C is not set +# CONFIG_SND_SOC_ES8328_SPI is not set +# CONFIG_SND_SOC_GTM601 is not set +CONFIG_SND_SOC_HDAC_HDMI=m +CONFIG_SND_SOC_HDAC_HDA=m +# CONFIG_SND_SOC_INNO_RK3036 is not set +CONFIG_SND_SOC_MAX98088=m +CONFIG_SND_SOC_MAX98090=m +CONFIG_SND_SOC_MAX98357A=m +# CONFIG_SND_SOC_MAX98504 is not set +# CONFIG_SND_SOC_MAX9867 is not set +CONFIG_SND_SOC_MAX98927=m +CONFIG_SND_SOC_MAX98373=m +# CONFIG_SND_SOC_MAX9860 is not set +# CONFIG_SND_SOC_MSM8916_WCD_ANALOG is not set +# CONFIG_SND_SOC_MSM8916_WCD_DIGITAL is not set +# CONFIG_SND_SOC_PCM1681 is not set +# CONFIG_SND_SOC_PCM1789_I2C is not set +# CONFIG_SND_SOC_PCM179X_I2C is not set +# CONFIG_SND_SOC_PCM179X_SPI is not set +# CONFIG_SND_SOC_PCM186X_I2C is not set +# CONFIG_SND_SOC_PCM186X_SPI is not set +# CONFIG_SND_SOC_PCM3060_I2C is not set +# CONFIG_SND_SOC_PCM3060_SPI is not set +# CONFIG_SND_SOC_PCM3168A_I2C is not set +# CONFIG_SND_SOC_PCM3168A_SPI is not set +# CONFIG_SND_SOC_PCM512x_I2C is not set +# CONFIG_SND_SOC_PCM512x_SPI is not set +# CONFIG_SND_SOC_RK3328 is not set +CONFIG_SND_SOC_RL6231=m +CONFIG_SND_SOC_RL6347A=m +CONFIG_SND_SOC_RT286=m +CONFIG_SND_SOC_RT298=m +CONFIG_SND_SOC_RT5514=m +CONFIG_SND_SOC_RT5514_SPI=m +# CONFIG_SND_SOC_RT5616 is not set +# CONFIG_SND_SOC_RT5631 is not set +CONFIG_SND_SOC_RT5640=m +CONFIG_SND_SOC_RT5645=m +CONFIG_SND_SOC_RT5651=m +CONFIG_SND_SOC_RT5660=m +CONFIG_SND_SOC_RT5663=m +CONFIG_SND_SOC_RT5670=m +CONFIG_SND_SOC_RT5677=m +CONFIG_SND_SOC_RT5677_SPI=m +CONFIG_SND_SOC_RT5682=m +# CONFIG_SND_SOC_SGTL5000 is not set +CONFIG_SND_SOC_SIGMADSP=m +CONFIG_SND_SOC_SIGMADSP_REGMAP=m +# CONFIG_SND_SOC_SIMPLE_AMPLIFIER is not set +# CONFIG_SND_SOC_SIRF_AUDIO_CODEC is not set +# CONFIG_SND_SOC_SPDIF is not set +# CONFIG_SND_SOC_SSM2305 is not set +# CONFIG_SND_SOC_SSM2602_SPI is not set +# CONFIG_SND_SOC_SSM2602_I2C is not set +CONFIG_SND_SOC_SSM4567=m +# CONFIG_SND_SOC_STA32X is not set +# CONFIG_SND_SOC_STA350 is not set +# CONFIG_SND_SOC_STI_SAS is not set +# CONFIG_SND_SOC_TAS2552 is not set +# CONFIG_SND_SOC_TAS5086 is not set +# CONFIG_SND_SOC_TAS571X is not set +# CONFIG_SND_SOC_TAS5720 is not set +# CONFIG_SND_SOC_TAS6424 is not set +# CONFIG_SND_SOC_TDA7419 is not set +# CONFIG_SND_SOC_TFA9879 is not set +# CONFIG_SND_SOC_TLV320AIC23_I2C is not set +# CONFIG_SND_SOC_TLV320AIC23_SPI is not set +# CONFIG_SND_SOC_TLV320AIC31XX is not set +# CONFIG_SND_SOC_TLV320AIC32X4_I2C is not set +# CONFIG_SND_SOC_TLV320AIC32X4_SPI is not set +# CONFIG_SND_SOC_TLV320AIC3X is not set +CONFIG_SND_SOC_TS3A227E=m +# CONFIG_SND_SOC_TSCS42XX is not set +# CONFIG_SND_SOC_TSCS454 is not set +# CONFIG_SND_SOC_UDA1334 is not set +# CONFIG_SND_SOC_WM8510 is not set +# CONFIG_SND_SOC_WM8523 is not set +CONFIG_SND_SOC_WM8524=m +# CONFIG_SND_SOC_WM8580 is not set +# CONFIG_SND_SOC_WM8711 is not set +# CONFIG_SND_SOC_WM8728 is not set +# CONFIG_SND_SOC_WM8731 is not set +# CONFIG_SND_SOC_WM8737 is not set +# CONFIG_SND_SOC_WM8741 is not set +# CONFIG_SND_SOC_WM8750 is not set +# CONFIG_SND_SOC_WM8753 is not set +# CONFIG_SND_SOC_WM8770 is not set +# CONFIG_SND_SOC_WM8776 is not set +CONFIG_SND_SOC_WM8782=m +# CONFIG_SND_SOC_WM8804_I2C is not set +# CONFIG_SND_SOC_WM8804_SPI is not set +# CONFIG_SND_SOC_WM8903 is not set +# CONFIG_SND_SOC_WM8904 is not set +# CONFIG_SND_SOC_WM8960 is not set +# CONFIG_SND_SOC_WM8962 is not set +# CONFIG_SND_SOC_WM8974 is not set +# CONFIG_SND_SOC_WM8978 is not set +# CONFIG_SND_SOC_WM8985 is not set +CONFIG_SND_SOC_ZX_AUD96P22=m +# CONFIG_SND_SOC_MAX9759 is not set +# CONFIG_SND_SOC_MT6351 is not set +# CONFIG_SND_SOC_MT6358 is not set +CONFIG_SND_SOC_NAU8540=m +CONFIG_SND_SOC_NAU8810=m +# CONFIG_SND_SOC_NAU8822 is not set +CONFIG_SND_SOC_NAU8824=m +CONFIG_SND_SOC_NAU8825=m +# CONFIG_SND_SOC_TPA6130A2 is not set +# end of CODEC drivers + +# CONFIG_SND_SIMPLE_CARD is not set +CONFIG_SND_X86=y +CONFIG_HDMI_LPE_AUDIO=m +CONFIG_SND_SYNTH_EMUX=m +CONFIG_SND_XEN_FRONTEND=m +CONFIG_AC97_BUS=m + +# +# HID support +# +CONFIG_HID=m +CONFIG_HID_BATTERY_STRENGTH=y +CONFIG_HIDRAW=y +CONFIG_UHID=m +CONFIG_HID_GENERIC=m + +# +# Special HID drivers +# +CONFIG_HID_A4TECH=m +# CONFIG_HID_ACCUTOUCH is not set +CONFIG_HID_ACRUX=m +CONFIG_HID_ACRUX_FF=y +CONFIG_HID_APPLE=m +CONFIG_HID_APPLEIR=m +CONFIG_HID_ASUS=m +CONFIG_HID_AUREAL=m +CONFIG_HID_BELKIN=m +CONFIG_HID_BETOP_FF=m +CONFIG_HID_BIGBEN_FF=m +CONFIG_HID_CHERRY=m +CONFIG_HID_CHICONY=m +CONFIG_HID_CORSAIR=m +CONFIG_HID_COUGAR=m +CONFIG_HID_MACALLY=m +CONFIG_HID_PRODIKEYS=m +CONFIG_HID_CMEDIA=m +CONFIG_HID_CP2112=m +CONFIG_HID_CREATIVE_SB0540=m +CONFIG_HID_CYPRESS=m +CONFIG_HID_DRAGONRISE=m +CONFIG_DRAGONRISE_FF=y +CONFIG_HID_EMS_FF=m +CONFIG_HID_ELAN=m +CONFIG_HID_ELECOM=m +CONFIG_HID_ELO=m +CONFIG_HID_EZKEY=m +CONFIG_HID_GEMBIRD=m +CONFIG_HID_GFRM=m +CONFIG_HID_HOLTEK=m +CONFIG_HOLTEK_FF=y +CONFIG_HID_GOOGLE_HAMMER=m +CONFIG_HID_GT683R=m +CONFIG_HID_KEYTOUCH=m +CONFIG_HID_KYE=m +CONFIG_HID_UCLOGIC=m +CONFIG_HID_WALTOP=m +# CONFIG_HID_VIEWSONIC is not set +CONFIG_HID_GYRATION=m +CONFIG_HID_ICADE=m +CONFIG_HID_ITE=m +CONFIG_HID_JABRA=m +CONFIG_HID_TWINHAN=m +CONFIG_HID_KENSINGTON=m +CONFIG_HID_LCPOWER=m +CONFIG_HID_LED=m +CONFIG_HID_LENOVO=m +CONFIG_HID_LOGITECH=m +CONFIG_HID_LOGITECH_DJ=m +CONFIG_HID_LOGITECH_HIDPP=m +CONFIG_LOGITECH_FF=y +CONFIG_LOGIRUMBLEPAD2_FF=y +CONFIG_LOGIG940_FF=y +CONFIG_LOGIWHEELS_FF=y +CONFIG_HID_MAGICMOUSE=m +# CONFIG_HID_MALTRON is not set +CONFIG_HID_MAYFLASH=m +CONFIG_HID_REDRAGON=m +CONFIG_HID_MICROSOFT=m +CONFIG_HID_MONTEREY=m +CONFIG_HID_MULTITOUCH=m +# CONFIG_HID_NTI is not set +CONFIG_HID_NTRIG=m +CONFIG_HID_ORTEK=m +CONFIG_HID_PANTHERLORD=m +CONFIG_PANTHERLORD_FF=y +CONFIG_HID_PENMOUNT=m +CONFIG_HID_PETALYNX=m +CONFIG_HID_PICOLCD=m +CONFIG_HID_PICOLCD_FB=y +CONFIG_HID_PICOLCD_BACKLIGHT=y +CONFIG_HID_PICOLCD_LCD=y +CONFIG_HID_PICOLCD_LEDS=y +CONFIG_HID_PICOLCD_CIR=y +CONFIG_HID_PLANTRONICS=m +CONFIG_HID_PRIMAX=m +CONFIG_HID_RETRODE=m +CONFIG_HID_ROCCAT=m +CONFIG_HID_SAITEK=m +CONFIG_HID_SAMSUNG=m +CONFIG_HID_SONY=m +CONFIG_SONY_FF=y +CONFIG_HID_SPEEDLINK=m +CONFIG_HID_STEAM=m +CONFIG_HID_STEELSERIES=m +CONFIG_HID_SUNPLUS=m +CONFIG_HID_RMI=m +CONFIG_HID_GREENASIA=m +CONFIG_GREENASIA_FF=y +CONFIG_HID_HYPERV_MOUSE=m +CONFIG_HID_SMARTJOYPLUS=m +CONFIG_SMARTJOYPLUS_FF=y +CONFIG_HID_TIVO=m +CONFIG_HID_TOPSEED=m +CONFIG_HID_THINGM=m +CONFIG_HID_THRUSTMASTER=m +CONFIG_THRUSTMASTER_FF=y +# CONFIG_HID_UDRAW_PS3 is not set +# CONFIG_HID_U2FZERO is not set +CONFIG_HID_WACOM=m +CONFIG_HID_WIIMOTE=m +CONFIG_HID_XINMO=m +CONFIG_HID_ZEROPLUS=m +CONFIG_ZEROPLUS_FF=y +CONFIG_HID_ZYDACRON=m +CONFIG_HID_SENSOR_HUB=m +# CONFIG_HID_SENSOR_CUSTOM_SENSOR is not set +# CONFIG_HID_ALPS is not set +# end of Special HID drivers + +# +# USB HID support +# +CONFIG_USB_HID=m +CONFIG_HID_PID=y +CONFIG_USB_HIDDEV=y + +# +# USB HID Boot Protocol drivers +# +# CONFIG_USB_KBD is not set +# CONFIG_USB_MOUSE is not set +# end of USB HID Boot Protocol drivers +# end of USB HID support + +# +# I2C HID support +# +CONFIG_I2C_HID=m +# end of I2C HID support + +# +# Intel ISH HID support +# +CONFIG_INTEL_ISH_HID=m +CONFIG_INTEL_ISH_FIRMWARE_DOWNLOADER=m +# end of Intel ISH HID support +# end of HID support + +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +CONFIG_USB_SUPPORT=y +CONFIG_USB_COMMON=m +# CONFIG_USB_LED_TRIG is not set +CONFIG_USB_ULPI_BUS=m +# CONFIG_USB_CONN_GPIO is not set +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB=m +CONFIG_USB_PCI=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y + +# +# Miscellaneous USB options +# +CONFIG_USB_DEFAULT_PERSIST=y +CONFIG_USB_DYNAMIC_MINORS=y +CONFIG_USB_OTG=y +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +CONFIG_USB_OTG_FSM=m +# CONFIG_USB_LEDS_TRIGGER_USBPORT is not set +CONFIG_USB_AUTOSUSPEND_DELAY=2 +CONFIG_USB_MON=m + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +CONFIG_USB_XHCI_HCD=m +# CONFIG_USB_XHCI_DBGCAP is not set +CONFIG_USB_XHCI_PCI=m +CONFIG_USB_XHCI_PLATFORM=m +CONFIG_USB_EHCI_HCD=m +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_TT_NEWSCHED=y +CONFIG_USB_EHCI_PCI=m +# CONFIG_USB_EHCI_FSL is not set +CONFIG_USB_EHCI_HCD_PLATFORM=m +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +CONFIG_USB_FOTG210_HCD=m +CONFIG_USB_MAX3421_HCD=m +CONFIG_USB_OHCI_HCD=m +CONFIG_USB_OHCI_HCD_PCI=m +# CONFIG_USB_OHCI_HCD_SSB is not set +CONFIG_USB_OHCI_HCD_PLATFORM=m +CONFIG_USB_UHCI_HCD=m +CONFIG_USB_U132_HCD=m +CONFIG_USB_SL811_HCD=m +# CONFIG_USB_SL811_HCD_ISO is not set +CONFIG_USB_SL811_CS=m +# CONFIG_USB_R8A66597_HCD is not set +CONFIG_USB_HCD_BCMA=m +CONFIG_USB_HCD_SSB=m +# CONFIG_USB_HCD_TEST_MODE is not set + +# +# USB Device Class drivers +# +CONFIG_USB_ACM=m +CONFIG_USB_PRINTER=m +CONFIG_USB_WDM=m +CONFIG_USB_TMC=m + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may +# + +# +# also be needed; see USB_STORAGE Help for more info +# +CONFIG_USB_STORAGE=m +# CONFIG_USB_STORAGE_DEBUG is not set +CONFIG_USB_STORAGE_REALTEK=m +CONFIG_REALTEK_AUTOPM=y +CONFIG_USB_STORAGE_DATAFAB=m +CONFIG_USB_STORAGE_FREECOM=m +CONFIG_USB_STORAGE_ISD200=m +CONFIG_USB_STORAGE_USBAT=m +CONFIG_USB_STORAGE_SDDR09=m +CONFIG_USB_STORAGE_SDDR55=m +CONFIG_USB_STORAGE_JUMPSHOT=m +CONFIG_USB_STORAGE_ALAUDA=m +CONFIG_USB_STORAGE_ONETOUCH=m +CONFIG_USB_STORAGE_KARMA=m +CONFIG_USB_STORAGE_CYPRESS_ATACB=m +CONFIG_USB_STORAGE_ENE_UB6250=m +CONFIG_USB_UAS=m + +# +# USB Imaging devices +# +CONFIG_USB_MDC800=m +CONFIG_USB_MICROTEK=m +CONFIG_USBIP_CORE=m +CONFIG_USBIP_VHCI_HCD=m +CONFIG_USBIP_VHCI_HC_PORTS=8 +CONFIG_USBIP_VHCI_NR_HCS=1 +CONFIG_USBIP_HOST=m +# CONFIG_USBIP_DEBUG is not set +CONFIG_USB_CDNS3=m +CONFIG_USB_CDNS3_HOST=y +CONFIG_USB_CDNS3_PCI_WRAP=m +CONFIG_USB_MUSB_HDRC=m +CONFIG_USB_MUSB_HOST=y + +# +# Platform Glue Layer +# + +# +# MUSB DMA mode +# +CONFIG_MUSB_PIO_ONLY=y +CONFIG_USB_DWC3=m +# CONFIG_USB_DWC3_ULPI is not set +CONFIG_USB_DWC3_HOST=y + +# +# Platform Glue Driver Support +# +CONFIG_USB_DWC3_PCI=m +CONFIG_USB_DWC3_HAPS=m +CONFIG_USB_DWC2=m +CONFIG_USB_DWC2_HOST=y + +# +# Gadget/Dual-role mode requires USB Gadget support to be enabled +# +CONFIG_USB_DWC2_PCI=m +# CONFIG_USB_DWC2_DEBUG is not set +# CONFIG_USB_DWC2_TRACK_MISSED_SOFS is not set +# CONFIG_USB_CHIPIDEA is not set +# CONFIG_USB_ISP1760 is not set + +# +# USB port drivers +# +CONFIG_USB_USS720=m +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_SIMPLE=m +CONFIG_USB_SERIAL_AIRCABLE=m +CONFIG_USB_SERIAL_ARK3116=m +CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_CH341=m +CONFIG_USB_SERIAL_WHITEHEAT=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_CP210X=m +CONFIG_USB_SERIAL_CYPRESS_M8=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IR=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +CONFIG_USB_SERIAL_F81232=m +CONFIG_USB_SERIAL_F8153X=m +CONFIG_USB_SERIAL_GARMIN=m +CONFIG_USB_SERIAL_IPW=m +CONFIG_USB_SERIAL_IUU=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KEYSPAN=m +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_METRO=m +CONFIG_USB_SERIAL_MOS7720=m +CONFIG_USB_SERIAL_MOS7715_PARPORT=y +CONFIG_USB_SERIAL_MOS7840=m +CONFIG_USB_SERIAL_MXUPORT=m +CONFIG_USB_SERIAL_NAVMAN=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_OTI6858=m +CONFIG_USB_SERIAL_QCAUX=m +CONFIG_USB_SERIAL_QUALCOMM=m +CONFIG_USB_SERIAL_SPCP8X5=m +CONFIG_USB_SERIAL_SAFE=m +CONFIG_USB_SERIAL_SAFE_PADDED=y +CONFIG_USB_SERIAL_SIERRAWIRELESS=m +CONFIG_USB_SERIAL_SYMBOL=m +CONFIG_USB_SERIAL_TI=m +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_XIRCOM=m +CONFIG_USB_SERIAL_WWAN=m +CONFIG_USB_SERIAL_OPTION=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_SERIAL_OPTICON=m +CONFIG_USB_SERIAL_XSENS_MT=m +CONFIG_USB_SERIAL_WISHBONE=m +CONFIG_USB_SERIAL_SSU100=m +CONFIG_USB_SERIAL_QT2=m +CONFIG_USB_SERIAL_UPD78F0730=m +CONFIG_USB_SERIAL_DEBUG=m + +# +# USB Miscellaneous drivers +# +CONFIG_USB_EMI62=m +CONFIG_USB_EMI26=m +CONFIG_USB_ADUTUX=m +CONFIG_USB_SEVSEG=m +CONFIG_USB_LEGOTOWER=m +CONFIG_USB_LCD=m +CONFIG_USB_CYPRESS_CY7C63=m +CONFIG_USB_CYTHERM=m +CONFIG_USB_IDMOUSE=m +CONFIG_USB_FTDI_ELAN=m +CONFIG_USB_APPLEDISPLAY=m +CONFIG_USB_SISUSBVGA=m +CONFIG_USB_SISUSBVGA_CON=y +CONFIG_USB_LD=m +CONFIG_USB_TRANCEVIBRATOR=m +CONFIG_USB_IOWARRIOR=m +CONFIG_USB_TEST=m +# CONFIG_USB_EHSET_TEST_FIXTURE is not set +CONFIG_USB_ISIGHTFW=m +CONFIG_USB_YUREX=m +CONFIG_USB_EZUSB_FX2=m +# CONFIG_USB_HUB_USB251XB is not set +CONFIG_USB_HSIC_USB3503=m +CONFIG_USB_HSIC_USB4604=m +# CONFIG_USB_LINK_LAYER_TEST is not set +# CONFIG_USB_CHAOSKEY is not set +CONFIG_USB_ATM=m +CONFIG_USB_SPEEDTOUCH=m +CONFIG_USB_CXACRU=m +CONFIG_USB_UEAGLEATM=m +CONFIG_USB_XUSBATM=m + +# +# USB Physical Layer drivers +# +CONFIG_USB_PHY=y +CONFIG_NOP_USB_XCEIV=m +# CONFIG_USB_GPIO_VBUS is not set +CONFIG_TAHVO_USB=m +# CONFIG_TAHVO_USB_HOST_BY_DEFAULT is not set +CONFIG_USB_ISP1301=m +# end of USB Physical Layer drivers + +# CONFIG_USB_GADGET is not set +CONFIG_TYPEC=m +CONFIG_TYPEC_TCPM=m +CONFIG_TYPEC_TCPCI=m +CONFIG_TYPEC_RT1711H=m +CONFIG_TYPEC_FUSB302=m +CONFIG_TYPEC_WCOVE=m +CONFIG_TYPEC_UCSI=m +CONFIG_UCSI_CCG=m +CONFIG_UCSI_ACPI=m +# CONFIG_TYPEC_TPS6598X is not set + +# +# USB Type-C Multiplexer/DeMultiplexer Switch support +# +# CONFIG_TYPEC_MUX_PI3USB30532 is not set +# end of USB Type-C Multiplexer/DeMultiplexer Switch support + +# +# USB Type-C Alternate Mode drivers +# +CONFIG_TYPEC_DP_ALTMODE=m +CONFIG_TYPEC_NVIDIA_ALTMODE=m +# end of USB Type-C Alternate Mode drivers + +CONFIG_USB_ROLE_SWITCH=m +CONFIG_USB_ROLES_INTEL_XHCI=m +CONFIG_MMC=m +CONFIG_MMC_BLOCK=m +CONFIG_MMC_BLOCK_MINORS=8 +CONFIG_SDIO_UART=m +CONFIG_MMC_TEST=m + +# +# MMC/SD/SDIO Host Controller Drivers +# +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_SDHCI=m +CONFIG_MMC_SDHCI_IO_ACCESSORS=y +CONFIG_MMC_SDHCI_PCI=m +CONFIG_MMC_RICOH_MMC=y +CONFIG_MMC_SDHCI_ACPI=m +CONFIG_MMC_SDHCI_PLTFM=m +CONFIG_MMC_SDHCI_F_SDH30=m +CONFIG_MMC_WBSD=m +CONFIG_MMC_ALCOR=m +CONFIG_MMC_TIFM_SD=m +CONFIG_MMC_SPI=m +CONFIG_MMC_SDRICOH_CS=m +CONFIG_MMC_CB710=m +CONFIG_MMC_VIA_SDMMC=m +CONFIG_MMC_VUB300=m +CONFIG_MMC_USHC=m +CONFIG_MMC_USDHI6ROL0=m +CONFIG_MMC_REALTEK_PCI=m +CONFIG_MMC_REALTEK_USB=m +CONFIG_MMC_CQHCI=m +CONFIG_MMC_TOSHIBA_PCI=m +CONFIG_MMC_MTK=m +CONFIG_MMC_SDHCI_XENON=m +CONFIG_MEMSTICK=m +# CONFIG_MEMSTICK_DEBUG is not set + +# +# MemoryStick drivers +# +# CONFIG_MEMSTICK_UNSAFE_RESUME is not set +CONFIG_MSPRO_BLOCK=m +CONFIG_MS_BLOCK=m + +# +# MemoryStick Host Controller Drivers +# +CONFIG_MEMSTICK_TIFM_MS=m +CONFIG_MEMSTICK_JMICRON_38X=m +CONFIG_MEMSTICK_R592=m +CONFIG_MEMSTICK_REALTEK_PCI=m +CONFIG_MEMSTICK_REALTEK_USB=m +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +# CONFIG_LEDS_CLASS_FLASH is not set +# CONFIG_LEDS_BRIGHTNESS_HW_CHANGED is not set + +# +# LED drivers +# +CONFIG_LEDS_88PM860X=m +# CONFIG_LEDS_APU is not set +CONFIG_LEDS_LM3530=m +# CONFIG_LEDS_LM3532 is not set +CONFIG_LEDS_LM3642=m +# CONFIG_LEDS_PCA9532 is not set +CONFIG_LEDS_GPIO=m +# CONFIG_LEDS_LP3944 is not set +# CONFIG_LEDS_LP3952 is not set +CONFIG_LEDS_LP55XX_COMMON=m +CONFIG_LEDS_LP5521=m +CONFIG_LEDS_LP5523=m +CONFIG_LEDS_LP5562=m +CONFIG_LEDS_LP8501=m +CONFIG_LEDS_LP8788=m +CONFIG_LEDS_CLEVO_MAIL=m +# CONFIG_LEDS_PCA955X is not set +CONFIG_LEDS_PCA963X=m +CONFIG_LEDS_WM831X_STATUS=m +CONFIG_LEDS_WM8350=m +CONFIG_LEDS_DA903X=m +CONFIG_LEDS_DA9052=m +CONFIG_LEDS_DAC124S085=m +CONFIG_LEDS_PWM=m +CONFIG_LEDS_REGULATOR=m +# CONFIG_LEDS_BD2802 is not set +CONFIG_LEDS_INTEL_SS4200=m +CONFIG_LEDS_ADP5520=m +CONFIG_LEDS_MC13783=m +CONFIG_LEDS_TCA6507=m +CONFIG_LEDS_TLC591XX=m +CONFIG_LEDS_MAX8997=m +CONFIG_LEDS_LM355x=m +CONFIG_LEDS_MENF21BMC=m + +# +# LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM) +# +CONFIG_LEDS_BLINKM=m +CONFIG_LEDS_MLXCPLD=m +CONFIG_LEDS_MLXREG=m +CONFIG_LEDS_USER=m +# CONFIG_LEDS_NIC78BX is not set +# CONFIG_LEDS_TI_LMU_COMMON is not set + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=m +CONFIG_LEDS_TRIGGER_ONESHOT=m +CONFIG_LEDS_TRIGGER_DISK=y +# CONFIG_LEDS_TRIGGER_MTD is not set +CONFIG_LEDS_TRIGGER_HEARTBEAT=m +CONFIG_LEDS_TRIGGER_BACKLIGHT=m +CONFIG_LEDS_TRIGGER_CPU=y +# CONFIG_LEDS_TRIGGER_ACTIVITY is not set +CONFIG_LEDS_TRIGGER_GPIO=m +CONFIG_LEDS_TRIGGER_DEFAULT_ON=m + +# +# iptables trigger is under Netfilter config (LED target) +# +CONFIG_LEDS_TRIGGER_TRANSIENT=m +CONFIG_LEDS_TRIGGER_CAMERA=m +# CONFIG_LEDS_TRIGGER_PANIC is not set +CONFIG_LEDS_TRIGGER_NETDEV=m +CONFIG_LEDS_TRIGGER_PATTERN=m +CONFIG_LEDS_TRIGGER_AUDIO=m +CONFIG_ACCESSIBILITY=y +CONFIG_A11Y_BRAILLE_CONSOLE=y +CONFIG_INFINIBAND=m +CONFIG_INFINIBAND_USER_MAD=m +CONFIG_INFINIBAND_USER_ACCESS=m +# CONFIG_INFINIBAND_EXP_LEGACY_VERBS_NEW_UAPI is not set +CONFIG_INFINIBAND_USER_MEM=y +CONFIG_INFINIBAND_ON_DEMAND_PAGING=y +CONFIG_INFINIBAND_ADDR_TRANS=y +CONFIG_INFINIBAND_ADDR_TRANS_CONFIGFS=y +CONFIG_INFINIBAND_MTHCA=m +# CONFIG_INFINIBAND_MTHCA_DEBUG is not set +CONFIG_INFINIBAND_QIB=m +CONFIG_INFINIBAND_QIB_DCA=y +CONFIG_INFINIBAND_CXGB3=m +CONFIG_INFINIBAND_CXGB4=m +CONFIG_INFINIBAND_EFA=m +CONFIG_INFINIBAND_I40IW=m +CONFIG_MLX4_INFINIBAND=m +CONFIG_MLX5_INFINIBAND=m +CONFIG_INFINIBAND_OCRDMA=m +CONFIG_INFINIBAND_VMWARE_PVRDMA=m +CONFIG_INFINIBAND_USNIC=m +CONFIG_INFINIBAND_BNXT_RE=m +CONFIG_INFINIBAND_HFI1=m +# CONFIG_HFI1_DEBUG_SDMA_ORDER is not set +# CONFIG_SDMA_VERBOSITY is not set +CONFIG_INFINIBAND_QEDR=m +CONFIG_INFINIBAND_RDMAVT=m +CONFIG_RDMA_RXE=m +CONFIG_RDMA_SIW=m +CONFIG_INFINIBAND_IPOIB=m +# CONFIG_INFINIBAND_IPOIB_CM is not set +# CONFIG_INFINIBAND_IPOIB_DEBUG is not set +CONFIG_INFINIBAND_SRP=m +CONFIG_INFINIBAND_SRPT=m +CONFIG_INFINIBAND_ISER=m +CONFIG_INFINIBAND_ISERT=m +CONFIG_INFINIBAND_OPA_VNIC=m +CONFIG_EDAC_ATOMIC_SCRUB=y +CONFIG_EDAC_SUPPORT=y +CONFIG_EDAC=y +CONFIG_EDAC_LEGACY_SYSFS=y +# CONFIG_EDAC_DEBUG is not set +CONFIG_EDAC_DECODE_MCE=y +# CONFIG_EDAC_GHES is not set +CONFIG_EDAC_AMD64=m +# CONFIG_EDAC_AMD64_ERROR_INJECTION is not set +CONFIG_EDAC_E752X=m +CONFIG_EDAC_I82975X=m +CONFIG_EDAC_I3000=m +CONFIG_EDAC_I3200=m +CONFIG_EDAC_IE31200=m +CONFIG_EDAC_X38=m +CONFIG_EDAC_I5400=m +CONFIG_EDAC_I7CORE=m +CONFIG_EDAC_I5000=m +CONFIG_EDAC_I5100=m +CONFIG_EDAC_I7300=m +CONFIG_EDAC_SBRIDGE=m +CONFIG_EDAC_SKX=m +CONFIG_EDAC_I10NM=m +CONFIG_EDAC_PND2=m +CONFIG_RTC_LIB=y +CONFIG_RTC_MC146818_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +CONFIG_RTC_SYSTOHC=y +CONFIG_RTC_SYSTOHC_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set +CONFIG_RTC_NVMEM=y + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +# CONFIG_RTC_INTF_PROC is not set +CONFIG_RTC_INTF_DEV=y +CONFIG_RTC_INTF_DEV_UIE_EMUL=y +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +CONFIG_RTC_DRV_88PM860X=m +CONFIG_RTC_DRV_88PM80X=m +# CONFIG_RTC_DRV_ABB5ZES3 is not set +# CONFIG_RTC_DRV_ABEOZ9 is not set +# CONFIG_RTC_DRV_ABX80X is not set +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +CONFIG_RTC_DRV_LP8788=m +# CONFIG_RTC_DRV_MAX6900 is not set +CONFIG_RTC_DRV_MAX8907=m +CONFIG_RTC_DRV_MAX8925=m +CONFIG_RTC_DRV_MAX8998=m +CONFIG_RTC_DRV_MAX8997=m +# CONFIG_RTC_DRV_RS5C372 is not set +CONFIG_RTC_DRV_ISL1208=m +CONFIG_RTC_DRV_ISL12022=m +# CONFIG_RTC_DRV_X1205 is not set +CONFIG_RTC_DRV_PCF8523=m +CONFIG_RTC_DRV_PCF85063=m +# CONFIG_RTC_DRV_PCF85363 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +CONFIG_RTC_DRV_BQ32K=m +CONFIG_RTC_DRV_PALMAS=m +CONFIG_RTC_DRV_TPS6586X=m +CONFIG_RTC_DRV_TPS65910=m +CONFIG_RTC_DRV_TPS80031=m +CONFIG_RTC_DRV_RC5T583=m +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +CONFIG_RTC_DRV_RX8010=m +# CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_RX8025 is not set +# CONFIG_RTC_DRV_EM3027 is not set +# CONFIG_RTC_DRV_RV3028 is not set +CONFIG_RTC_DRV_RV8803=m +CONFIG_RTC_DRV_S5M=m +# CONFIG_RTC_DRV_SD3078 is not set + +# +# SPI RTC drivers +# +CONFIG_RTC_DRV_M41T93=m +CONFIG_RTC_DRV_M41T94=m +CONFIG_RTC_DRV_DS1302=m +CONFIG_RTC_DRV_DS1305=m +CONFIG_RTC_DRV_DS1343=m +CONFIG_RTC_DRV_DS1347=m +CONFIG_RTC_DRV_DS1390=m +CONFIG_RTC_DRV_MAX6916=m +CONFIG_RTC_DRV_R9701=m +CONFIG_RTC_DRV_RX4581=m +CONFIG_RTC_DRV_RX6110=m +CONFIG_RTC_DRV_RS5C348=m +CONFIG_RTC_DRV_MAX6902=m +CONFIG_RTC_DRV_PCF2123=m +CONFIG_RTC_DRV_MCP795=m +CONFIG_RTC_I2C_AND_SPI=y + +# +# SPI and I2C RTC drivers +# +# CONFIG_RTC_DRV_DS3232 is not set +CONFIG_RTC_DRV_PCF2127=m +# CONFIG_RTC_DRV_RV3029C2 is not set + +# +# Platform RTC drivers +# +CONFIG_RTC_DRV_CMOS=y +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1685_FAMILY is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_DS2404 is not set +CONFIG_RTC_DRV_DA9052=m +CONFIG_RTC_DRV_DA9055=m +CONFIG_RTC_DRV_DA9063=m +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_MSM6242 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_RP5C01 is not set +# CONFIG_RTC_DRV_V3020 is not set +CONFIG_RTC_DRV_WM831X=m +CONFIG_RTC_DRV_WM8350=m +CONFIG_RTC_DRV_CROS_EC=m + +# +# on-CPU RTC drivers +# +# CONFIG_RTC_DRV_FTRTC010 is not set +CONFIG_RTC_DRV_PCAP=m +CONFIG_RTC_DRV_MC13XXX=m + +# +# HID Sensor RTC drivers +# +CONFIG_RTC_DRV_HID_SENSOR_TIME=m +CONFIG_RTC_DRV_WILCO_EC=m +CONFIG_DMADEVICES=y +# CONFIG_DMADEVICES_DEBUG is not set + +# +# DMA Devices +# +CONFIG_DMA_ENGINE=y +CONFIG_DMA_VIRTUAL_CHANNELS=m +CONFIG_DMA_ACPI=y +CONFIG_ALTERA_MSGDMA=m +CONFIG_INTEL_IDMA64=m +CONFIG_INTEL_IOATDMA=m +CONFIG_INTEL_MIC_X100_DMA=m +CONFIG_QCOM_HIDMA_MGMT=m +CONFIG_QCOM_HIDMA=m +CONFIG_DW_DMAC_CORE=m +CONFIG_DW_DMAC=m +CONFIG_DW_DMAC_PCI=m +CONFIG_DW_EDMA=m +CONFIG_DW_EDMA_PCIE=m +CONFIG_HSU_DMA=m + +# +# DMA Clients +# +# CONFIG_ASYNC_TX_DMA is not set +CONFIG_DMATEST=m +CONFIG_DMA_ENGINE_RAID=y + +# +# DMABUF options +# +CONFIG_SYNC_FILE=y +# CONFIG_SW_SYNC is not set +CONFIG_UDMABUF=y +# CONFIG_DMABUF_SELFTESTS is not set +# end of DMABUF options + +CONFIG_DCA=m +CONFIG_AUXDISPLAY=y +# CONFIG_HD44780 is not set +CONFIG_KS0108=m +CONFIG_KS0108_PORT=0x378 +CONFIG_KS0108_DELAY=2 +CONFIG_CFAG12864B=m +CONFIG_CFAG12864B_RATE=20 +# CONFIG_IMG_ASCII_LCD is not set +CONFIG_PARPORT_PANEL=m +CONFIG_PANEL_PARPORT=0 +CONFIG_PANEL_PROFILE=5 +# CONFIG_PANEL_CHANGE_MESSAGE is not set +# CONFIG_CHARLCD_BL_OFF is not set +# CONFIG_CHARLCD_BL_ON is not set +CONFIG_CHARLCD_BL_FLASH=y +CONFIG_PANEL=m +CONFIG_CHARLCD=m +CONFIG_UIO=m +CONFIG_UIO_CIF=m +# CONFIG_UIO_PDRV_GENIRQ is not set +CONFIG_UIO_DMEM_GENIRQ=m +CONFIG_UIO_AEC=m +CONFIG_UIO_SERCOS3=m +CONFIG_UIO_PCI_GENERIC=m +CONFIG_UIO_NETX=m +CONFIG_UIO_PRUSS=m +CONFIG_UIO_MF624=m +CONFIG_UIO_HV_GENERIC=m +CONFIG_VFIO_IOMMU_TYPE1=m +CONFIG_VFIO_VIRQFD=m +CONFIG_VFIO=m +# CONFIG_VFIO_NOIOMMU is not set +CONFIG_VFIO_PCI=m +CONFIG_VFIO_PCI_VGA=y +CONFIG_VFIO_PCI_MMAP=y +CONFIG_VFIO_PCI_INTX=y +CONFIG_VFIO_PCI_IGD=y +CONFIG_VFIO_MDEV=m +CONFIG_VFIO_MDEV_DEVICE=m +CONFIG_IRQ_BYPASS_MANAGER=m +CONFIG_VIRT_DRIVERS=y +CONFIG_VBOXGUEST=m +CONFIG_VIRTIO=m +CONFIG_VIRTIO_MENU=y +CONFIG_VIRTIO_PCI=m +CONFIG_VIRTIO_PCI_LEGACY=y +CONFIG_VIRTIO_PMEM=m +CONFIG_VIRTIO_BALLOON=m +CONFIG_VIRTIO_INPUT=m +CONFIG_VIRTIO_MMIO=m +# CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES is not set + +# +# Microsoft Hyper-V guest support +# +CONFIG_HYPERV=m +CONFIG_HYPERV_TIMER=y +CONFIG_HYPERV_UTILS=m +CONFIG_HYPERV_BALLOON=m +# end of Microsoft Hyper-V guest support + +# +# Xen driver support +# +CONFIG_XEN_BALLOON=y +# CONFIG_XEN_BALLOON_MEMORY_HOTPLUG is not set +CONFIG_XEN_SCRUB_PAGES_DEFAULT=y +CONFIG_XEN_DEV_EVTCHN=m +CONFIG_XEN_BACKEND=y +CONFIG_XENFS=m +CONFIG_XEN_COMPAT_XENFS=y +CONFIG_XEN_SYS_HYPERVISOR=y +CONFIG_XEN_XENBUS_FRONTEND=y +CONFIG_XEN_GNTDEV=m +CONFIG_XEN_GRANT_DEV_ALLOC=m +# CONFIG_XEN_GRANT_DMA_ALLOC is not set +CONFIG_SWIOTLB_XEN=y +CONFIG_XEN_PCIDEV_BACKEND=m +# CONFIG_XEN_PVCALLS_FRONTEND is not set +# CONFIG_XEN_PVCALLS_BACKEND is not set +CONFIG_XEN_SCSI_BACKEND=m +CONFIG_XEN_PRIVCMD=m +CONFIG_XEN_ACPI_PROCESSOR=m +# CONFIG_XEN_MCE_LOG is not set +CONFIG_XEN_HAVE_PVMMU=y +CONFIG_XEN_EFI=y +CONFIG_XEN_AUTO_XLATE=y +CONFIG_XEN_ACPI=y +CONFIG_XEN_SYMS=y +CONFIG_XEN_HAVE_VPMU=y +CONFIG_XEN_FRONT_PGDIR_SHBUF=m +# end of Xen driver support + +# CONFIG_GREYBUS is not set +CONFIG_STAGING=y +CONFIG_PRISM2_USB=m +CONFIG_COMEDI=m +# CONFIG_COMEDI_DEBUG is not set +CONFIG_COMEDI_DEFAULT_BUF_SIZE_KB=2048 +CONFIG_COMEDI_DEFAULT_BUF_MAXSIZE_KB=20480 +CONFIG_COMEDI_MISC_DRIVERS=y +CONFIG_COMEDI_BOND=m +CONFIG_COMEDI_TEST=m +CONFIG_COMEDI_PARPORT=m +CONFIG_COMEDI_ISA_DRIVERS=y +CONFIG_COMEDI_PCL711=m +CONFIG_COMEDI_PCL724=m +CONFIG_COMEDI_PCL726=m +CONFIG_COMEDI_PCL730=m +CONFIG_COMEDI_PCL812=m +CONFIG_COMEDI_PCL816=m +CONFIG_COMEDI_PCL818=m +CONFIG_COMEDI_PCM3724=m +CONFIG_COMEDI_AMPLC_DIO200_ISA=m +CONFIG_COMEDI_AMPLC_PC236_ISA=m +CONFIG_COMEDI_AMPLC_PC263_ISA=m +CONFIG_COMEDI_RTI800=m +CONFIG_COMEDI_RTI802=m +# CONFIG_COMEDI_DAC02 is not set +CONFIG_COMEDI_DAS16M1=m +CONFIG_COMEDI_DAS08_ISA=m +CONFIG_COMEDI_DAS16=m +CONFIG_COMEDI_DAS800=m +CONFIG_COMEDI_DAS1800=m +CONFIG_COMEDI_DAS6402=m +CONFIG_COMEDI_DT2801=m +CONFIG_COMEDI_DT2811=m +CONFIG_COMEDI_DT2814=m +CONFIG_COMEDI_DT2815=m +CONFIG_COMEDI_DT2817=m +CONFIG_COMEDI_DT282X=m +CONFIG_COMEDI_DMM32AT=m +CONFIG_COMEDI_FL512=m +CONFIG_COMEDI_AIO_AIO12_8=m +CONFIG_COMEDI_AIO_IIRO_16=m +CONFIG_COMEDI_II_PCI20KC=m +CONFIG_COMEDI_C6XDIGIO=m +CONFIG_COMEDI_MPC624=m +CONFIG_COMEDI_ADQ12B=m +CONFIG_COMEDI_NI_AT_A2150=m +CONFIG_COMEDI_NI_AT_AO=m +CONFIG_COMEDI_NI_ATMIO=m +CONFIG_COMEDI_NI_ATMIO16D=m +CONFIG_COMEDI_NI_LABPC_ISA=m +CONFIG_COMEDI_PCMAD=m +CONFIG_COMEDI_PCMDA12=m +CONFIG_COMEDI_PCMMIO=m +CONFIG_COMEDI_PCMUIO=m +CONFIG_COMEDI_MULTIQ3=m +CONFIG_COMEDI_S526=m +CONFIG_COMEDI_PCI_DRIVERS=m +CONFIG_COMEDI_8255_PCI=m +CONFIG_COMEDI_ADDI_WATCHDOG=m +CONFIG_COMEDI_ADDI_APCI_1032=m +CONFIG_COMEDI_ADDI_APCI_1500=m +CONFIG_COMEDI_ADDI_APCI_1516=m +CONFIG_COMEDI_ADDI_APCI_1564=m +CONFIG_COMEDI_ADDI_APCI_16XX=m +CONFIG_COMEDI_ADDI_APCI_2032=m +CONFIG_COMEDI_ADDI_APCI_2200=m +CONFIG_COMEDI_ADDI_APCI_3120=m +CONFIG_COMEDI_ADDI_APCI_3501=m +CONFIG_COMEDI_ADDI_APCI_3XXX=m +CONFIG_COMEDI_ADL_PCI6208=m +CONFIG_COMEDI_ADL_PCI7X3X=m +CONFIG_COMEDI_ADL_PCI8164=m +CONFIG_COMEDI_ADL_PCI9111=m +CONFIG_COMEDI_ADL_PCI9118=m +CONFIG_COMEDI_ADV_PCI1710=m +CONFIG_COMEDI_ADV_PCI1720=m +CONFIG_COMEDI_ADV_PCI1723=m +CONFIG_COMEDI_ADV_PCI1724=m +CONFIG_COMEDI_ADV_PCI1760=m +CONFIG_COMEDI_ADV_PCI_DIO=m +CONFIG_COMEDI_AMPLC_DIO200_PCI=m +CONFIG_COMEDI_AMPLC_PC236_PCI=m +CONFIG_COMEDI_AMPLC_PC263_PCI=m +CONFIG_COMEDI_AMPLC_PCI224=m +CONFIG_COMEDI_AMPLC_PCI230=m +CONFIG_COMEDI_CONTEC_PCI_DIO=m +CONFIG_COMEDI_DAS08_PCI=m +CONFIG_COMEDI_DT3000=m +CONFIG_COMEDI_DYNA_PCI10XX=m +CONFIG_COMEDI_GSC_HPDI=m +CONFIG_COMEDI_MF6X4=m +CONFIG_COMEDI_ICP_MULTI=m +CONFIG_COMEDI_DAQBOARD2000=m +CONFIG_COMEDI_JR3_PCI=m +CONFIG_COMEDI_KE_COUNTER=m +CONFIG_COMEDI_CB_PCIDAS64=m +CONFIG_COMEDI_CB_PCIDAS=m +CONFIG_COMEDI_CB_PCIDDA=m +CONFIG_COMEDI_CB_PCIMDAS=m +CONFIG_COMEDI_CB_PCIMDDA=m +CONFIG_COMEDI_ME4000=m +CONFIG_COMEDI_ME_DAQ=m +CONFIG_COMEDI_NI_6527=m +CONFIG_COMEDI_NI_65XX=m +CONFIG_COMEDI_NI_660X=m +CONFIG_COMEDI_NI_670X=m +CONFIG_COMEDI_NI_LABPC_PCI=m +CONFIG_COMEDI_NI_PCIDIO=m +CONFIG_COMEDI_NI_PCIMIO=m +CONFIG_COMEDI_RTD520=m +CONFIG_COMEDI_S626=m +CONFIG_COMEDI_MITE=m +CONFIG_COMEDI_NI_TIOCMD=m +CONFIG_COMEDI_PCMCIA_DRIVERS=m +CONFIG_COMEDI_CB_DAS16_CS=m +CONFIG_COMEDI_DAS08_CS=m +CONFIG_COMEDI_NI_DAQ_700_CS=m +CONFIG_COMEDI_NI_DAQ_DIO24_CS=m +CONFIG_COMEDI_NI_LABPC_CS=m +CONFIG_COMEDI_NI_MIO_CS=m +CONFIG_COMEDI_QUATECH_DAQP_CS=m +CONFIG_COMEDI_USB_DRIVERS=m +CONFIG_COMEDI_DT9812=m +CONFIG_COMEDI_NI_USB6501=m +CONFIG_COMEDI_USBDUX=m +CONFIG_COMEDI_USBDUXFAST=m +CONFIG_COMEDI_USBDUXSIGMA=m +CONFIG_COMEDI_VMK80XX=m +CONFIG_COMEDI_8254=m +CONFIG_COMEDI_8255=m +CONFIG_COMEDI_8255_SA=m +CONFIG_COMEDI_KCOMEDILIB=m +CONFIG_COMEDI_AMPLC_DIO200=m +CONFIG_COMEDI_AMPLC_PC236=m +CONFIG_COMEDI_DAS08=m +CONFIG_COMEDI_ISADMA=m +CONFIG_COMEDI_NI_LABPC=m +CONFIG_COMEDI_NI_LABPC_ISADMA=m +CONFIG_COMEDI_NI_TIO=m +CONFIG_COMEDI_NI_ROUTING=m +CONFIG_RTL8192U=m +CONFIG_RTLLIB=m +CONFIG_RTLLIB_CRYPTO_CCMP=m +CONFIG_RTLLIB_CRYPTO_TKIP=m +CONFIG_RTLLIB_CRYPTO_WEP=m +CONFIG_RTL8192E=m +CONFIG_RTL8723BS=m +CONFIG_R8712U=m +CONFIG_R8188EU=m +CONFIG_88EU_AP_MODE=y +CONFIG_RTS5208=m +CONFIG_VT6655=m +CONFIG_VT6656=m + +# +# IIO staging drivers +# + +# +# Accelerometers +# +CONFIG_ADIS16203=m +CONFIG_ADIS16240=m +# end of Accelerometers + +# +# Analog to digital converters +# +CONFIG_AD7816=m +CONFIG_AD7192=m +CONFIG_AD7280=m +# end of Analog to digital converters + +# +# Analog digital bi-direction converters +# +CONFIG_ADT7316=m +CONFIG_ADT7316_SPI=m +CONFIG_ADT7316_I2C=m +# end of Analog digital bi-direction converters + +# +# Capacitance to digital converters +# +CONFIG_AD7150=m +CONFIG_AD7746=m +# end of Capacitance to digital converters + +# +# Direct Digital Synthesis +# +CONFIG_AD9832=m +CONFIG_AD9834=m +# end of Direct Digital Synthesis + +# +# Network Analyzer, Impedance Converters +# +CONFIG_AD5933=m +# end of Network Analyzer, Impedance Converters + +# +# Active energy metering IC +# +CONFIG_ADE7854=m +CONFIG_ADE7854_I2C=m +CONFIG_ADE7854_SPI=m +# end of Active energy metering IC + +# +# Resolver to digital converters +# +CONFIG_AD2S1210=m +# end of Resolver to digital converters +# end of IIO staging drivers + +# CONFIG_FB_SM750 is not set + +# +# Speakup console speech +# +CONFIG_SPEAKUP=m +CONFIG_SPEAKUP_SYNTH_ACNTSA=m +CONFIG_SPEAKUP_SYNTH_APOLLO=m +CONFIG_SPEAKUP_SYNTH_AUDPTR=m +CONFIG_SPEAKUP_SYNTH_BNS=m +CONFIG_SPEAKUP_SYNTH_DECTLK=m +CONFIG_SPEAKUP_SYNTH_DECEXT=m +CONFIG_SPEAKUP_SYNTH_LTLK=m +CONFIG_SPEAKUP_SYNTH_SOFT=m +CONFIG_SPEAKUP_SYNTH_SPKOUT=m +CONFIG_SPEAKUP_SYNTH_TXPRT=m +CONFIG_SPEAKUP_SYNTH_DUMMY=m +# end of Speakup console speech + +CONFIG_STAGING_MEDIA=y + +# +# soc_camera sensor drivers +# + +# +# Android +# +# end of Android + +CONFIG_LTE_GDM724X=m +CONFIG_FIREWIRE_SERIAL=m +CONFIG_FWTTY_MAX_TOTAL_PORTS=64 +CONFIG_FWTTY_MAX_CARD_PORTS=32 +# CONFIG_GS_FPGABOOT is not set +CONFIG_UNISYSSPAR=y +CONFIG_UNISYS_VISORNIC=m +CONFIG_UNISYS_VISORINPUT=m +CONFIG_UNISYS_VISORHBA=m +CONFIG_WILC1000=m +CONFIG_WILC1000_SDIO=m +# CONFIG_WILC1000_SPI is not set +# CONFIG_WILC1000_HW_OOB_INTR is not set +CONFIG_MOST=m +CONFIG_MOST_CDEV=m +CONFIG_MOST_NET=m +CONFIG_MOST_SOUND=m +CONFIG_MOST_VIDEO=m +CONFIG_MOST_I2C=m +CONFIG_MOST_USB=m +CONFIG_KS7010=m +# CONFIG_PI433 is not set + +# +# Gasket devices +# +# CONFIG_STAGING_GASKET_FRAMEWORK is not set +# end of Gasket devices + +CONFIG_FIELDBUS_DEV=m +# CONFIG_KPC2000 is not set + +# +# ISDN CAPI drivers +# +CONFIG_CAPI_AVM=y +CONFIG_ISDN_DRV_AVMB1_B1PCI=m +# CONFIG_ISDN_DRV_AVMB1_B1PCIV4 is not set +CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m +CONFIG_ISDN_DRV_AVMB1_AVM_CS=m +CONFIG_ISDN_DRV_AVMB1_T1PCI=m +CONFIG_ISDN_DRV_AVMB1_C4=m +CONFIG_ISDN_DRV_GIGASET=m +CONFIG_GIGASET_CAPI=y +CONFIG_GIGASET_BASE=m +CONFIG_GIGASET_M105=m +CONFIG_GIGASET_M101=m +# CONFIG_GIGASET_DEBUG is not set +CONFIG_HYSDN=m +CONFIG_HYSDN_CAPI=y +# end of ISDN CAPI drivers + +CONFIG_USB_WUSB=m +CONFIG_USB_WUSB_CBAF=m +# CONFIG_USB_WUSB_CBAF_DEBUG is not set +CONFIG_USB_WHCI_HCD=m +CONFIG_USB_HWA_HCD=m +CONFIG_UWB=m +CONFIG_UWB_HWA=m +CONFIG_UWB_WHCI=m +CONFIG_UWB_I1480U=m +CONFIG_EXFAT_FS=m +CONFIG_EXFAT_DONT_MOUNT_VFAT=y +CONFIG_EXFAT_DISCARD=y +# CONFIG_EXFAT_DELAYED_SYNC is not set +# CONFIG_EXFAT_KERNEL_DEBUG is not set +# CONFIG_EXFAT_DEBUG_MSG is not set +CONFIG_EXFAT_DEFAULT_CODEPAGE=437 +CONFIG_EXFAT_DEFAULT_IOCHARSET="utf8" +CONFIG_QLGE=m +CONFIG_VBOXSF_FS=m +CONFIG_X86_PLATFORM_DEVICES=y +CONFIG_ACER_WMI=m +CONFIG_ACER_WIRELESS=m +CONFIG_ACERHDF=m +CONFIG_ALIENWARE_WMI=m +CONFIG_ASUS_LAPTOP=m +CONFIG_DCDBAS=m +CONFIG_DELL_SMBIOS=m +CONFIG_DELL_SMBIOS_WMI=y +CONFIG_DELL_SMBIOS_SMM=y +CONFIG_DELL_LAPTOP=m +CONFIG_DELL_WMI=m +CONFIG_DELL_WMI_DESCRIPTOR=m +CONFIG_DELL_WMI_AIO=m +CONFIG_DELL_WMI_LED=m +CONFIG_DELL_SMO8800=m +CONFIG_DELL_RBTN=m +# CONFIG_DELL_RBU is not set +CONFIG_FUJITSU_LAPTOP=m +CONFIG_FUJITSU_TABLET=m +CONFIG_AMILO_RFKILL=m +CONFIG_GPD_POCKET_FAN=m +CONFIG_HP_ACCEL=m +CONFIG_HP_WIRELESS=m +CONFIG_HP_WMI=m +CONFIG_LG_LAPTOP=m +CONFIG_MSI_LAPTOP=m +CONFIG_PANASONIC_LAPTOP=m +CONFIG_COMPAL_LAPTOP=m +CONFIG_SONY_LAPTOP=m +CONFIG_SONYPI_COMPAT=y +CONFIG_IDEAPAD_LAPTOP=m +CONFIG_SURFACE3_WMI=m +CONFIG_THINKPAD_ACPI=m +CONFIG_THINKPAD_ACPI_ALSA_SUPPORT=y +# CONFIG_THINKPAD_ACPI_DEBUGFACILITIES is not set +# CONFIG_THINKPAD_ACPI_DEBUG is not set +# CONFIG_THINKPAD_ACPI_UNSAFE_LEDS is not set +CONFIG_THINKPAD_ACPI_VIDEO=y +CONFIG_THINKPAD_ACPI_HOTKEY_POLL=y +CONFIG_SENSORS_HDAPS=m +CONFIG_INTEL_MENLOW=m +CONFIG_EEEPC_LAPTOP=m +CONFIG_ASUS_WMI=m +CONFIG_ASUS_NB_WMI=m +CONFIG_EEEPC_WMI=m +CONFIG_ASUS_WIRELESS=m +CONFIG_ACPI_WMI=m +CONFIG_WMI_BMOF=m +CONFIG_INTEL_WMI_THUNDERBOLT=m +CONFIG_XIAOMI_WMI=m +CONFIG_MSI_WMI=m +CONFIG_PEAQ_WMI=m +CONFIG_TOPSTAR_LAPTOP=m +CONFIG_ACPI_TOSHIBA=m +CONFIG_TOSHIBA_BT_RFKILL=m +CONFIG_TOSHIBA_HAPS=m +CONFIG_TOSHIBA_WMI=m +CONFIG_ACPI_CMPC=m +CONFIG_INTEL_INT0002_VGPIO=m +CONFIG_INTEL_HID_EVENT=m +CONFIG_INTEL_VBTN=m +CONFIG_INTEL_IPS=m +CONFIG_INTEL_PMC_CORE=y +CONFIG_IBM_RTL=m +CONFIG_SAMSUNG_LAPTOP=m +CONFIG_MXM_WMI=m +CONFIG_INTEL_OAKTRAIL=m +CONFIG_SAMSUNG_Q10=m +CONFIG_APPLE_GMUX=m +CONFIG_INTEL_RST=m +CONFIG_INTEL_SMARTCONNECT=m +CONFIG_INTEL_PMC_IPC=m +CONFIG_INTEL_BXTWC_PMIC_TMU=m +CONFIG_SURFACE_PRO3_BUTTON=m +CONFIG_SURFACE_3_BUTTON=m +CONFIG_INTEL_PUNIT_IPC=m +CONFIG_INTEL_TELEMETRY=m +CONFIG_MLX_PLATFORM=m +CONFIG_INTEL_TURBO_MAX_3=y +CONFIG_TOUCHSCREEN_DMI=y +CONFIG_INTEL_CHTDC_TI_PWRBTN=m +CONFIG_I2C_MULTI_INSTANTIATE=m +CONFIG_INTEL_ATOMISP2_PM=m +CONFIG_HUAWEI_WMI=m +# CONFIG_PCENGINES_APU2 is not set + +# +# Intel Speed Select Technology interface support +# +CONFIG_INTEL_SPEED_SELECT_INTERFACE=m +# end of Intel Speed Select Technology interface support + +CONFIG_PMC_ATOM=y +CONFIG_MFD_CROS_EC=m +CONFIG_CHROME_PLATFORMS=y +CONFIG_CHROMEOS_LAPTOP=m +CONFIG_CHROMEOS_PSTORE=m +CONFIG_CHROMEOS_TBMC=m +CONFIG_CROS_EC=m +CONFIG_CROS_EC_I2C=m +CONFIG_CROS_EC_ISHTP=m +CONFIG_CROS_EC_SPI=m +CONFIG_CROS_EC_LPC=m +CONFIG_CROS_EC_PROTO=y +CONFIG_CROS_KBD_LED_BACKLIGHT=m +CONFIG_CROS_EC_CHARDEV=m +CONFIG_CROS_EC_LIGHTBAR=m +CONFIG_CROS_EC_DEBUGFS=m +CONFIG_CROS_EC_SYSFS=m +CONFIG_CROS_USBPD_LOGGER=m +CONFIG_WILCO_EC=m +CONFIG_WILCO_EC_DEBUGFS=m +CONFIG_WILCO_EC_EVENTS=m +CONFIG_WILCO_EC_TELEMETRY=m +CONFIG_MELLANOX_PLATFORM=y +CONFIG_MLXREG_HOTPLUG=m +CONFIG_MLXREG_IO=m +CONFIG_CLKDEV_LOOKUP=y +CONFIG_HAVE_CLK_PREPARE=y +CONFIG_COMMON_CLK=y + +# +# Common Clock Framework +# +CONFIG_COMMON_CLK_WM831X=m +# CONFIG_COMMON_CLK_MAX9485 is not set +# CONFIG_COMMON_CLK_SI5341 is not set +CONFIG_COMMON_CLK_SI5351=m +# CONFIG_COMMON_CLK_SI544 is not set +# CONFIG_COMMON_CLK_CDCE706 is not set +CONFIG_COMMON_CLK_CS2000_CP=m +CONFIG_COMMON_CLK_S2MPS11=m +CONFIG_CLK_TWL6040=m +CONFIG_COMMON_CLK_PALMAS=m +CONFIG_COMMON_CLK_PWM=m +# end of Common Clock Framework + +# CONFIG_HWSPINLOCK is not set + +# +# Clock Source drivers +# +CONFIG_CLKEVT_I8253=y +CONFIG_I8253_LOCK=y +CONFIG_CLKBLD_I8253=y +# end of Clock Source drivers + +CONFIG_MAILBOX=y +CONFIG_PCC=y +CONFIG_ALTERA_MBOX=m +CONFIG_IOMMU_IOVA=y +CONFIG_IOMMU_API=y +CONFIG_IOMMU_SUPPORT=y + +# +# Generic IOMMU Pagetable Support +# +# end of Generic IOMMU Pagetable Support + +# CONFIG_IOMMU_DEBUGFS is not set +# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set +CONFIG_AMD_IOMMU=y +CONFIG_AMD_IOMMU_V2=m +CONFIG_DMAR_TABLE=y +CONFIG_INTEL_IOMMU=y +# CONFIG_INTEL_IOMMU_SVM is not set +# CONFIG_INTEL_IOMMU_DEFAULT_ON is not set +CONFIG_INTEL_IOMMU_FLOPPY_WA=y +CONFIG_IRQ_REMAP=y +CONFIG_HYPERV_IOMMU=y + +# +# Remoteproc drivers +# +# CONFIG_REMOTEPROC is not set +# end of Remoteproc drivers + +# +# Rpmsg drivers +# +CONFIG_RPMSG=m +# CONFIG_RPMSG_CHAR is not set +CONFIG_RPMSG_QCOM_GLINK_NATIVE=m +CONFIG_RPMSG_QCOM_GLINK_RPM=m +CONFIG_RPMSG_VIRTIO=m +# end of Rpmsg drivers + +CONFIG_SOUNDWIRE=y + +# +# SoundWire Devices +# +CONFIG_SOUNDWIRE_CADENCE=m +CONFIG_SOUNDWIRE_INTEL=m + +# +# SOC (System On Chip) specific Drivers +# + +# +# Amlogic SoC drivers +# +# end of Amlogic SoC drivers + +# +# Aspeed SoC drivers +# +# end of Aspeed SoC drivers + +# +# Broadcom SoC drivers +# +# end of Broadcom SoC drivers + +# +# NXP/Freescale QorIQ SoC drivers +# +# end of NXP/Freescale QorIQ SoC drivers + +# +# i.MX SoC drivers +# +# end of i.MX SoC drivers + +# +# Qualcomm SoC drivers +# +# end of Qualcomm SoC drivers + +# CONFIG_SOC_TI is not set + +# +# Xilinx SoC drivers +# +CONFIG_XILINX_VCU=m +# end of Xilinx SoC drivers +# end of SOC (System On Chip) specific Drivers + +CONFIG_PM_DEVFREQ=y + +# +# DEVFREQ Governors +# +CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=m +# CONFIG_DEVFREQ_GOV_PERFORMANCE is not set +# CONFIG_DEVFREQ_GOV_POWERSAVE is not set +# CONFIG_DEVFREQ_GOV_USERSPACE is not set +# CONFIG_DEVFREQ_GOV_PASSIVE is not set + +# +# DEVFREQ Drivers +# +# CONFIG_PM_DEVFREQ_EVENT is not set +CONFIG_EXTCON=y + +# +# Extcon Device Drivers +# +CONFIG_EXTCON_ADC_JACK=m +# CONFIG_EXTCON_ARIZONA is not set +CONFIG_EXTCON_AXP288=m +# CONFIG_EXTCON_FSA9480 is not set +CONFIG_EXTCON_GPIO=m +CONFIG_EXTCON_INTEL_INT3496=m +CONFIG_EXTCON_INTEL_CHT_WC=m +CONFIG_EXTCON_MAX14577=m +CONFIG_EXTCON_MAX3355=m +CONFIG_EXTCON_MAX77693=m +CONFIG_EXTCON_MAX8997=m +CONFIG_EXTCON_PALMAS=m +# CONFIG_EXTCON_PTN5150 is not set +CONFIG_EXTCON_RT8973A=m +CONFIG_EXTCON_SM5502=m +CONFIG_EXTCON_USB_GPIO=m +CONFIG_EXTCON_USBC_CROS_EC=m +CONFIG_MEMORY=y +CONFIG_IIO=m +CONFIG_IIO_BUFFER=y +CONFIG_IIO_BUFFER_CB=m +CONFIG_IIO_BUFFER_HW_CONSUMER=m +CONFIG_IIO_KFIFO_BUF=m +CONFIG_IIO_TRIGGERED_BUFFER=m +CONFIG_IIO_CONFIGFS=m +CONFIG_IIO_TRIGGER=y +CONFIG_IIO_CONSUMERS_PER_TRIGGER=2 +CONFIG_IIO_SW_DEVICE=m +CONFIG_IIO_SW_TRIGGER=m +CONFIG_IIO_TRIGGERED_EVENT=m + +# +# Accelerometers +# +CONFIG_ADIS16201=m +CONFIG_ADIS16209=m +CONFIG_ADXL345=m +CONFIG_ADXL345_I2C=m +CONFIG_ADXL345_SPI=m +# CONFIG_ADXL372_SPI is not set +# CONFIG_ADXL372_I2C is not set +CONFIG_BMA180=m +CONFIG_BMA220=m +CONFIG_BMC150_ACCEL=m +CONFIG_BMC150_ACCEL_I2C=m +CONFIG_BMC150_ACCEL_SPI=m +# CONFIG_DA280 is not set +# CONFIG_DA311 is not set +# CONFIG_DMARD09 is not set +# CONFIG_DMARD10 is not set +CONFIG_HID_SENSOR_ACCEL_3D=m +# CONFIG_IIO_CROS_EC_ACCEL_LEGACY is not set +CONFIG_IIO_ST_ACCEL_3AXIS=m +CONFIG_IIO_ST_ACCEL_I2C_3AXIS=m +CONFIG_IIO_ST_ACCEL_SPI_3AXIS=m +CONFIG_KXSD9=m +CONFIG_KXSD9_SPI=m +CONFIG_KXSD9_I2C=m +CONFIG_KXCJK1013=m +# CONFIG_MC3230 is not set +CONFIG_MMA7455=m +CONFIG_MMA7455_I2C=m +CONFIG_MMA7455_SPI=m +CONFIG_MMA7660=m +CONFIG_MMA8452=m +# CONFIG_MMA9551 is not set +# CONFIG_MMA9553 is not set +CONFIG_MXC4005=m +CONFIG_MXC6255=m +CONFIG_SCA3000=m +CONFIG_STK8312=m +CONFIG_STK8BA50=m +# end of Accelerometers + +# +# Analog to digital converters +# +CONFIG_AD_SIGMA_DELTA=m +CONFIG_AD7124=m +CONFIG_AD7266=m +CONFIG_AD7291=m +CONFIG_AD7298=m +CONFIG_AD7476=m +CONFIG_AD7606=m +CONFIG_AD7606_IFACE_PARALLEL=m +CONFIG_AD7606_IFACE_SPI=m +CONFIG_AD7766=m +# CONFIG_AD7768_1 is not set +CONFIG_AD7780=m +CONFIG_AD7791=m +CONFIG_AD7793=m +CONFIG_AD7887=m +CONFIG_AD7923=m +CONFIG_AD7949=m +CONFIG_AD799X=m +# CONFIG_AXP20X_ADC is not set +CONFIG_AXP288_ADC=m +# CONFIG_CC10001_ADC is not set +CONFIG_DLN2_ADC=m +CONFIG_HI8435=m +# CONFIG_HX711 is not set +CONFIG_INA2XX_ADC=m +CONFIG_LP8788_ADC=m +CONFIG_LTC2471=m +# CONFIG_LTC2485 is not set +# CONFIG_LTC2497 is not set +CONFIG_MAX1027=m +# CONFIG_MAX11100 is not set +# CONFIG_MAX1118 is not set +CONFIG_MAX1363=m +# CONFIG_MAX9611 is not set +CONFIG_MCP320X=m +CONFIG_MCP3422=m +# CONFIG_MCP3911 is not set +CONFIG_NAU7802=m +CONFIG_PALMAS_GPADC=m +CONFIG_QCOM_SPMI_IADC=m +# CONFIG_QCOM_SPMI_VADC is not set +# CONFIG_QCOM_SPMI_ADC5 is not set +CONFIG_TI_ADC081C=m +CONFIG_TI_ADC0832=m +CONFIG_TI_ADC084S021=m +# CONFIG_TI_ADC12138 is not set +CONFIG_TI_ADC108S102=m +CONFIG_TI_ADC128S052=m +# CONFIG_TI_ADC161S626 is not set +CONFIG_TI_ADS1015=m +# CONFIG_TI_ADS7950 is not set +CONFIG_TI_AM335X_ADC=m +# CONFIG_TI_TLC4541 is not set +CONFIG_TWL4030_MADC=m +CONFIG_TWL6030_GPADC=m +CONFIG_VIPERBOARD_ADC=m +CONFIG_XILINX_XADC=m +# end of Analog to digital converters + +# +# Analog Front Ends +# +# end of Analog Front Ends + +# +# Amplifiers +# +CONFIG_AD8366=m +# end of Amplifiers + +# +# Chemical Sensors +# +CONFIG_ATLAS_PH_SENSOR=m +# CONFIG_BME680 is not set +CONFIG_CCS811=m +CONFIG_IAQCORE=m +# CONFIG_PMS7003 is not set +# CONFIG_SENSIRION_SGP30 is not set +# CONFIG_SPS30 is not set +CONFIG_VZ89X=m +# end of Chemical Sensors + +CONFIG_IIO_CROS_EC_SENSORS_CORE=m +CONFIG_IIO_CROS_EC_SENSORS=m +CONFIG_IIO_CROS_EC_SENSORS_LID_ANGLE=m + +# +# Hid Sensor IIO Common +# +CONFIG_HID_SENSOR_IIO_COMMON=m +CONFIG_HID_SENSOR_IIO_TRIGGER=m +# end of Hid Sensor IIO Common + +CONFIG_IIO_MS_SENSORS_I2C=m + +# +# SSP Sensor Common +# +# CONFIG_IIO_SSP_SENSORHUB is not set +# end of SSP Sensor Common + +CONFIG_IIO_ST_SENSORS_I2C=m +CONFIG_IIO_ST_SENSORS_SPI=m +CONFIG_IIO_ST_SENSORS_CORE=m + +# +# Digital to analog converters +# +CONFIG_AD5064=m +CONFIG_AD5360=m +CONFIG_AD5380=m +CONFIG_AD5421=m +CONFIG_AD5446=m +CONFIG_AD5449=m +CONFIG_AD5592R_BASE=m +CONFIG_AD5592R=m +CONFIG_AD5593R=m +CONFIG_AD5504=m +CONFIG_AD5624R_SPI=m +# CONFIG_LTC1660 is not set +# CONFIG_LTC2632 is not set +CONFIG_AD5686=m +CONFIG_AD5686_SPI=m +CONFIG_AD5696_I2C=m +CONFIG_AD5755=m +CONFIG_AD5758=m +CONFIG_AD5761=m +CONFIG_AD5764=m +CONFIG_AD5791=m +CONFIG_AD7303=m +# CONFIG_CIO_DAC is not set +CONFIG_AD8801=m +# CONFIG_DS4424 is not set +CONFIG_M62332=m +CONFIG_MAX517=m +CONFIG_MCP4725=m +CONFIG_MCP4922=m +# CONFIG_TI_DAC082S085 is not set +# CONFIG_TI_DAC5571 is not set +# CONFIG_TI_DAC7311 is not set +# CONFIG_TI_DAC7612 is not set +# end of Digital to analog converters + +# +# IIO dummy driver +# +# CONFIG_IIO_SIMPLE_DUMMY is not set +# end of IIO dummy driver + +# +# Frequency Synthesizers DDS/PLL +# + +# +# Clock Generator/Distribution +# +CONFIG_AD9523=m +# end of Clock Generator/Distribution + +# +# Phase-Locked Loop (PLL) frequency synthesizers +# +CONFIG_ADF4350=m +CONFIG_ADF4371=m +# end of Phase-Locked Loop (PLL) frequency synthesizers +# end of Frequency Synthesizers DDS/PLL + +# +# Digital gyroscope sensors +# +CONFIG_ADIS16080=m +CONFIG_ADIS16130=m +CONFIG_ADIS16136=m +CONFIG_ADIS16260=m +CONFIG_ADXRS450=m +CONFIG_BMG160=m +CONFIG_BMG160_I2C=m +CONFIG_BMG160_SPI=m +# CONFIG_FXAS21002C is not set +CONFIG_HID_SENSOR_GYRO_3D=m +# CONFIG_MPU3050_I2C is not set +CONFIG_IIO_ST_GYRO_3AXIS=m +CONFIG_IIO_ST_GYRO_I2C_3AXIS=m +CONFIG_IIO_ST_GYRO_SPI_3AXIS=m +CONFIG_ITG3200=m +# end of Digital gyroscope sensors + +# +# Health Sensors +# + +# +# Heart Rate Monitors +# +CONFIG_AFE4403=m +CONFIG_AFE4404=m +CONFIG_MAX30100=m +# CONFIG_MAX30102 is not set +# end of Heart Rate Monitors +# end of Health Sensors + +# +# Humidity sensors +# +CONFIG_AM2315=m +CONFIG_DHT11=m +CONFIG_HDC100X=m +CONFIG_HID_SENSOR_HUMIDITY=m +CONFIG_HTS221=m +CONFIG_HTS221_I2C=m +CONFIG_HTS221_SPI=m +CONFIG_HTU21=m +CONFIG_SI7005=m +CONFIG_SI7020=m +# end of Humidity sensors + +# +# Inertial measurement units +# +CONFIG_ADIS16400=m +CONFIG_ADIS16460=m +CONFIG_ADIS16480=m +CONFIG_BMI160=m +CONFIG_BMI160_I2C=m +CONFIG_BMI160_SPI=m +# CONFIG_KMX61 is not set +CONFIG_INV_MPU6050_IIO=m +CONFIG_INV_MPU6050_I2C=m +CONFIG_INV_MPU6050_SPI=m +# CONFIG_IIO_ST_LSM6DSX is not set +# end of Inertial measurement units + +CONFIG_IIO_ADIS_LIB=m +CONFIG_IIO_ADIS_LIB_BUFFER=y + +# +# Light sensors +# +CONFIG_ACPI_ALS=m +CONFIG_ADJD_S311=m +CONFIG_AL3320A=m +CONFIG_APDS9300=m +CONFIG_APDS9960=m +CONFIG_BH1750=m +CONFIG_BH1780=m +CONFIG_CM32181=m +# CONFIG_CM3232 is not set +# CONFIG_CM3323 is not set +CONFIG_CM36651=m +CONFIG_IIO_CROS_EC_LIGHT_PROX=m +CONFIG_GP2AP020A00F=m +CONFIG_SENSORS_ISL29018=m +CONFIG_SENSORS_ISL29028=m +CONFIG_ISL29125=m +CONFIG_HID_SENSOR_ALS=m +CONFIG_HID_SENSOR_PROX=m +# CONFIG_JSA1212 is not set +CONFIG_RPR0521=m +CONFIG_LTR501=m +# CONFIG_LV0104CS is not set +CONFIG_MAX44000=m +# CONFIG_MAX44009 is not set +# CONFIG_NOA1305 is not set +CONFIG_OPT3001=m +CONFIG_PA12203001=m +# CONFIG_SI1133 is not set +# CONFIG_SI1145 is not set +CONFIG_STK3310=m +CONFIG_ST_UVIS25=m +CONFIG_ST_UVIS25_I2C=m +CONFIG_ST_UVIS25_SPI=m +CONFIG_TCS3414=m +CONFIG_TCS3472=m +CONFIG_SENSORS_TSL2563=m +CONFIG_TSL2583=m +# CONFIG_TSL2772 is not set +CONFIG_TSL4531=m +CONFIG_US5182D=m +CONFIG_VCNL4000=m +# CONFIG_VCNL4035 is not set +CONFIG_VEML6070=m +# CONFIG_VL6180 is not set +# CONFIG_ZOPT2201 is not set +# end of Light sensors + +# +# Magnetometer sensors +# +CONFIG_AK8975=m +CONFIG_AK09911=m +CONFIG_BMC150_MAGN=m +CONFIG_BMC150_MAGN_I2C=m +CONFIG_BMC150_MAGN_SPI=m +CONFIG_MAG3110=m +CONFIG_HID_SENSOR_MAGNETOMETER_3D=m +CONFIG_MMC35240=m +CONFIG_IIO_ST_MAGN_3AXIS=m +CONFIG_IIO_ST_MAGN_I2C_3AXIS=m +CONFIG_IIO_ST_MAGN_SPI_3AXIS=m +CONFIG_SENSORS_HMC5843=m +CONFIG_SENSORS_HMC5843_I2C=m +CONFIG_SENSORS_HMC5843_SPI=m +# CONFIG_SENSORS_RM3100_I2C is not set +# CONFIG_SENSORS_RM3100_SPI is not set +# end of Magnetometer sensors + +# +# Multiplexers +# +# end of Multiplexers + +# +# Inclinometer sensors +# +CONFIG_HID_SENSOR_INCLINOMETER_3D=m +CONFIG_HID_SENSOR_DEVICE_ROTATION=m +# end of Inclinometer sensors + +# +# Triggers - standalone +# +CONFIG_IIO_HRTIMER_TRIGGER=m +CONFIG_IIO_INTERRUPT_TRIGGER=m +# CONFIG_IIO_TIGHTLOOP_TRIGGER is not set +CONFIG_IIO_SYSFS_TRIGGER=m +# end of Triggers - standalone + +# +# Digital potentiometers +# +# CONFIG_AD5272 is not set +CONFIG_DS1803=m +# CONFIG_MAX5432 is not set +# CONFIG_MAX5481 is not set +# CONFIG_MAX5487 is not set +# CONFIG_MCP4018 is not set +CONFIG_MCP4131=m +CONFIG_MCP4531=m +# CONFIG_MCP41010 is not set +CONFIG_TPL0102=m +# end of Digital potentiometers + +# +# Digital potentiostats +# +# CONFIG_LMP91000 is not set +# end of Digital potentiostats + +# +# Pressure sensors +# +# CONFIG_ABP060MG is not set +# CONFIG_BMP280 is not set +CONFIG_IIO_CROS_EC_BARO=m +# CONFIG_DPS310 is not set +CONFIG_HID_SENSOR_PRESS=m +CONFIG_HP03=m +CONFIG_MPL115=m +CONFIG_MPL115_I2C=m +CONFIG_MPL115_SPI=m +# CONFIG_MPL3115 is not set +# CONFIG_MS5611 is not set +CONFIG_MS5637=m +CONFIG_IIO_ST_PRESS=m +CONFIG_IIO_ST_PRESS_I2C=m +CONFIG_IIO_ST_PRESS_SPI=m +CONFIG_T5403=m +CONFIG_HP206C=m +# CONFIG_ZPA2326 is not set +# end of Pressure sensors + +# +# Lightning sensors +# +CONFIG_AS3935=m +# end of Lightning sensors + +# +# Proximity and distance sensors +# +# CONFIG_ISL29501 is not set +CONFIG_LIDAR_LITE_V2=m +# CONFIG_MB1232 is not set +# CONFIG_RFD77402 is not set +# CONFIG_SRF04 is not set +# CONFIG_SX9500 is not set +# CONFIG_SRF08 is not set +# CONFIG_VL53L0X_I2C is not set +# end of Proximity and distance sensors + +# +# Resolver to digital converters +# +CONFIG_AD2S90=m +CONFIG_AD2S1200=m +# end of Resolver to digital converters + +# +# Temperature sensors +# +# CONFIG_MAXIM_THERMOCOUPLE is not set +CONFIG_HID_SENSOR_TEMP=m +CONFIG_MLX90614=m +CONFIG_MLX90632=m +CONFIG_TMP006=m +# CONFIG_TMP007 is not set +CONFIG_TSYS01=m +CONFIG_TSYS02D=m +# CONFIG_MAX31856 is not set +# end of Temperature sensors + +CONFIG_NTB=m +# CONFIG_NTB_MSI is not set +CONFIG_NTB_AMD=m +CONFIG_NTB_IDT=m +CONFIG_NTB_INTEL=m +# CONFIG_NTB_SWITCHTEC is not set +CONFIG_NTB_PINGPONG=m +CONFIG_NTB_TOOL=m +CONFIG_NTB_PERF=m +CONFIG_NTB_TRANSPORT=m +CONFIG_VME_BUS=y + +# +# VME Bridge Drivers +# +CONFIG_VME_CA91CX42=m +CONFIG_VME_TSI148=m +# CONFIG_VME_FAKE is not set + +# +# VME Board Drivers +# +CONFIG_VMIVME_7805=m + +# +# VME Device Drivers +# +CONFIG_VME_USER=m +CONFIG_PWM=y +CONFIG_PWM_SYSFS=y +CONFIG_PWM_CRC=y +CONFIG_PWM_CROS_EC=m +CONFIG_PWM_LP3943=m +CONFIG_PWM_LPSS=m +CONFIG_PWM_LPSS_PCI=m +CONFIG_PWM_LPSS_PLATFORM=m +CONFIG_PWM_PCA9685=m +CONFIG_PWM_TWL=m +CONFIG_PWM_TWL_LED=m + +# +# IRQ chip support +# +CONFIG_MADERA_IRQ=m +# end of IRQ chip support + +# CONFIG_IPACK_BUS is not set +CONFIG_RESET_CONTROLLER=y +CONFIG_RESET_TI_SYSCON=m + +# +# PHY Subsystem +# +CONFIG_GENERIC_PHY=y +CONFIG_BCM_KONA_USB2_PHY=m +CONFIG_PHY_PXA_28NM_HSIC=m +CONFIG_PHY_PXA_28NM_USB2=m +CONFIG_PHY_CPCAP_USB=m +CONFIG_PHY_QCOM_USB_HS=m +CONFIG_PHY_QCOM_USB_HSIC=m +CONFIG_PHY_SAMSUNG_USB2=m +CONFIG_PHY_TUSB1210=m +# end of PHY Subsystem + +CONFIG_POWERCAP=y +CONFIG_INTEL_RAPL_CORE=m +CONFIG_INTEL_RAPL=m +CONFIG_IDLE_INJECT=y +# CONFIG_MCB is not set + +# +# Performance monitor support +# +# end of Performance monitor support + +CONFIG_RAS=y +# CONFIG_RAS_CEC is not set +CONFIG_THUNDERBOLT=m + +# +# Android +# +# CONFIG_ANDROID is not set +# end of Android + +CONFIG_LIBNVDIMM=m +CONFIG_BLK_DEV_PMEM=m +CONFIG_ND_BLK=m +CONFIG_ND_CLAIM=y +CONFIG_ND_BTT=m +CONFIG_BTT=y +CONFIG_NVDIMM_KEYS=y +CONFIG_DAX_DRIVER=y +CONFIG_DAX=y +CONFIG_DEV_DAX=m +CONFIG_DEV_DAX_KMEM=m +CONFIG_NVMEM=y +CONFIG_NVMEM_SYSFS=y + +# +# HW tracing support +# +CONFIG_STM=m +CONFIG_STM_PROTO_BASIC=m +CONFIG_STM_PROTO_SYS_T=m +CONFIG_STM_DUMMY=m +CONFIG_STM_SOURCE_CONSOLE=m +CONFIG_STM_SOURCE_HEARTBEAT=m +# CONFIG_STM_SOURCE_FTRACE is not set +CONFIG_INTEL_TH=m +CONFIG_INTEL_TH_PCI=m +CONFIG_INTEL_TH_ACPI=m +CONFIG_INTEL_TH_GTH=m +CONFIG_INTEL_TH_STH=m +CONFIG_INTEL_TH_MSU=m +CONFIG_INTEL_TH_PTI=m +# CONFIG_INTEL_TH_DEBUG is not set +# end of HW tracing support + +CONFIG_FPGA=m +# CONFIG_ALTERA_PR_IP_CORE is not set +# CONFIG_FPGA_MGR_ALTERA_PS_SPI is not set +# CONFIG_FPGA_MGR_ALTERA_CVP is not set +# CONFIG_FPGA_MGR_XILINX_SPI is not set +# CONFIG_FPGA_MGR_MACHXO2_SPI is not set +# CONFIG_FPGA_BRIDGE is not set +# CONFIG_FPGA_DFL is not set +CONFIG_PM_OPP=y +CONFIG_UNISYS_VISORBUS=m +# CONFIG_SIOX is not set +# CONFIG_SLIMBUS is not set +# CONFIG_INTERCONNECT is not set +# CONFIG_COUNTER is not set +# end of Device Drivers + +# +# File systems +# +CONFIG_DCACHE_WORD_ACCESS=y +# CONFIG_VALIDATE_FS_PARSER is not set +CONFIG_FS_IOMAP=y +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +CONFIG_EXT3_FS=m +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y +# CONFIG_EXT4_DEBUG is not set +CONFIG_JBD2=y +# CONFIG_JBD2_DEBUG is not set +CONFIG_FS_MBCACHE=y +CONFIG_REISERFS_FS=m +# CONFIG_REISERFS_CHECK is not set +CONFIG_REISERFS_PROC_INFO=y +CONFIG_REISERFS_FS_XATTR=y +CONFIG_REISERFS_FS_POSIX_ACL=y +CONFIG_REISERFS_FS_SECURITY=y +CONFIG_JFS_FS=m +CONFIG_JFS_POSIX_ACL=y +CONFIG_JFS_SECURITY=y +# CONFIG_JFS_DEBUG is not set +CONFIG_JFS_STATISTICS=y +CONFIG_XFS_FS=m +CONFIG_XFS_QUOTA=y +CONFIG_XFS_POSIX_ACL=y +CONFIG_XFS_RT=y +# CONFIG_XFS_ONLINE_SCRUB is not set +# CONFIG_XFS_WARN is not set +# CONFIG_XFS_DEBUG is not set +CONFIG_GFS2_FS=m +CONFIG_GFS2_FS_LOCKING_DLM=y +CONFIG_OCFS2_FS=m +CONFIG_OCFS2_FS_O2CB=m +CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m +CONFIG_OCFS2_FS_STATS=y +CONFIG_OCFS2_DEBUG_MASKLOG=y +# CONFIG_OCFS2_DEBUG_FS is not set +CONFIG_BTRFS_FS=y +CONFIG_BTRFS_FS_POSIX_ACL=y +# CONFIG_BTRFS_FS_CHECK_INTEGRITY is not set +# CONFIG_BTRFS_FS_RUN_SANITY_TESTS is not set +# CONFIG_BTRFS_DEBUG is not set +# CONFIG_BTRFS_ASSERT is not set +# CONFIG_BTRFS_FS_REF_VERIFY is not set +CONFIG_NILFS2_FS=m +CONFIG_F2FS_FS=m +CONFIG_F2FS_STAT_FS=y +CONFIG_F2FS_FS_XATTR=y +CONFIG_F2FS_FS_POSIX_ACL=y +# CONFIG_F2FS_FS_SECURITY is not set +# CONFIG_F2FS_CHECK_FS is not set +# CONFIG_F2FS_IO_TRACE is not set +# CONFIG_F2FS_FAULT_INJECTION is not set +CONFIG_FS_DAX=y +CONFIG_FS_POSIX_ACL=y +CONFIG_EXPORTFS=y +CONFIG_EXPORTFS_BLOCK_OPS=y +CONFIG_FILE_LOCKING=y +CONFIG_MANDATORY_FILE_LOCKING=y +CONFIG_FS_ENCRYPTION=y +# CONFIG_FS_VERITY is not set +CONFIG_FSNOTIFY=y +CONFIG_DNOTIFY=y +CONFIG_INOTIFY_USER=y +CONFIG_FANOTIFY=y +CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y +CONFIG_QUOTA=y +CONFIG_QUOTA_NETLINK_INTERFACE=y +CONFIG_PRINT_QUOTA_WARNING=y +# CONFIG_QUOTA_DEBUG is not set +CONFIG_QUOTA_TREE=y +CONFIG_QFMT_V1=m +CONFIG_QFMT_V2=y +CONFIG_QUOTACTL=y +CONFIG_QUOTACTL_COMPAT=y +CONFIG_AUTOFS4_FS=m +CONFIG_AUTOFS_FS=m +CONFIG_FUSE_FS=m +CONFIG_CUSE=m +CONFIG_VIRTIO_FS=m +CONFIG_OVERLAY_FS=m +# CONFIG_OVERLAY_FS_REDIRECT_DIR is not set +CONFIG_OVERLAY_FS_REDIRECT_ALWAYS_FOLLOW=y +# CONFIG_OVERLAY_FS_INDEX is not set +# CONFIG_OVERLAY_FS_XINO_AUTO is not set +# CONFIG_OVERLAY_FS_METACOPY is not set +CONFIG_AUFS_FS=m +# CONFIG_AUFS_BRANCH_MAX_127 is not set +CONFIG_AUFS_BRANCH_MAX_511=y +# CONFIG_AUFS_BRANCH_MAX_1023 is not set +# CONFIG_AUFS_BRANCH_MAX_32767 is not set +CONFIG_AUFS_SBILIST=y +# CONFIG_AUFS_HNOTIFY is not set +# CONFIG_AUFS_EXPORT is not set +# CONFIG_AUFS_XATTR is not set +# CONFIG_AUFS_FHSM is not set +# CONFIG_AUFS_RDU is not set +# CONFIG_AUFS_DIRREN is not set +CONFIG_AUFS_SHWH=y +# CONFIG_AUFS_BR_RAMFS is not set +# CONFIG_AUFS_BR_FUSE is not set +CONFIG_AUFS_BR_HFSPLUS=y +CONFIG_AUFS_BDEV_LOOP=y +# CONFIG_AUFS_DEBUG is not set + +# +# Caches +# +CONFIG_FSCACHE=m +CONFIG_FSCACHE_STATS=y +# CONFIG_FSCACHE_HISTOGRAM is not set +CONFIG_FSCACHE_DEBUG=y +# CONFIG_FSCACHE_OBJECT_LIST is not set +CONFIG_CACHEFILES=m +CONFIG_CACHEFILES_DEBUG=y +# CONFIG_CACHEFILES_HISTOGRAM is not set +# end of Caches + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=m +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_UDF_FS=m +# end of CD-ROM/DVD Filesystems + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +CONFIG_FAT_DEFAULT_UTF8=y +CONFIG_NTFS_FS=m +# CONFIG_NTFS_DEBUG is not set +# CONFIG_NTFS_RW is not set +# end of DOS/FAT/NT Filesystems + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_PROC_VMCORE=y +# CONFIG_PROC_VMCORE_DEVICE_DUMP is not set +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_PROC_CHILDREN=y +CONFIG_PROC_PID_ARCH_STATUS=y +CONFIG_KERNFS=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_TMPFS_XATTR=y +CONFIG_HUGETLBFS=y +CONFIG_HUGETLB_PAGE=y +CONFIG_MEMFD_CREATE=y +CONFIG_ARCH_HAS_GIGANTIC_PAGE=y +CONFIG_CONFIGFS_FS=m +CONFIG_EFIVAR_FS=m +# end of Pseudo filesystems + +CONFIG_MISC_FILESYSTEMS=y +CONFIG_ORANGEFS_FS=m +CONFIG_ADFS_FS=m +# CONFIG_ADFS_FS_RW is not set +CONFIG_AFFS_FS=m +CONFIG_ECRYPT_FS=m +# CONFIG_ECRYPT_FS_MESSAGING is not set +CONFIG_HFS_FS=m +CONFIG_HFSPLUS_FS=m +CONFIG_BEFS_FS=m +# CONFIG_BEFS_DEBUG is not set +CONFIG_BFS_FS=m +CONFIG_EFS_FS=m +CONFIG_JFFS2_FS=m +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +CONFIG_JFFS2_SUMMARY=y +CONFIG_JFFS2_FS_XATTR=y +CONFIG_JFFS2_FS_POSIX_ACL=y +CONFIG_JFFS2_FS_SECURITY=y +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +CONFIG_UBIFS_FS=m +# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set +CONFIG_UBIFS_FS_LZO=y +CONFIG_UBIFS_FS_ZLIB=y +CONFIG_UBIFS_FS_ZSTD=y +# CONFIG_UBIFS_ATIME_SUPPORT is not set +CONFIG_UBIFS_FS_XATTR=y +CONFIG_UBIFS_FS_SECURITY=y +CONFIG_UBIFS_FS_AUTHENTICATION=y +CONFIG_CRAMFS=y +CONFIG_CRAMFS_BLOCKDEV=y +CONFIG_SQUASHFS=m +# CONFIG_SQUASHFS_FILE_CACHE is not set +CONFIG_SQUASHFS_FILE_DIRECT=y +# CONFIG_SQUASHFS_DECOMP_SINGLE is not set +CONFIG_SQUASHFS_DECOMP_MULTI=y +# CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU is not set +CONFIG_SQUASHFS_XATTR=y +CONFIG_SQUASHFS_ZLIB=y +CONFIG_SQUASHFS_LZ4=y +CONFIG_SQUASHFS_LZO=y +CONFIG_SQUASHFS_XZ=y +CONFIG_SQUASHFS_ZSTD=y +# CONFIG_SQUASHFS_4K_DEVBLK_SIZE is not set +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +CONFIG_VXFS_FS=m +CONFIG_MINIX_FS=m +CONFIG_OMFS_FS=m +CONFIG_HPFS_FS=m +CONFIG_QNX4FS_FS=m +CONFIG_QNX6FS_FS=m +# CONFIG_QNX6FS_DEBUG is not set +CONFIG_ROMFS_FS=m +# CONFIG_ROMFS_BACKED_BY_BLOCK is not set +# CONFIG_ROMFS_BACKED_BY_MTD is not set +CONFIG_ROMFS_BACKED_BY_BOTH=y +CONFIG_ROMFS_ON_BLOCK=y +CONFIG_ROMFS_ON_MTD=y +CONFIG_PSTORE=y +CONFIG_PSTORE_DEFLATE_COMPRESS=m +CONFIG_PSTORE_LZO_COMPRESS=m +CONFIG_PSTORE_LZ4_COMPRESS=m +CONFIG_PSTORE_LZ4HC_COMPRESS=m +CONFIG_PSTORE_842_COMPRESS=y +CONFIG_PSTORE_ZSTD_COMPRESS=y +CONFIG_PSTORE_COMPRESS=y +CONFIG_PSTORE_DEFLATE_COMPRESS_DEFAULT=y +# CONFIG_PSTORE_LZO_COMPRESS_DEFAULT is not set +# CONFIG_PSTORE_LZ4_COMPRESS_DEFAULT is not set +# CONFIG_PSTORE_LZ4HC_COMPRESS_DEFAULT is not set +# CONFIG_PSTORE_842_COMPRESS_DEFAULT is not set +# CONFIG_PSTORE_ZSTD_COMPRESS_DEFAULT is not set +CONFIG_PSTORE_COMPRESS_DEFAULT="deflate" +# CONFIG_PSTORE_CONSOLE is not set +# CONFIG_PSTORE_PMSG is not set +# CONFIG_PSTORE_FTRACE is not set +CONFIG_PSTORE_RAM=m +CONFIG_SYSV_FS=m +CONFIG_UFS_FS=m +# CONFIG_UFS_FS_WRITE is not set +# CONFIG_UFS_DEBUG is not set +CONFIG_EROFS_FS=m +# CONFIG_EROFS_FS_DEBUG is not set +CONFIG_EROFS_FS_XATTR=y +CONFIG_EROFS_FS_POSIX_ACL=y +# CONFIG_EROFS_FS_SECURITY is not set +# CONFIG_EROFS_FS_ZIP is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=m +CONFIG_NFS_V2=m +CONFIG_NFS_V3=m +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=m +CONFIG_NFS_SWAP=y +CONFIG_NFS_V4_1=y +CONFIG_NFS_V4_2=y +CONFIG_PNFS_FILE_LAYOUT=m +CONFIG_PNFS_BLOCK=m +CONFIG_PNFS_FLEXFILE_LAYOUT=m +CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN="kernel.org" +# CONFIG_NFS_V4_1_MIGRATION is not set +CONFIG_NFS_V4_SECURITY_LABEL=y +CONFIG_NFS_FSCACHE=y +# CONFIG_NFS_USE_LEGACY_DNS is not set +CONFIG_NFS_USE_KERNEL_DNS=y +CONFIG_NFS_DEBUG=y +CONFIG_NFSD=m +CONFIG_NFSD_V2_ACL=y +CONFIG_NFSD_V3=y +CONFIG_NFSD_V3_ACL=y +CONFIG_NFSD_V4=y +CONFIG_NFSD_PNFS=y +CONFIG_NFSD_BLOCKLAYOUT=y +CONFIG_NFSD_SCSILAYOUT=y +CONFIG_NFSD_FLEXFILELAYOUT=y +# CONFIG_NFSD_V4_SECURITY_LABEL is not set +CONFIG_GRACE_PERIOD=m +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_NFS_ACL_SUPPORT=m +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=m +CONFIG_SUNRPC_GSS=m +CONFIG_SUNRPC_BACKCHANNEL=y +CONFIG_SUNRPC_SWAP=y +CONFIG_RPCSEC_GSS_KRB5=m +# CONFIG_SUNRPC_DISABLE_INSECURE_ENCTYPES is not set +CONFIG_SUNRPC_DEBUG=y +CONFIG_SUNRPC_XPRT_RDMA=m +CONFIG_CEPH_FS=m +CONFIG_CEPH_FSCACHE=y +CONFIG_CEPH_FS_POSIX_ACL=y +CONFIG_CEPH_FS_SECURITY_LABEL=y +CONFIG_CIFS=m +CONFIG_CIFS_STATS2=y +CONFIG_CIFS_ALLOW_INSECURE_LEGACY=y +CONFIG_CIFS_WEAK_PW_HASH=y +CONFIG_CIFS_UPCALL=y +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y +CONFIG_CIFS_DEBUG=y +# CONFIG_CIFS_DEBUG2 is not set +# CONFIG_CIFS_DEBUG_DUMP_KEYS is not set +CONFIG_CIFS_DFS_UPCALL=y +# CONFIG_CIFS_SMB_DIRECT is not set +# CONFIG_CIFS_FSCACHE is not set +CONFIG_CODA_FS=m +CONFIG_AFS_FS=m +# CONFIG_AFS_DEBUG is not set +CONFIG_AFS_FSCACHE=y +# CONFIG_AFS_DEBUG_CURSOR is not set +CONFIG_9P_FS=m +CONFIG_9P_FSCACHE=y +CONFIG_9P_FS_POSIX_ACL=y +# CONFIG_9P_FS_SECURITY is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_CODEPAGE_437=m +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m +CONFIG_NLS_ASCII=m +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m +CONFIG_NLS_MAC_ROMAN=m +CONFIG_NLS_MAC_CELTIC=m +CONFIG_NLS_MAC_CENTEURO=m +CONFIG_NLS_MAC_CROATIAN=m +CONFIG_NLS_MAC_CYRILLIC=m +CONFIG_NLS_MAC_GAELIC=m +CONFIG_NLS_MAC_GREEK=m +CONFIG_NLS_MAC_ICELAND=m +CONFIG_NLS_MAC_INUIT=m +CONFIG_NLS_MAC_ROMANIAN=m +CONFIG_NLS_MAC_TURKISH=m +CONFIG_NLS_UTF8=m +CONFIG_DLM=m +# CONFIG_DLM_DEBUG is not set +# CONFIG_UNICODE is not set +# end of File systems + +# +# Security options +# +CONFIG_KEYS=y +CONFIG_KEYS_COMPAT=y +# CONFIG_KEYS_REQUEST_CACHE is not set +# CONFIG_PERSISTENT_KEYRINGS is not set +# CONFIG_BIG_KEYS is not set +CONFIG_TRUSTED_KEYS=m +CONFIG_ENCRYPTED_KEYS=y +# CONFIG_KEY_DH_OPERATIONS is not set +# CONFIG_SECURITY_DMESG_RESTRICT is not set +CONFIG_SECURITY=y +CONFIG_SECURITYFS=y +CONFIG_SECURITY_NETWORK=y +CONFIG_PAGE_TABLE_ISOLATION=y +# CONFIG_SECURITY_INFINIBAND is not set +CONFIG_SECURITY_NETWORK_XFRM=y +CONFIG_SECURITY_PATH=y +CONFIG_INTEL_TXT=y +CONFIG_LSM_MMAP_MIN_ADDR=65536 +CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y +CONFIG_HARDENED_USERCOPY=y +CONFIG_HARDENED_USERCOPY_FALLBACK=y +# CONFIG_HARDENED_USERCOPY_PAGESPAN is not set +CONFIG_FORTIFY_SOURCE=y +# CONFIG_STATIC_USERMODEHELPER is not set +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +# CONFIG_SECURITY_SELINUX_DISABLE is not set +CONFIG_SECURITY_SELINUX_DEVELOP=y +# CONFIG_SECURITY_SELINUX_AVC_STATS is not set +CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=0 +# CONFIG_SECURITY_SMACK is not set +CONFIG_SECURITY_TOMOYO=y +CONFIG_SECURITY_TOMOYO_MAX_ACCEPT_ENTRY=2048 +CONFIG_SECURITY_TOMOYO_MAX_AUDIT_LOG=1024 +# CONFIG_SECURITY_TOMOYO_OMIT_USERSPACE_LOADER is not set +CONFIG_SECURITY_TOMOYO_POLICY_LOADER="/sbin/tomoyo-init" +CONFIG_SECURITY_TOMOYO_ACTIVATION_TRIGGER="/sbin/init" +# CONFIG_SECURITY_TOMOYO_INSECURE_BUILTIN_SETTING is not set +# CONFIG_SECURITY_APPARMOR is not set +# CONFIG_SECURITY_LOADPIN is not set +# CONFIG_SECURITY_YAMA is not set +# CONFIG_SECURITY_SAFESETID is not set +# CONFIG_SECURITY_LOCKDOWN_LSM is not set +CONFIG_INTEGRITY=y +# CONFIG_INTEGRITY_SIGNATURE is not set +CONFIG_INTEGRITY_AUDIT=y +# CONFIG_IMA is not set +# CONFIG_EVM is not set +CONFIG_DEFAULT_SECURITY_SELINUX=y +# CONFIG_DEFAULT_SECURITY_TOMOYO is not set +# CONFIG_DEFAULT_SECURITY_DAC is not set +CONFIG_LSM="" + +# +# Kernel hardening options +# + +# +# Memory initialization +# +CONFIG_INIT_STACK_NONE=y +# CONFIG_INIT_ON_ALLOC_DEFAULT_ON is not set +# CONFIG_INIT_ON_FREE_DEFAULT_ON is not set +# end of Memory initialization +# end of Kernel hardening options +# end of Security options + +CONFIG_XOR_BLOCKS=y +CONFIG_ASYNC_CORE=m +CONFIG_ASYNC_MEMCPY=m +CONFIG_ASYNC_XOR=m +CONFIG_ASYNC_PQ=m +CONFIG_ASYNC_RAID6_RECOV=m +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD=y +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_RNG_DEFAULT=y +CONFIG_CRYPTO_AKCIPHER2=y +CONFIG_CRYPTO_AKCIPHER=y +CONFIG_CRYPTO_KPP2=y +CONFIG_CRYPTO_KPP=m +CONFIG_CRYPTO_ACOMP2=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +CONFIG_CRYPTO_USER=m +CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y +CONFIG_CRYPTO_GF128MUL=m +CONFIG_CRYPTO_NULL=y +CONFIG_CRYPTO_NULL2=y +CONFIG_CRYPTO_PCRYPT=m +CONFIG_CRYPTO_CRYPTD=m +CONFIG_CRYPTO_AUTHENC=m +CONFIG_CRYPTO_TEST=m +CONFIG_CRYPTO_SIMD=m +CONFIG_CRYPTO_GLUE_HELPER_X86=m +CONFIG_CRYPTO_ENGINE=m + +# +# Public-key cryptography +# +CONFIG_CRYPTO_RSA=y +CONFIG_CRYPTO_DH=m +CONFIG_CRYPTO_ECC=m +CONFIG_CRYPTO_ECDH=m +CONFIG_CRYPTO_ECRDSA=m + +# +# Authenticated Encryption with Associated Data +# +CONFIG_CRYPTO_CCM=m +CONFIG_CRYPTO_GCM=m +CONFIG_CRYPTO_CHACHA20POLY1305=m +CONFIG_CRYPTO_AEGIS128=m +CONFIG_CRYPTO_AEGIS128_AESNI_SSE2=m +CONFIG_CRYPTO_SEQIV=y +CONFIG_CRYPTO_ECHAINIV=m + +# +# Block modes +# +CONFIG_CRYPTO_CBC=y +CONFIG_CRYPTO_CFB=m +CONFIG_CRYPTO_CTR=y +CONFIG_CRYPTO_CTS=y +CONFIG_CRYPTO_ECB=y +CONFIG_CRYPTO_LRW=m +CONFIG_CRYPTO_OFB=m +CONFIG_CRYPTO_PCBC=m +CONFIG_CRYPTO_XTS=y +CONFIG_CRYPTO_KEYWRAP=m +CONFIG_CRYPTO_NHPOLY1305=m +CONFIG_CRYPTO_NHPOLY1305_SSE2=m +CONFIG_CRYPTO_NHPOLY1305_AVX2=m +CONFIG_CRYPTO_ADIANTUM=m +CONFIG_CRYPTO_ESSIV=m + +# +# Hash modes +# +CONFIG_CRYPTO_CMAC=m +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_XCBC=m +CONFIG_CRYPTO_VMAC=m + +# +# Digest +# +CONFIG_CRYPTO_CRC32C=y +CONFIG_CRYPTO_CRC32C_INTEL=m +CONFIG_CRYPTO_CRC32=m +CONFIG_CRYPTO_CRC32_PCLMUL=m +CONFIG_CRYPTO_XXHASH=m +CONFIG_CRYPTO_CRCT10DIF=y +CONFIG_CRYPTO_CRCT10DIF_PCLMUL=y +CONFIG_CRYPTO_GHASH=m +CONFIG_CRYPTO_POLY1305=m +CONFIG_CRYPTO_POLY1305_X86_64=m +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_RMD128=m +CONFIG_CRYPTO_RMD160=m +CONFIG_CRYPTO_RMD256=m +CONFIG_CRYPTO_RMD320=m +CONFIG_CRYPTO_SHA1=m +CONFIG_CRYPTO_SHA1_SSSE3=m +CONFIG_CRYPTO_SHA256_SSSE3=m +CONFIG_CRYPTO_SHA512_SSSE3=m +CONFIG_CRYPTO_LIB_SHA256=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_SHA3=m +CONFIG_CRYPTO_SM3=m +CONFIG_CRYPTO_STREEBOG=m +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL=m + +# +# Ciphers +# +CONFIG_CRYPTO_LIB_AES=y +CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_AES_TI=m +CONFIG_CRYPTO_AES_NI_INTEL=m +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_LIB_ARC4=m +CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_BLOWFISH_COMMON=m +CONFIG_CRYPTO_BLOWFISH_X86_64=m +CONFIG_CRYPTO_CAMELLIA=m +CONFIG_CRYPTO_CAMELLIA_X86_64=m +CONFIG_CRYPTO_CAMELLIA_AESNI_AVX_X86_64=m +CONFIG_CRYPTO_CAMELLIA_AESNI_AVX2_X86_64=m +CONFIG_CRYPTO_CAST_COMMON=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST5_AVX_X86_64=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_CAST6_AVX_X86_64=m +CONFIG_CRYPTO_LIB_DES=m +CONFIG_CRYPTO_DES=m +CONFIG_CRYPTO_DES3_EDE_X86_64=m +CONFIG_CRYPTO_FCRYPT=m +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_SALSA20=m +CONFIG_CRYPTO_CHACHA20=m +CONFIG_CRYPTO_CHACHA20_X86_64=m +CONFIG_CRYPTO_SEED=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_SERPENT_SSE2_X86_64=m +CONFIG_CRYPTO_SERPENT_AVX_X86_64=m +CONFIG_CRYPTO_SERPENT_AVX2_X86_64=m +CONFIG_CRYPTO_SM4=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_TWOFISH_COMMON=m +CONFIG_CRYPTO_TWOFISH_X86_64=m +CONFIG_CRYPTO_TWOFISH_X86_64_3WAY=m +CONFIG_CRYPTO_TWOFISH_AVX_X86_64=m + +# +# Compression +# +CONFIG_CRYPTO_DEFLATE=m +CONFIG_CRYPTO_LZO=y +CONFIG_CRYPTO_842=y +CONFIG_CRYPTO_LZ4=m +CONFIG_CRYPTO_LZ4HC=m +CONFIG_CRYPTO_ZSTD=y + +# +# Random Number Generation +# +CONFIG_CRYPTO_ANSI_CPRNG=m +CONFIG_CRYPTO_DRBG_MENU=y +CONFIG_CRYPTO_DRBG_HMAC=y +# CONFIG_CRYPTO_DRBG_HASH is not set +# CONFIG_CRYPTO_DRBG_CTR is not set +CONFIG_CRYPTO_DRBG=y +CONFIG_CRYPTO_JITTERENTROPY=y +CONFIG_CRYPTO_USER_API=m +CONFIG_CRYPTO_USER_API_HASH=m +CONFIG_CRYPTO_USER_API_SKCIPHER=m +CONFIG_CRYPTO_USER_API_RNG=m +CONFIG_CRYPTO_USER_API_AEAD=m +# CONFIG_CRYPTO_STATS is not set +CONFIG_CRYPTO_HASH_INFO=y +CONFIG_CRYPTO_HW=y +CONFIG_CRYPTO_DEV_PADLOCK=m +CONFIG_CRYPTO_DEV_PADLOCK_AES=m +CONFIG_CRYPTO_DEV_PADLOCK_SHA=m +CONFIG_CRYPTO_DEV_ATMEL_I2C=m +CONFIG_CRYPTO_DEV_ATMEL_ECC=m +CONFIG_CRYPTO_DEV_ATMEL_SHA204A=m +CONFIG_CRYPTO_DEV_CCP=y +CONFIG_CRYPTO_DEV_CCP_DD=m +CONFIG_CRYPTO_DEV_SP_CCP=y +CONFIG_CRYPTO_DEV_CCP_CRYPTO=m +CONFIG_CRYPTO_DEV_SP_PSP=y +# CONFIG_CRYPTO_DEV_CCP_DEBUGFS is not set +CONFIG_CRYPTO_DEV_QAT=m +CONFIG_CRYPTO_DEV_QAT_DH895xCC=m +CONFIG_CRYPTO_DEV_QAT_C3XXX=m +CONFIG_CRYPTO_DEV_QAT_C62X=m +CONFIG_CRYPTO_DEV_QAT_DH895xCCVF=m +CONFIG_CRYPTO_DEV_QAT_C3XXXVF=m +CONFIG_CRYPTO_DEV_QAT_C62XVF=m +CONFIG_CRYPTO_DEV_NITROX=m +CONFIG_CRYPTO_DEV_NITROX_CNN55XX=m +CONFIG_CRYPTO_DEV_CHELSIO=m +CONFIG_CHELSIO_IPSEC_INLINE=y +CONFIG_CRYPTO_DEV_CHELSIO_TLS=m +CONFIG_CRYPTO_DEV_VIRTIO=m +CONFIG_CRYPTO_DEV_SAFEXCEL=m +CONFIG_ASYMMETRIC_KEY_TYPE=y +CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y +CONFIG_ASYMMETRIC_TPM_KEY_SUBTYPE=m +CONFIG_X509_CERTIFICATE_PARSER=y +CONFIG_PKCS8_PRIVATE_KEY_PARSER=m +CONFIG_TPM_KEY_PARSER=m +CONFIG_PKCS7_MESSAGE_PARSER=y +# CONFIG_PKCS7_TEST_KEY is not set +CONFIG_SIGNED_PE_FILE_VERIFICATION=y + +# +# Certificates for signature checking +# +CONFIG_SYSTEM_TRUSTED_KEYRING=y +CONFIG_SYSTEM_TRUSTED_KEYS="" +# CONFIG_SYSTEM_EXTRA_CERTIFICATE is not set +# CONFIG_SECONDARY_TRUSTED_KEYRING is not set +# CONFIG_SYSTEM_BLACKLIST_KEYRING is not set +# end of Certificates for signature checking + +CONFIG_BINARY_PRINTF=y + +# +# Library routines +# +CONFIG_RAID6_PQ=y +CONFIG_RAID6_PQ_BENCHMARK=y +# CONFIG_PACKING is not set +CONFIG_BITREVERSE=y +CONFIG_GENERIC_STRNCPY_FROM_USER=y +CONFIG_GENERIC_STRNLEN_USER=y +CONFIG_GENERIC_NET_UTILS=y +CONFIG_GENERIC_FIND_FIRST_BIT=y +CONFIG_CORDIC=m +CONFIG_RATIONAL=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_IOMAP=y +CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y +CONFIG_ARCH_HAS_FAST_MULTIPLIER=y +CONFIG_CRC_CCITT=m +CONFIG_CRC16=y +CONFIG_CRC_T10DIF=y +CONFIG_CRC_ITU_T=m +CONFIG_CRC32=y +# CONFIG_CRC32_SELFTEST is not set +CONFIG_CRC32_SLICEBY8=y +# CONFIG_CRC32_SLICEBY4 is not set +# CONFIG_CRC32_SARWATE is not set +# CONFIG_CRC32_BIT is not set +CONFIG_CRC64=y +CONFIG_CRC4=m +CONFIG_CRC7=m +CONFIG_LIBCRC32C=y +CONFIG_CRC8=m +CONFIG_XXHASH=y +# CONFIG_RANDOM32_SELFTEST is not set +CONFIG_842_COMPRESS=y +CONFIG_842_DECOMPRESS=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_LZ4_COMPRESS=m +CONFIG_LZ4HC_COMPRESS=m +CONFIG_LZ4_DECOMPRESS=y +CONFIG_ZSTD_COMPRESS=y +CONFIG_ZSTD_DECOMPRESS=y +CONFIG_XZ_DEC=y +CONFIG_XZ_DEC_X86=y +# CONFIG_XZ_DEC_POWERPC is not set +# CONFIG_XZ_DEC_IA64 is not set +# CONFIG_XZ_DEC_ARM is not set +# CONFIG_XZ_DEC_ARMTHUMB is not set +# CONFIG_XZ_DEC_SPARC is not set +CONFIG_XZ_DEC_BCJ=y +# CONFIG_XZ_DEC_TEST is not set +CONFIG_DECOMPRESS_GZIP=y +CONFIG_DECOMPRESS_BZIP2=y +CONFIG_DECOMPRESS_LZMA=y +CONFIG_DECOMPRESS_XZ=y +CONFIG_DECOMPRESS_LZO=y +CONFIG_DECOMPRESS_LZ4=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_REED_SOLOMON=m +CONFIG_REED_SOLOMON_ENC8=y +CONFIG_REED_SOLOMON_DEC8=y +CONFIG_REED_SOLOMON_DEC16=y +CONFIG_BCH=m +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=m +CONFIG_TEXTSEARCH_BM=m +CONFIG_TEXTSEARCH_FSM=m +CONFIG_BTREE=y +CONFIG_INTERVAL_TREE=y +CONFIG_XARRAY_MULTI=y +CONFIG_ASSOCIATIVE_ARRAY=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT_MAP=y +CONFIG_HAS_DMA=y +CONFIG_NEED_SG_DMA_LENGTH=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_ARCH_DMA_ADDR_T_64BIT=y +CONFIG_DMA_VIRT_OPS=y +CONFIG_SWIOTLB=y +# CONFIG_DMA_CMA is not set +# CONFIG_DMA_API_DEBUG is not set +CONFIG_SGL_ALLOC=y +CONFIG_IOMMU_HELPER=y +CONFIG_CHECK_SIGNATURE=y +CONFIG_CPU_RMAP=y +CONFIG_DQL=y +CONFIG_GLOB=y +# CONFIG_GLOB_SELFTEST is not set +CONFIG_NLATTR=y +CONFIG_CLZ_TAB=y +CONFIG_IRQ_POLL=y +CONFIG_MPILIB=y +CONFIG_DIMLIB=y +CONFIG_OID_REGISTRY=y +CONFIG_UCS2_STRING=y +CONFIG_HAVE_GENERIC_VDSO=y +CONFIG_GENERIC_GETTIMEOFDAY=y +CONFIG_FONT_SUPPORT=y +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +CONFIG_SG_POOL=y +CONFIG_ARCH_HAS_PMEM_API=y +CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE=y +CONFIG_ARCH_HAS_UACCESS_MCSAFE=y +CONFIG_ARCH_STACKWALK=y +CONFIG_SBITMAP=y +CONFIG_PARMAN=m +CONFIG_OBJAGG=m +# CONFIG_STRING_SELFTEST is not set +# end of Library routines + +# +# Kernel hacking +# + +# +# printk and dmesg options +# +CONFIG_PRINTK_TIME=y +# CONFIG_PRINTK_CALLER is not set +CONFIG_CONSOLE_LOGLEVEL_DEFAULT=7 +CONFIG_CONSOLE_LOGLEVEL_QUIET=4 +CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 +CONFIG_BOOT_PRINTK_DELAY=y +CONFIG_DYNAMIC_DEBUG=y +# end of printk and dmesg options + +# +# Compile-time checks and compiler options +# +# CONFIG_DEBUG_INFO is not set +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=2048 +CONFIG_STRIP_ASM_SYMS=y +# CONFIG_READABLE_ASM is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_INSTALL is not set +CONFIG_OPTIMIZE_INLINING=y +# CONFIG_DEBUG_SECTION_MISMATCH is not set +CONFIG_SECTION_MISMATCH_WARN_ONLY=y +CONFIG_STACK_VALIDATION=y +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +# end of Compile-time checks and compiler options + +CONFIG_MAGIC_SYSRQ=y +CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1 +CONFIG_MAGIC_SYSRQ_SERIAL=y +CONFIG_DEBUG_KERNEL=y +CONFIG_DEBUG_MISC=y + +# +# Memory Debugging +# +# CONFIG_PAGE_EXTENSION is not set +# CONFIG_DEBUG_PAGEALLOC is not set +# CONFIG_PAGE_OWNER is not set +# CONFIG_PAGE_POISONING is not set +# CONFIG_DEBUG_PAGE_REF is not set +# CONFIG_DEBUG_RODATA_TEST is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_SLUB_STATS is not set +CONFIG_HAVE_DEBUG_KMEMLEAK=y +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_VM is not set +CONFIG_ARCH_HAS_DEBUG_VIRTUAL=y +# CONFIG_DEBUG_VIRTUAL is not set +CONFIG_DEBUG_MEMORY_INIT=y +CONFIG_MEMORY_NOTIFIER_ERROR_INJECT=m +# CONFIG_DEBUG_PER_CPU_MAPS is not set +CONFIG_HAVE_ARCH_KASAN=y +CONFIG_CC_HAS_KASAN_GENERIC=y +# CONFIG_KASAN is not set +CONFIG_KASAN_STACK=1 +# end of Memory Debugging + +CONFIG_ARCH_HAS_KCOV=y +CONFIG_CC_HAS_SANCOV_TRACE_PC=y +# CONFIG_KCOV is not set +# CONFIG_DEBUG_SHIRQ is not set + +# +# Debug Lockups and Hangs +# +# CONFIG_SOFTLOCKUP_DETECTOR is not set +CONFIG_HARDLOCKUP_CHECK_TIMESTAMP=y +# CONFIG_HARDLOCKUP_DETECTOR is not set +CONFIG_DETECT_HUNG_TASK=y +CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 +# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set +CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 +# CONFIG_WQ_WATCHDOG is not set +# end of Debug Lockups and Hangs + +# CONFIG_PANIC_ON_OOPS is not set +CONFIG_PANIC_ON_OOPS_VALUE=0 +CONFIG_PANIC_TIMEOUT=0 +CONFIG_SCHED_DEBUG=y +CONFIG_SCHED_INFO=y +CONFIG_SCHEDSTATS=y +# CONFIG_SCHED_STACK_END_CHECK is not set +# CONFIG_DEBUG_TIMEKEEPING is not set + +# +# Lock Debugging (spinlocks, mutexes, etc...) +# +CONFIG_LOCK_DEBUGGING_SUPPORT=y +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set +# CONFIG_DEBUG_RWSEMS is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_DEBUG_ATOMIC_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_LOCK_TORTURE_TEST is not set +# CONFIG_WW_MUTEX_SELFTEST is not set +# end of Lock Debugging (spinlocks, mutexes, etc...) + +CONFIG_STACKTRACE=y +# CONFIG_WARN_ALL_UNSEEDED_RANDOM is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_PLIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS is not set + +# +# RCU Debugging +# +CONFIG_TORTURE_TEST=m +CONFIG_RCU_PERF_TEST=m +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_RCU_CPU_STALL_TIMEOUT=60 +# CONFIG_RCU_TRACE is not set +# CONFIG_RCU_EQS_DEBUG is not set +# end of RCU Debugging + +# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_CPU_HOTPLUG_STATE_CONTROL is not set +CONFIG_NOTIFIER_ERROR_INJECTION=m +CONFIG_PM_NOTIFIER_ERROR_INJECT=m +# CONFIG_NETDEV_NOTIFIER_ERROR_INJECT is not set +CONFIG_FUNCTION_ERROR_INJECTION=y +# CONFIG_FAULT_INJECTION is not set +CONFIG_LATENCYTOP=y +CONFIG_USER_STACKTRACE_SUPPORT=y +CONFIG_NOP_TRACER=y +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_SYSCALL_TRACEPOINTS=y +CONFIG_HAVE_FENTRY=y +CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_TRACER_MAX_TRACE=y +CONFIG_TRACE_CLOCK=y +CONFIG_RING_BUFFER=y +CONFIG_EVENT_TRACING=y +CONFIG_CONTEXT_SWITCH_TRACER=y +CONFIG_RING_BUFFER_ALLOW_SWAP=y +CONFIG_TRACING=y +CONFIG_GENERIC_TRACER=y +CONFIG_TRACING_SUPPORT=y +CONFIG_FTRACE=y +CONFIG_FUNCTION_TRACER=y +# CONFIG_FUNCTION_GRAPH_TRACER is not set +# CONFIG_PREEMPTIRQ_EVENTS is not set +# CONFIG_IRQSOFF_TRACER is not set +CONFIG_SCHED_TRACER=y +# CONFIG_HWLAT_TRACER is not set +CONFIG_FTRACE_SYSCALLS=y +CONFIG_TRACER_SNAPSHOT=y +# CONFIG_TRACER_SNAPSHOT_PER_CPU_SWAP is not set +CONFIG_BRANCH_PROFILE_NONE=y +# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set +CONFIG_STACK_TRACER=y +CONFIG_BLK_DEV_IO_TRACE=y +CONFIG_KPROBE_EVENTS=y +# CONFIG_KPROBE_EVENTS_ON_NOTRACE is not set +CONFIG_UPROBE_EVENTS=y +CONFIG_BPF_EVENTS=y +CONFIG_DYNAMIC_EVENTS=y +CONFIG_PROBE_EVENTS=y +CONFIG_DYNAMIC_FTRACE=y +CONFIG_DYNAMIC_FTRACE_WITH_REGS=y +CONFIG_FUNCTION_PROFILER=y +# CONFIG_BPF_KPROBE_OVERRIDE is not set +CONFIG_FTRACE_MCOUNT_RECORD=y +# CONFIG_FTRACE_STARTUP_TEST is not set +CONFIG_MMIOTRACE=y +# CONFIG_HIST_TRIGGERS is not set +# CONFIG_MMIOTRACE_TEST is not set +# CONFIG_TRACEPOINT_BENCHMARK is not set +CONFIG_RING_BUFFER_BENCHMARK=m +# CONFIG_RING_BUFFER_STARTUP_TEST is not set +# CONFIG_PREEMPTIRQ_DELAY_TEST is not set +# CONFIG_TRACE_EVAL_MAP_FILE is not set +# CONFIG_PROVIDE_OHCI1394_DMA_INIT is not set +CONFIG_RUNTIME_TESTING_MENU=y +# CONFIG_LKDTM is not set +# CONFIG_TEST_LIST_SORT is not set +# CONFIG_TEST_SORT is not set +# CONFIG_KPROBES_SANITY_TEST is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +CONFIG_RBTREE_TEST=m +# CONFIG_REED_SOLOMON_TEST is not set +CONFIG_INTERVAL_TREE_TEST=m +# CONFIG_PERCPU_TEST is not set +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_ASYNC_RAID6_TEST is not set +# CONFIG_TEST_HEXDUMP is not set +# CONFIG_TEST_STRING_HELPERS is not set +# CONFIG_TEST_STRSCPY is not set +# CONFIG_TEST_KSTRTOX is not set +# CONFIG_TEST_PRINTF is not set +# CONFIG_TEST_BITMAP is not set +# CONFIG_TEST_BITFIELD is not set +# CONFIG_TEST_UUID is not set +CONFIG_TEST_XARRAY=m +# CONFIG_TEST_OVERFLOW is not set +# CONFIG_TEST_RHASHTABLE is not set +# CONFIG_TEST_HASH is not set +# CONFIG_TEST_IDA is not set +# CONFIG_TEST_PARMAN is not set +# CONFIG_TEST_LKM is not set +# CONFIG_TEST_VMALLOC is not set +# CONFIG_TEST_USER_COPY is not set +# CONFIG_TEST_BPF is not set +# CONFIG_TEST_BLACKHOLE_DEV is not set +# CONFIG_FIND_BIT_BENCHMARK is not set +# CONFIG_TEST_FIRMWARE is not set +# CONFIG_TEST_SYSCTL is not set +# CONFIG_TEST_UDELAY is not set +# CONFIG_TEST_STATIC_KEYS is not set +# CONFIG_TEST_KMOD is not set +# CONFIG_TEST_MEMCAT_P is not set +# CONFIG_TEST_LIVEPATCH is not set +# CONFIG_TEST_OBJAGG is not set +# CONFIG_TEST_STACKINIT is not set +# CONFIG_TEST_MEMINIT is not set +CONFIG_MEMTEST=y +# CONFIG_BUG_ON_DATA_CORRUPTION is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +CONFIG_ARCH_HAS_UBSAN_SANITIZE_ALL=y +# CONFIG_UBSAN is not set +CONFIG_UBSAN_ALIGNMENT=y +CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y +CONFIG_STRICT_DEVMEM=y +CONFIG_IO_STRICT_DEVMEM=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_X86_VERBOSE_BOOTUP=y +CONFIG_EARLY_PRINTK=y +# CONFIG_EARLY_PRINTK_DBGP is not set +# CONFIG_EARLY_PRINTK_USB_XDBC is not set +CONFIG_X86_PTDUMP_CORE=y +# CONFIG_X86_PTDUMP is not set +# CONFIG_EFI_PGT_DUMP is not set +CONFIG_DEBUG_WX=y +CONFIG_DOUBLEFAULT=y +# CONFIG_DEBUG_TLBFLUSH is not set +# CONFIG_IOMMU_DEBUG is not set +CONFIG_HAVE_MMIOTRACE_SUPPORT=y +# CONFIG_X86_DECODER_SELFTEST is not set +CONFIG_IO_DELAY_0X80=y +# CONFIG_IO_DELAY_0XED is not set +# CONFIG_IO_DELAY_UDELAY is not set +# CONFIG_IO_DELAY_NONE is not set +# CONFIG_DEBUG_BOOT_PARAMS is not set +# CONFIG_CPA_DEBUG is not set +# CONFIG_DEBUG_ENTRY is not set +# CONFIG_DEBUG_NMI_SELFTEST is not set +CONFIG_X86_DEBUG_FPU=y +CONFIG_PUNIT_ATOM_DEBUG=m +CONFIG_UNWINDER_ORC=y +# CONFIG_UNWINDER_FRAME_POINTER is not set +# CONFIG_UNWINDER_GUESS is not set +# end of Kernel hacking diff --git a/kernel/kernel/files/patches/linux/patch-5.4.6.xz b/kernel/kernel/files/patches/linux/patch-5.4.6.xz new file mode 100644 index 0000000000000000000000000000000000000000..96152450feec2ee538e623e2318d53be0529fab7 GIT binary patch literal 167272 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 literal 0 HcmV?d00001 diff --git a/kernel/kernel/files/patches/mageia/CVE-2019-12379.patch b/kernel/kernel/files/patches/mageia/CVE-2019-12379.patch new file mode 100644 index 00000000..04d16049 --- /dev/null +++ b/kernel/kernel/files/patches/mageia/CVE-2019-12379.patch @@ -0,0 +1,37 @@ +From 84ecc2f6eb1cb12e6d44818f94fa49b50f06e6ac Mon Sep 17 00:00:00 2001 +From: Gen Zhang +Date: Thu, 23 May 2019 08:34:52 +0800 +Subject: consolemap: Fix a memory leaking bug in drivers/tty/vt/consolemap.c + +In function con_insert_unipair(), when allocation for p2 and p1[n] +fails, ENOMEM is returned, but previously allocated p1 is not freed, +remains as leaking memory. Thus we should free p1 as well when this +allocation fails. + +Signed-off-by: Gen Zhang +Reviewed-by: Kees Cook +Signed-off-by: Greg Kroah-Hartman +--- + drivers/tty/vt/consolemap.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/tty/vt/consolemap.c b/drivers/tty/vt/consolemap.c +index b28aa0d289f8..79fcc96cc7c0 100644 +--- a/drivers/tty/vt/consolemap.c ++++ b/drivers/tty/vt/consolemap.c +@@ -489,7 +489,11 @@ con_insert_unipair(struct uni_pagedir *p, u_short unicode, u_short fontpos) + p2 = p1[n = (unicode >> 6) & 0x1f]; + if (!p2) { + p2 = p1[n] = kmalloc_array(64, sizeof(u16), GFP_KERNEL); +- if (!p2) return -ENOMEM; ++ if (!p2) { ++ kfree(p1); ++ p->uni_pgdir[n] = NULL; ++ return -ENOMEM; ++ } + memset(p2, 0xff, 64*sizeof(u16)); /* No glyphs for the characters (yet) */ + } + +-- +cgit 1.2-0.3.lf.el7 + diff --git a/kernel/kernel/files/patches/mageia/disable-mrproper-in-devel-rpms.patch b/kernel/kernel/files/patches/mageia/disable-mrproper-in-devel-rpms.patch new file mode 100644 index 00000000..150d8e1e --- /dev/null +++ b/kernel/kernel/files/patches/mageia/disable-mrproper-in-devel-rpms.patch @@ -0,0 +1,74 @@ + + Makefile | 18 +++++------------- + scripts/kconfig/Makefile | 4 ---- + 2 files changed, 5 insertions(+), 17 deletions(-) + +diff -Nurp linux-5.4.orig/Makefile linux-5.4/Makefile +--- linux-5.4.orig/Makefile 2019-11-30 23:06:49.394199628 +0200 ++++ linux-5.4/Makefile 2019-11-30 23:08:00.927203318 +0200 +@@ -1093,8 +1093,7 @@ include/config/kernel.release: FORCE + # Carefully list dependencies so we do not try to build scripts twice + # in parallel + PHONY += scripts +-scripts: scripts_basic scripts_dtc +- $(Q)$(MAKE) $(build)=$(@) ++scripts: + + # Things we need to do before we recursively start building the kernel + # or the modules are listed in "prepare". +@@ -1112,7 +1111,7 @@ prepare0: archprepare + $(Q)$(MAKE) $(build)=. + + # All the preparing.. +-prepare: prepare0 prepare-objtool ++prepare: + + # Support for using generic headers in asm-generic + asm-generic := -f $(srctree)/scripts/Makefile.asm-generic obj +@@ -1363,15 +1362,8 @@ CLEAN_DIRS += include/ksym + CLEAN_FILES += modules.builtin.modinfo + + # Directories & files removed with 'make mrproper' +-MRPROPER_DIRS += include/config include/generated \ +- arch/$(SRCARCH)/include/generated .tmp_objdiff \ +- debian/ snap/ tar-install/ +-MRPROPER_FILES += .config .config.old .version \ +- Module.symvers \ +- signing_key.pem signing_key.priv signing_key.x509 \ +- x509.genkey extra_certificates signing_key.x509.keyid \ +- signing_key.x509.signer vmlinux-gdb.py \ +- *.spec ++MRPROPER_DIRS += "" ++MRPROPER_FILES += "" + + # Directories & files removed with 'make distclean' + DISTCLEAN_DIRS += +@@ -1394,7 +1386,7 @@ clean: archclean vmlinuxclean + # + mrproper: rm-dirs := $(wildcard $(MRPROPER_DIRS)) + mrproper: rm-files := $(wildcard $(MRPROPER_FILES)) +-mrproper-dirs := $(addprefix _mrproper_,scripts) ++mrproper-dirs := $(addprefix _mrproper_,scripts) + + PHONY += $(mrproper-dirs) mrproper + $(mrproper-dirs): +diff -Nurp linux-5.4.orig/scripts/kconfig/Makefile linux-5.4/scripts/kconfig/Makefile +--- linux-5.4.orig/scripts/kconfig/Makefile 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4/scripts/kconfig/Makefile 2019-11-30 23:07:24.957201462 +0200 +@@ -24,16 +24,12 @@ endif + unexport CONFIG_ + + xconfig: $(obj)/qconf +- $< $(silent) $(Kconfig) + + gconfig: $(obj)/gconf +- $< $(silent) $(Kconfig) + + menuconfig: $(obj)/mconf +- $< $(silent) $(Kconfig) + + config: $(obj)/conf +- $< $(silent) --oldaskconfig $(Kconfig) + + nconfig: $(obj)/nconf + $< $(silent) $(Kconfig) diff --git a/kernel/kernel/files/patches/mageia/fs-aufs-5.4-modular.patch b/kernel/kernel/files/patches/mageia/fs-aufs-5.4-modular.patch new file mode 100644 index 00000000..ec4a9135 --- /dev/null +++ b/kernel/kernel/files/patches/mageia/fs-aufs-5.4-modular.patch @@ -0,0 +1,321 @@ + + fs/aufs/Kconfig | 2 +- + fs/dcache.c | 2 ++ + fs/exec.c | 1 + + fs/fcntl.c | 1 + + fs/file_table.c | 2 ++ + fs/inode.c | 1 + + fs/namespace.c | 3 +++ + fs/notify/group.c | 1 + + fs/open.c | 1 + + fs/read_write.c | 4 ++++ + fs/splice.c | 2 ++ + fs/sync.c | 1 + + fs/xattr.c | 1 + + kernel/locking/lockdep.c | 1 + + kernel/task_work.c | 1 + + security/device_cgroup.c | 1 + + security/security.c | 8 ++++++++ + 17 files changed, 32 insertions(+), 1 deletion(-) + +diff -Nurp linux-5.4-aufs/fs/aufs/Kconfig linux-5.4-aufs-mod/fs/aufs/Kconfig +--- linux-5.4-aufs/fs/aufs/Kconfig 2019-11-28 01:25:59.062925618 +0200 ++++ linux-5.4-aufs-mod/fs/aufs/Kconfig 2019-11-28 01:38:40.564895255 +0200 +@@ -1,6 +1,6 @@ + # SPDX-License-Identifier: GPL-2.0 + config AUFS_FS +- bool "Aufs (Advanced multi layered unification filesystem) support" ++ tristate "Aufs (Advanced multi layered unification filesystem) support" + help + Aufs is a stackable unification filesystem such as Unionfs, + which unifies several directories and provides a merged single +diff -Nurp linux-5.4-aufs/fs/dcache.c linux-5.4-aufs-mod/fs/dcache.c +--- linux-5.4-aufs/fs/dcache.c 2019-11-28 01:25:59.069925618 +0200 ++++ linux-5.4-aufs-mod/fs/dcache.c 2019-11-28 01:38:40.585895254 +0200 +@@ -1369,6 +1369,7 @@ rename_retry: + seq = 1; + goto again; + } ++EXPORT_SYMBOL_GPL(d_walk); + + struct check_mount { + struct vfsmount *mnt; +@@ -2914,6 +2915,7 @@ void d_exchange(struct dentry *dentry1, + + write_sequnlock(&rename_lock); + } ++EXPORT_SYMBOL_GPL(d_exchange); + + /** + * d_ancestor - search for an ancestor +diff -Nurp linux-5.4-aufs/fs/exec.c linux-5.4-aufs-mod/fs/exec.c +--- linux-5.4-aufs/fs/exec.c 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs-mod/fs/exec.c 2019-11-28 01:38:40.589895254 +0200 +@@ -110,6 +110,7 @@ bool path_noexec(const struct path *path + return (path->mnt->mnt_flags & MNT_NOEXEC) || + (path->mnt->mnt_sb->s_iflags & SB_I_NOEXEC); + } ++EXPORT_SYMBOL_GPL(path_noexec); + + #ifdef CONFIG_USELIB + /* +diff -Nurp linux-5.4-aufs/fs/fcntl.c linux-5.4-aufs-mod/fs/fcntl.c +--- linux-5.4-aufs/fs/fcntl.c 2019-11-28 01:25:59.069925618 +0200 ++++ linux-5.4-aufs-mod/fs/fcntl.c 2019-11-28 01:38:40.589895254 +0200 +@@ -85,6 +85,7 @@ int setfl(int fd, struct file * filp, un + out: + return error; + } ++EXPORT_SYMBOL_GPL(setfl); + + static void f_modown(struct file *filp, struct pid *pid, enum pid_type type, + int force) +diff -Nurp linux-5.4-aufs/fs/file_table.c linux-5.4-aufs-mod/fs/file_table.c +--- linux-5.4-aufs/fs/file_table.c 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs-mod/fs/file_table.c 2019-11-28 01:38:40.589895254 +0200 +@@ -162,6 +162,7 @@ over: + } + return ERR_PTR(-ENFILE); + } ++EXPORT_SYMBOL_GPL(alloc_empty_file); + + /* + * Variant of alloc_empty_file() that doesn't check and modify nr_files. +@@ -375,6 +377,7 @@ void __fput_sync(struct file *file) + } + + EXPORT_SYMBOL(fput); ++EXPORT_SYMBOL_GPL(__fput_sync); + + void __init files_init(void) + { +diff -Nurp linux-5.4-aufs/fs/inode.c linux-5.4-aufs-mod/fs/inode.c +--- linux-5.4-aufs/fs/inode.c 2019-11-28 01:25:59.070925617 +0200 ++++ linux-5.4-aufs-mod/fs/inode.c 2019-11-28 01:38:40.589895254 +0200 +@@ -1682,6 +1682,7 @@ int update_time(struct inode *inode, str + + return update_time(inode, time, flags); + } ++EXPORT_SYMBOL_GPL(update_time); + + /** + * touch_atime - update the access time +diff -Nurp linux-5.4-aufs/fs/namespace.c linux-5.4-aufs-mod/fs/namespace.c +--- linux-5.4-aufs/fs/namespace.c 2019-11-28 01:25:59.070925617 +0200 ++++ linux-5.4-aufs-mod/fs/namespace.c 2019-11-28 01:38:40.589895254 +0200 +@@ -431,6 +431,7 @@ void __mnt_drop_write(struct vfsmount *m + mnt_dec_writers(real_mount(mnt)); + preempt_enable(); + } ++EXPORT_SYMBOL_GPL(__mnt_drop_write); + + /** + * mnt_drop_write - give up write access to a mount +@@ -781,6 +782,7 @@ int is_current_mnt_ns(struct vfsmount *m + { + return check_mnt(real_mount(mnt)); + } ++EXPORT_SYMBOL_GPL(is_current_mnt_ns); + + /* + * vfsmount lock must be held for write +@@ -1903,6 +1905,7 @@ int iterate_mounts(int (*f)(struct vfsmo + } + return 0; + } ++EXPORT_SYMBOL_GPL(iterate_mounts); + + static void lock_mnt_tree(struct mount *mnt) + { +diff -Nurp linux-5.4-aufs/fs/notify/group.c linux-5.4-aufs-mod/fs/notify/group.c +--- linux-5.4-aufs/fs/notify/group.c 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs-mod/fs/notify/group.c 2019-11-28 01:38:40.590895253 +0200 +@@ -99,6 +99,7 @@ void fsnotify_get_group(struct fsnotify_ + { + refcount_inc(&group->refcnt); + } ++EXPORT_SYMBOL_GPL(fsnotify_get_group); + + /* + * Drop a reference to a group. Free it if it's through. +diff -Nurp linux-5.4-aufs/fs/open.c linux-5.4-aufs-mod/fs/open.c +--- linux-5.4-aufs/fs/open.c 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs-mod/fs/open.c 2019-11-28 01:38:48.762894928 +0200 +@@ -65,6 +65,7 @@ int do_truncate(struct dentry *dentry, l + inode_unlock(dentry->d_inode); + return ret; + } ++EXPORT_SYMBOL_GPL(do_truncate); + + long vfs_truncate(const struct path *path, loff_t length) + { +diff -Nurp linux-5.4-aufs/fs/read_write.c linux-5.4-aufs-mod/fs/read_write.c +--- linux-5.4-aufs/fs/read_write.c 2019-11-28 01:25:59.070925617 +0200 ++++ linux-5.4-aufs-mod/fs/read_write.c 2019-11-28 01:38:48.780894927 +0200 +@@ -468,6 +468,7 @@ ssize_t vfs_read(struct file *file, char + + return ret; + } ++EXPORT_SYMBOL_GPL(vfs_read); + + static ssize_t new_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos) + { +@@ -508,6 +509,7 @@ vfs_readf_t vfs_readf(struct file *file) + return new_sync_read; + return ERR_PTR(-ENOSYS); + } ++EXPORT_SYMBOL_GPL(vfs_readf); + + vfs_writef_t vfs_writef(struct file *file) + { +@@ -519,6 +521,7 @@ vfs_writef_t vfs_writef(struct file *fil + return new_sync_write; + return ERR_PTR(-ENOSYS); + } ++EXPORT_SYMBOL_GPL(vfs_writef); + + ssize_t __kernel_write(struct file *file, const void *buf, size_t count, loff_t *pos) + { +@@ -588,6 +591,7 @@ ssize_t vfs_write(struct file *file, con + + return ret; + } ++EXPORT_SYMBOL_GPL(vfs_write); + + /* file_ppos returns &file->f_pos or NULL if file is stream */ + static inline loff_t *file_ppos(struct file *file) +diff -Nurp linux-5.4-aufs/fs/splice.c linux-5.4-aufs-mod/fs/splice.c +--- linux-5.4-aufs/fs/splice.c 2019-11-28 01:25:59.071925617 +0200 ++++ linux-5.4-aufs-mod/fs/splice.c 2019-11-28 01:38:48.780894927 +0200 +@@ -847,6 +847,7 @@ long do_splice_from(struct pipe_inode_in + + return splice_write(pipe, out, ppos, len, flags); + } ++EXPORT_SYMBOL_GPL(do_splice_from); + + /* + * Attempt to initiate a splice from a file to a pipe. +@@ -876,6 +877,7 @@ long do_splice_to(struct file *in, loff_ + + return splice_read(in, ppos, pipe, len, flags); + } ++EXPORT_SYMBOL_GPL(do_splice_to); + + /** + * splice_direct_to_actor - splices data directly between two non-pipes +diff -Nurp linux-5.4-aufs/fs/sync.c linux-5.4-aufs-mod/fs/sync.c +--- linux-5.4-aufs/fs/sync.c 2019-11-28 01:25:59.071925617 +0200 ++++ linux-5.4-aufs-mod/fs/sync.c 2019-11-28 01:38:48.780894927 +0200 +@@ -39,6 +39,7 @@ int __sync_filesystem(struct super_block + sb->s_op->sync_fs(sb, wait); + return __sync_blockdev(sb->s_bdev, wait); + } ++EXPORT_SYMBOL_GPL(__sync_filesystem); + + /* + * Write out and wait upon all dirty data associated with this +diff -Nurp linux-5.4-aufs/fs/xattr.c linux-5.4-aufs-mod/fs/xattr.c +--- linux-5.4-aufs/fs/xattr.c 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs-mod/fs/xattr.c 2019-11-28 01:38:48.780894927 +0200 +@@ -296,6 +296,7 @@ vfs_getxattr_alloc(struct dentry *dentry + *xattr_value = value; + return error; + } ++EXPORT_SYMBOL_GPL(vfs_getxattr_alloc); + + ssize_t + __vfs_getxattr(struct dentry *dentry, struct inode *inode, const char *name, +diff -Nurp linux-5.4-aufs/kernel/locking/lockdep.c linux-5.4-aufs-mod/kernel/locking/lockdep.c +--- linux-5.4-aufs/kernel/locking/lockdep.c 2019-11-28 01:25:59.072925617 +0200 ++++ linux-5.4-aufs-mod/kernel/locking/lockdep.c 2019-11-28 01:38:48.780894927 +0200 +@@ -174,6 +174,7 @@ inline struct lock_class *lockdep_hlock_ + */ + return lock_classes + class_idx; + } ++EXPORT_SYMBOL_GPL(lockdep_hlock_class); + #define hlock_class(hlock) lockdep_hlock_class(hlock) + + #ifdef CONFIG_LOCK_STAT +diff -Nurp linux-5.4-aufs/kernel/task_work.c linux-5.4-aufs-mod/kernel/task_work.c +--- linux-5.4-aufs/kernel/task_work.c 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs-mod/kernel/task_work.c 2019-11-28 01:38:48.786894927 +0200 +@@ -116,3 +116,4 @@ void task_work_run(void) + } while (work); + } + } ++EXPORT_SYMBOL_GPL(task_work_run); +diff -Nurp linux-5.4-aufs/security/device_cgroup.c linux-5.4-aufs-mod/security/device_cgroup.c +--- linux-5.4-aufs/security/device_cgroup.c 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs-mod/security/device_cgroup.c 2019-11-28 01:38:48.790894927 +0200 +@@ -824,3 +824,4 @@ int __devcgroup_check_permission(short t + + return 0; + } ++EXPORT_SYMBOL_GPL(__devcgroup_check_permission); +diff -Nurp linux-5.4-aufs/security/security.c linux-5.4-aufs-mod/security/security.c +--- linux-5.4-aufs/security/security.c 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs-mod/security/security.c 2019-11-28 01:38:48.794894926 +0200 +@@ -1036,6 +1036,7 @@ int security_path_rmdir(const struct pat + return 0; + return call_int_hook(path_rmdir, 0, dir, dentry); + } ++EXPORT_SYMBOL_GPL(security_path_rmdir); + + int security_path_unlink(const struct path *dir, struct dentry *dentry) + { +@@ -1052,6 +1053,7 @@ int security_path_symlink(const struct p + return 0; + return call_int_hook(path_symlink, 0, dir, dentry, old_name); + } ++EXPORT_SYMBOL_GPL(security_path_symlink); + + int security_path_link(struct dentry *old_dentry, const struct path *new_dir, + struct dentry *new_dentry) +@@ -1060,6 +1062,7 @@ int security_path_link(struct dentry *ol + return 0; + return call_int_hook(path_link, 0, old_dentry, new_dir, new_dentry); + } ++EXPORT_SYMBOL_GPL(security_path_link); + + int security_path_rename(const struct path *old_dir, struct dentry *old_dentry, + const struct path *new_dir, struct dentry *new_dentry, +@@ -1087,6 +1090,7 @@ int security_path_truncate(const struct + return 0; + return call_int_hook(path_truncate, 0, path); + } ++EXPORT_SYMBOL_GPL(security_path_truncate); + + int security_path_chmod(const struct path *path, umode_t mode) + { +@@ -1094,6 +1098,7 @@ int security_path_chmod(const struct pat + return 0; + return call_int_hook(path_chmod, 0, path, mode); + } ++EXPORT_SYMBOL_GPL(security_path_chmod); + + int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid) + { +@@ -1101,6 +1106,7 @@ int security_path_chown(const struct pat + return 0; + return call_int_hook(path_chown, 0, path, uid, gid); + } ++EXPORT_SYMBOL_GPL(security_path_chown); + + int security_path_chroot(const struct path *path) + { +@@ -1201,6 +1207,7 @@ int security_inode_permission(struct ino + return 0; + return call_int_hook(inode_permission, 0, inode, mask); + } ++EXPORT_SYMBOL_GPL(security_inode_permission); + + int security_inode_setattr(struct dentry *dentry, struct iattr *attr) + { +@@ -1378,6 +1385,7 @@ int security_file_permission(struct file + + return fsnotify_perm(file, mask); + } ++EXPORT_SYMBOL_GPL(security_file_permission); + + int security_file_alloc(struct file *file) + { diff --git a/kernel/kernel/files/patches/mageia/fs-aufs-5.4-version.patch b/kernel/kernel/files/patches/mageia/fs-aufs-5.4-version.patch new file mode 100755 index 00000000..85c71bf3 --- /dev/null +++ b/kernel/kernel/files/patches/mageia/fs-aufs-5.4-version.patch @@ -0,0 +1,12 @@ +diff -Nurp linux-5.3-aufs/include/uapi/linux/aufs_type.h linux-5.3-aufs-ver/include/uapi/linux/aufs_type.h +--- linux-5.3-aufs/include/uapi/linux/aufs_type.h 2019-09-24 16:13:44.012259519 +0300 ++++ linux-5.3-aufs-ver/include/uapi/linux/aufs_type.h 2019-09-24 20:04:21.924707762 +0300 +@@ -27,7 +27,7 @@ + + #include + +-#define AUFS_VERSION "5.x-rcN" ++#define AUFS_VERSION "5.4" + + /* todo? move this to linux-2.6.19/include/magic.h */ + #define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's') diff --git a/kernel/kernel/files/patches/mageia/fs-aufs-5.4.patch b/kernel/kernel/files/patches/mageia/fs-aufs-5.4.patch new file mode 100644 index 00000000..0f717dbf --- /dev/null +++ b/kernel/kernel/files/patches/mageia/fs-aufs-5.4.patch @@ -0,0 +1,37876 @@ + + Documentation/ABI/testing/debugfs-aufs | 55 + Documentation/ABI/testing/sysfs-aufs | 31 + Documentation/filesystems/aufs/README | 399 +++ + Documentation/filesystems/aufs/design/01intro.txt | 158 + + Documentation/filesystems/aufs/design/02struct.txt | 245 ++ + Documentation/filesystems/aufs/design/03atomic_open.txt | 72 + Documentation/filesystems/aufs/design/03lookup.txt | 100 + Documentation/filesystems/aufs/design/04branch.txt | 61 + Documentation/filesystems/aufs/design/05wbr_policy.txt | 51 + Documentation/filesystems/aufs/design/06dirren.dot | 31 + Documentation/filesystems/aufs/design/06dirren.txt | 89 + Documentation/filesystems/aufs/design/06fhsm.txt | 105 + Documentation/filesystems/aufs/design/06mmap.txt | 59 + Documentation/filesystems/aufs/design/06xattr.txt | 81 + Documentation/filesystems/aufs/design/07export.txt | 45 + Documentation/filesystems/aufs/design/08shwh.txt | 39 + Documentation/filesystems/aufs/design/10dynop.txt | 34 + MAINTAINERS | 13 + drivers/block/loop.c | 18 + fs/Kconfig | 1 + fs/Makefile | 1 + fs/aufs/Kconfig | 199 + + fs/aufs/Makefile | 39 + fs/aufs/aufs.h | 49 + fs/aufs/branch.c | 1415 +++++++++++ + fs/aufs/branch.h | 353 ++ + fs/aufs/cpup.c | 1445 +++++++++++ + fs/aufs/cpup.h | 87 + fs/aufs/dbgaufs.c | 513 ++++ + fs/aufs/dbgaufs.h | 40 + fs/aufs/dcsub.c | 212 + + fs/aufs/dcsub.h | 124 + + fs/aufs/debug.c | 428 +++ + fs/aufs/debug.h | 213 + + fs/aufs/dentry.c | 1141 +++++++++ + fs/aufs/dentry.h | 255 ++ + fs/aufs/dinfo.c | 541 ++++ + fs/aufs/dir.c | 750 ++++++ + fs/aufs/dir.h | 121 + fs/aufs/dirren.c | 1303 ++++++++++ + fs/aufs/dirren.h | 127 + + fs/aufs/dynop.c | 354 ++ + fs/aufs/dynop.h | 64 + fs/aufs/export.c | 825 ++++++ + fs/aufs/f_op.c | 806 ++++++ + fs/aufs/fhsm.c | 413 +++ + fs/aufs/file.c | 850 ++++++ + fs/aufs/file.h | 329 ++ + fs/aufs/finfo.c | 136 + + fs/aufs/fstype.h | 388 +++ + fs/aufs/hbl.h | 52 + fs/aufs/hfsnotify.c | 275 ++ + fs/aufs/hfsplus.c | 47 + fs/aufs/hnotify.c | 708 +++++ + fs/aufs/i_op.c | 1492 ++++++++++++ + fs/aufs/i_op_add.c | 923 +++++++ + fs/aufs/i_op_del.c | 500 ++++ + fs/aufs/i_op_ren.c | 1237 ++++++++++ + fs/aufs/iinfo.c | 273 ++ + fs/aufs/inode.c | 516 ++++ + fs/aufs/inode.h | 685 +++++ + fs/aufs/ioctl.c | 207 + + fs/aufs/lcnt.h | 173 + + fs/aufs/loop.c | 135 + + fs/aufs/loop.h | 42 + fs/aufs/magic.mk | 31 + fs/aufs/module.c | 259 ++ + fs/aufs/module.h | 153 + + fs/aufs/mvdown.c | 693 +++++ + fs/aufs/opts.c | 1867 +++++++++++++++ + fs/aufs/opts.h | 212 + + fs/aufs/plink.c | 503 ++++ + fs/aufs/poll.c | 38 + fs/aufs/posix_acl.c | 92 + fs/aufs/procfs.c | 158 + + fs/aufs/rdu.c | 371 +++ + fs/aufs/rwsem.h | 60 + fs/aufs/sbinfo.c | 301 ++ + fs/aufs/super.c | 1034 ++++++++ + fs/aufs/super.h | 576 ++++ + fs/aufs/sysaufs.c | 80 + fs/aufs/sysaufs.h | 89 + fs/aufs/sysfs.c | 338 ++ + fs/aufs/sysrq.c | 147 + + fs/aufs/vdir.c | 883 +++++++ + fs/aufs/vfsub.c | 889 +++++++ + fs/aufs/vfsub.h | 341 ++ + fs/aufs/wbr_policy.c | 817 ++++++ + fs/aufs/whout.c | 1049 ++++++++ + fs/aufs/whout.h | 73 + fs/aufs/wkq.c | 379 +++ + fs/aufs/wkq.h | 76 + fs/aufs/xattr.c | 343 ++ + fs/aufs/xino.c | 1952 ++++++++++++++++ + fs/dcache.c | 2 + fs/fcntl.c | 4 + fs/inode.c | 2 + fs/namespace.c | 6 + fs/proc/base.c | 2 + fs/proc/nommu.c | 5 + fs/proc/task_mmu.c | 7 + fs/proc/task_nommu.c | 5 + fs/read_write.c | 22 + fs/splice.c | 10 + fs/sync.c | 2 + include/linux/fs.h | 10 + include/linux/lockdep.h | 3 + include/linux/mm.h | 22 + include/linux/mm_types.h | 2 + include/linux/mnt_namespace.h | 3 + include/linux/splice.h | 6 + include/uapi/linux/aufs_type.h | 439 +++ + kernel/fork.c | 2 + kernel/locking/lockdep.c | 3 + mm/Makefile | 2 + mm/filemap.c | 2 + mm/mmap.c | 33 + mm/nommu.c | 10 + mm/prfile.c | 86 + 119 files changed, 36936 insertions(+), 31 deletions(-) + +diff -Nurp linux-5.4/Documentation/ABI/testing/debugfs-aufs linux-5.4-aufs/Documentation/ABI/testing/debugfs-aufs +--- linux-5.4/Documentation/ABI/testing/debugfs-aufs 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/Documentation/ABI/testing/debugfs-aufs 2019-11-28 01:25:59.060925618 +0200 +@@ -0,0 +1,55 @@ ++What: /debug/aufs/si_/ ++Date: March 2009 ++Contact: J. R. Okajima ++Description: ++ Under /debug/aufs, a directory named si_ is created ++ per aufs mount, where is a unique id generated ++ internally. ++ ++What: /debug/aufs/si_/plink ++Date: Apr 2013 ++Contact: J. R. Okajima ++Description: ++ It has three lines and shows the information about the ++ pseudo-link. The first line is a single number ++ representing a number of buckets. The second line is a ++ number of pseudo-links per buckets (separated by a ++ blank). The last line is a single number representing a ++ total number of psedo-links. ++ When the aufs mount option 'noplink' is specified, it ++ will show "1\n0\n0\n". ++ ++What: /debug/aufs/si_/xib ++Date: March 2009 ++Contact: J. R. Okajima ++Description: ++ It shows the consumed blocks by xib (External Inode Number ++ Bitmap), its block size and file size. ++ When the aufs mount option 'noxino' is specified, it ++ will be empty. About XINO files, see the aufs manual. ++ ++What: /debug/aufs/si_/xi0, xi1 ... xiN and xiN-N ++Date: March 2009 ++Contact: J. R. Okajima ++Description: ++ It shows the consumed blocks by xino (External Inode Number ++ Translation Table), its link count, block size and file ++ size. ++ Due to the file size limit, there may exist multiple ++ xino files per branch. In this case, "-N" is added to ++ the filename and it corresponds to the index of the ++ internal xino array. "-0" is omitted. ++ When the aufs mount option 'noxino' is specified, Those ++ entries won't exist. About XINO files, see the aufs ++ manual. ++ ++What: /debug/aufs/si_/xigen ++Date: March 2009 ++Contact: J. R. Okajima ++Description: ++ It shows the consumed blocks by xigen (External Inode ++ Generation Table), its block size and file size. ++ If CONFIG_AUFS_EXPORT is disabled, this entry will not ++ be created. ++ When the aufs mount option 'noxino' is specified, it ++ will be empty. About XINO files, see the aufs manual. +diff -Nurp linux-5.4/Documentation/ABI/testing/sysfs-aufs linux-5.4-aufs/Documentation/ABI/testing/sysfs-aufs +--- linux-5.4/Documentation/ABI/testing/sysfs-aufs 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/Documentation/ABI/testing/sysfs-aufs 2019-11-28 01:25:59.060925618 +0200 +@@ -0,0 +1,31 @@ ++What: /sys/fs/aufs/si_/ ++Date: March 2009 ++Contact: J. R. Okajima ++Description: ++ Under /sys/fs/aufs, a directory named si_ is created ++ per aufs mount, where is a unique id generated ++ internally. ++ ++What: /sys/fs/aufs/si_/br0, br1 ... brN ++Date: March 2009 ++Contact: J. R. Okajima ++Description: ++ It shows the abolute path of a member directory (which ++ is called branch) in aufs, and its permission. ++ ++What: /sys/fs/aufs/si_/brid0, brid1 ... bridN ++Date: July 2013 ++Contact: J. R. Okajima ++Description: ++ It shows the id of a member directory (which is called ++ branch) in aufs. ++ ++What: /sys/fs/aufs/si_/xi_path ++Date: March 2009 ++Contact: J. R. Okajima ++Description: ++ It shows the abolute path of XINO (External Inode Number ++ Bitmap, Translation Table and Generation Table) file ++ even if it is the default path. ++ When the aufs mount option 'noxino' is specified, it ++ will be empty. About XINO files, see the aufs manual. +diff -Nurp linux-5.4/Documentation/filesystems/aufs/design/01intro.txt linux-5.4-aufs/Documentation/filesystems/aufs/design/01intro.txt +--- linux-5.4/Documentation/filesystems/aufs/design/01intro.txt 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/Documentation/filesystems/aufs/design/01intro.txt 2019-11-28 01:25:59.060925618 +0200 +@@ -0,0 +1,158 @@ ++ ++# Copyright (C) 2005-2019 Junjiro R. Okajima ++ ++Introduction ++---------------------------------------- ++ ++aufs [ei ju: ef es] | /ey-yoo-ef-es/ | [a u f s] ++1. abbrev. for "advanced multi-layered unification filesystem". ++2. abbrev. for "another unionfs". ++3. abbrev. for "auf das" in German which means "on the" in English. ++ Ex. "Butter aufs Brot"(G) means "butter onto bread"(E). ++ But "Filesystem aufs Filesystem" is hard to understand. ++4. abbrev. for "African Urban Fashion Show". ++ ++AUFS is a filesystem with features: ++- multi layered stackable unification filesystem, the member directory ++ is called as a branch. ++- branch permission and attribute, 'readonly', 'real-readonly', ++ 'readwrite', 'whiteout-able', 'link-able whiteout', etc. and their ++ combination. ++- internal "file copy-on-write". ++- logical deletion, whiteout. ++- dynamic branch manipulation, adding, deleting and changing permission. ++- allow bypassing aufs, user's direct branch access. ++- external inode number translation table and bitmap which maintains the ++ persistent aufs inode number. ++- seekable directory, including NFS readdir. ++- file mapping, mmap and sharing pages. ++- pseudo-link, hardlink over branches. ++- loopback mounted filesystem as a branch. ++- several policies to select one among multiple writable branches. ++- revert a single systemcall when an error occurs in aufs. ++- and more... ++ ++ ++Multi Layered Stackable Unification Filesystem ++---------------------------------------------------------------------- ++Most people already knows what it is. ++It is a filesystem which unifies several directories and provides a ++merged single directory. When users access a file, the access will be ++passed/re-directed/converted (sorry, I am not sure which English word is ++correct) to the real file on the member filesystem. The member ++filesystem is called 'lower filesystem' or 'branch' and has a mode ++'readonly' and 'readwrite.' And the deletion for a file on the lower ++readonly branch is handled by creating 'whiteout' on the upper writable ++branch. ++ ++On LKML, there have been discussions about UnionMount (Jan Blunck, ++Bharata B Rao and Valerie Aurora) and Unionfs (Erez Zadok). They took ++different approaches to implement the merged-view. ++The former tries putting it into VFS, and the latter implements as a ++separate filesystem. ++(If I misunderstand about these implementations, please let me know and ++I shall correct it. Because it is a long time ago when I read their ++source files last time). ++ ++UnionMount's approach will be able to small, but may be hard to share ++branches between several UnionMount since the whiteout in it is ++implemented in the inode on branch filesystem and always ++shared. According to Bharata's post, readdir does not seems to be ++finished yet. ++There are several missing features known in this implementations such as ++- for users, the inode number may change silently. eg. copy-up. ++- link(2) may break by copy-up. ++- read(2) may get an obsoleted filedata (fstat(2) too). ++- fcntl(F_SETLK) may be broken by copy-up. ++- unnecessary copy-up may happen, for example mmap(MAP_PRIVATE) after ++ open(O_RDWR). ++ ++In linux-3.18, "overlay" filesystem (formerly known as "overlayfs") was ++merged into mainline. This is another implementation of UnionMount as a ++separated filesystem. All the limitations and known problems which ++UnionMount are equally inherited to "overlay" filesystem. ++ ++Unionfs has a longer history. When I started implementing a stackable ++filesystem (Aug 2005), it already existed. It has virtual super_block, ++inode, dentry and file objects and they have an array pointing lower ++same kind objects. After contributing many patches for Unionfs, I ++re-started my project AUFS (Jun 2006). ++ ++In AUFS, the structure of filesystem resembles to Unionfs, but I ++implemented my own ideas, approaches and enhancements and it became ++totally different one. ++ ++Comparing DM snapshot and fs based implementation ++- the number of bytes to be copied between devices is much smaller. ++- the type of filesystem must be one and only. ++- the fs must be writable, no readonly fs, even for the lower original ++ device. so the compression fs will not be usable. but if we use ++ loopback mount, we may address this issue. ++ for instance, ++ mount /cdrom/squashfs.img /sq ++ losetup /sq/ext2.img ++ losetup /somewhere/cow ++ dmsetup "snapshot /dev/loop0 /dev/loop1 ..." ++- it will be difficult (or needs more operations) to extract the ++ difference between the original device and COW. ++- DM snapshot-merge may help a lot when users try merging. in the ++ fs-layer union, users will use rsync(1). ++ ++You may want to read my old paper "Filesystems in LiveCD" ++(http://aufs.sourceforge.net/aufs2/report/sq/sq.pdf). ++ ++ ++Several characters/aspects/persona of aufs ++---------------------------------------------------------------------- ++ ++Aufs has several characters, aspects or persona. ++1. a filesystem, callee of VFS helper ++2. sub-VFS, caller of VFS helper for branches ++3. a virtual filesystem which maintains persistent inode number ++4. reader/writer of files on branches such like an application ++ ++1. Callee of VFS Helper ++As an ordinary linux filesystem, aufs is a callee of VFS. For instance, ++unlink(2) from an application reaches sys_unlink() kernel function and ++then vfs_unlink() is called. vfs_unlink() is one of VFS helper and it ++calls filesystem specific unlink operation. Actually aufs implements the ++unlink operation but it behaves like a redirector. ++ ++2. Caller of VFS Helper for Branches ++aufs_unlink() passes the unlink request to the branch filesystem as if ++it were called from VFS. So the called unlink operation of the branch ++filesystem acts as usual. As a caller of VFS helper, aufs should handle ++every necessary pre/post operation for the branch filesystem. ++- acquire the lock for the parent dir on a branch ++- lookup in a branch ++- revalidate dentry on a branch ++- mnt_want_write() for a branch ++- vfs_unlink() for a branch ++- mnt_drop_write() for a branch ++- release the lock on a branch ++ ++3. Persistent Inode Number ++One of the most important issue for a filesystem is to maintain inode ++numbers. This is particularly important to support exporting a ++filesystem via NFS. Aufs is a virtual filesystem which doesn't have a ++backend block device for its own. But some storage is necessary to ++keep and maintain the inode numbers. It may be a large space and may not ++suit to keep in memory. Aufs rents some space from its first writable ++branch filesystem (by default) and creates file(s) on it. These files ++are created by aufs internally and removed soon (currently) keeping ++opened. ++Note: Because these files are removed, they are totally gone after ++ unmounting aufs. It means the inode numbers are not persistent ++ across unmount or reboot. I have a plan to make them really ++ persistent which will be important for aufs on NFS server. ++ ++4. Read/Write Files Internally (copy-on-write) ++Because a branch can be readonly, when you write a file on it, aufs will ++"copy-up" it to the upper writable branch internally. And then write the ++originally requested thing to the file. Generally kernel doesn't ++open/read/write file actively. In aufs, even a single write may cause a ++internal "file copy". This behaviour is very similar to cp(1) command. ++ ++Some people may think it is better to pass such work to user space ++helper, instead of doing in kernel space. Actually I am still thinking ++about it. But currently I have implemented it in kernel space. +diff -Nurp linux-5.4/Documentation/filesystems/aufs/design/02struct.txt linux-5.4-aufs/Documentation/filesystems/aufs/design/02struct.txt +--- linux-5.4/Documentation/filesystems/aufs/design/02struct.txt 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/Documentation/filesystems/aufs/design/02struct.txt 2019-11-28 01:25:59.060925618 +0200 +@@ -0,0 +1,245 @@ ++ ++# Copyright (C) 2005-2019 Junjiro R. Okajima ++ ++Basic Aufs Internal Structure ++ ++Superblock/Inode/Dentry/File Objects ++---------------------------------------------------------------------- ++As like an ordinary filesystem, aufs has its own ++superblock/inode/dentry/file objects. All these objects have a ++dynamically allocated array and store the same kind of pointers to the ++lower filesystem, branch. ++For example, when you build a union with one readwrite branch and one ++readonly, mounted /au, /rw and /ro respectively. ++- /au = /rw + /ro ++- /ro/fileA exists but /rw/fileA ++ ++Aufs lookup operation finds /ro/fileA and gets dentry for that. These ++pointers are stored in a aufs dentry. The array in aufs dentry will be, ++- [0] = NULL (because /rw/fileA doesn't exist) ++- [1] = /ro/fileA ++ ++This style of an array is essentially same to the aufs ++superblock/inode/dentry/file objects. ++ ++Because aufs supports manipulating branches, ie. add/delete/change ++branches dynamically, these objects has its own generation. When ++branches are changed, the generation in aufs superblock is ++incremented. And a generation in other object are compared when it is ++accessed. When a generation in other objects are obsoleted, aufs ++refreshes the internal array. ++ ++ ++Superblock ++---------------------------------------------------------------------- ++Additionally aufs superblock has some data for policies to select one ++among multiple writable branches, XIB files, pseudo-links and kobject. ++See below in detail. ++About the policies which supports copy-down a directory, see ++wbr_policy.txt too. ++ ++ ++Branch and XINO(External Inode Number Translation Table) ++---------------------------------------------------------------------- ++Every branch has its own xino (external inode number translation table) ++file. The xino file is created and unlinked by aufs internally. When two ++members of a union exist on the same filesystem, they share the single ++xino file. ++The struct of a xino file is simple, just a sequence of aufs inode ++numbers which is indexed by the lower inode number. ++In the above sample, assume the inode number of /ro/fileA is i111 and ++aufs assigns the inode number i999 for fileA. Then aufs writes 999 as ++4(8) bytes at 111 * 4(8) bytes offset in the xino file. ++ ++When the inode numbers are not contiguous, the xino file will be sparse ++which has a hole in it and doesn't consume as much disk space as it ++might appear. If your branch filesystem consumes disk space for such ++holes, then you should specify 'xino=' option at mounting aufs. ++ ++Aufs has a mount option to free the disk blocks for such holes in XINO ++files on tmpfs or ramdisk. But it is not so effective actually. If you ++meet a problem of disk shortage due to XINO files, then you should try ++"tmpfs-ino.patch" (and "vfs-ino.patch" too) in aufs4-standalone.git. ++The patch localizes the assignment inumbers per tmpfs-mount and avoid ++the holes in XINO files. ++ ++Also a writable branch has three kinds of "whiteout bases". All these ++are existed when the branch is joined to aufs, and their names are ++whiteout-ed doubly, so that users will never see their names in aufs ++hierarchy. ++1. a regular file which will be hardlinked to all whiteouts. ++2. a directory to store a pseudo-link. ++3. a directory to store an "orphan"-ed file temporary. ++ ++1. Whiteout Base ++ When you remove a file on a readonly branch, aufs handles it as a ++ logical deletion and creates a whiteout on the upper writable branch ++ as a hardlink of this file in order not to consume inode on the ++ writable branch. ++2. Pseudo-link Dir ++ See below, Pseudo-link. ++3. Step-Parent Dir ++ When "fileC" exists on the lower readonly branch only and it is ++ opened and removed with its parent dir, and then user writes ++ something into it, then aufs copies-up fileC to this ++ directory. Because there is no other dir to store fileC. After ++ creating a file under this dir, the file is unlinked. ++ ++Because aufs supports manipulating branches, ie. add/delete/change ++dynamically, a branch has its own id. When the branch order changes, ++aufs finds the new index by searching the branch id. ++ ++ ++Pseudo-link ++---------------------------------------------------------------------- ++Assume "fileA" exists on the lower readonly branch only and it is ++hardlinked to "fileB" on the branch. When you write something to fileA, ++aufs copies-up it to the upper writable branch. Additionally aufs ++creates a hardlink under the Pseudo-link Directory of the writable ++branch. The inode of a pseudo-link is kept in aufs super_block as a ++simple list. If fileB is read after unlinking fileA, aufs returns ++filedata from the pseudo-link instead of the lower readonly ++branch. Because the pseudo-link is based upon the inode, to keep the ++inode number by xino (see above) is essentially necessary. ++ ++All the hardlinks under the Pseudo-link Directory of the writable branch ++should be restored in a proper location later. Aufs provides a utility ++to do this. The userspace helpers executed at remounting and unmounting ++aufs by default. ++During this utility is running, it puts aufs into the pseudo-link ++maintenance mode. In this mode, only the process which began the ++maintenance mode (and its child processes) is allowed to operate in ++aufs. Some other processes which are not related to the pseudo-link will ++be allowed to run too, but the rest have to return an error or wait ++until the maintenance mode ends. If a process already acquires an inode ++mutex (in VFS), it has to return an error. ++ ++ ++XIB(external inode number bitmap) ++---------------------------------------------------------------------- ++Addition to the xino file per a branch, aufs has an external inode number ++bitmap in a superblock object. It is also an internal file such like a ++xino file. ++It is a simple bitmap to mark whether the aufs inode number is in-use or ++not. ++To reduce the file I/O, aufs prepares a single memory page to cache xib. ++ ++As well as XINO files, aufs has a feature to truncate/refresh XIB to ++reduce the number of consumed disk blocks for these files. ++ ++ ++Virtual or Vertical Dir, and Readdir in Userspace ++---------------------------------------------------------------------- ++In order to support multiple layers (branches), aufs readdir operation ++constructs a virtual dir block on memory. For readdir, aufs calls ++vfs_readdir() internally for each dir on branches, merges their entries ++with eliminating the whiteout-ed ones, and sets it to file (dir) ++object. So the file object has its entry list until it is closed. The ++entry list will be updated when the file position is zero and becomes ++obsoleted. This decision is made in aufs automatically. ++ ++The dynamically allocated memory block for the name of entries has a ++unit of 512 bytes (by default) and stores the names contiguously (no ++padding). Another block for each entry is handled by kmem_cache too. ++During building dir blocks, aufs creates hash list and judging whether ++the entry is whiteouted by its upper branch or already listed. ++The merged result is cached in the corresponding inode object and ++maintained by a customizable life-time option. ++ ++Some people may call it can be a security hole or invite DoS attack ++since the opened and once readdir-ed dir (file object) holds its entry ++list and becomes a pressure for system memory. But I'd say it is similar ++to files under /proc or /sys. The virtual files in them also holds a ++memory page (generally) while they are opened. When an idea to reduce ++memory for them is introduced, it will be applied to aufs too. ++For those who really hate this situation, I've developed readdir(3) ++library which operates this merging in userspace. You just need to set ++LD_PRELOAD environment variable, and aufs will not consume no memory in ++kernel space for readdir(3). ++ ++ ++Workqueue ++---------------------------------------------------------------------- ++Aufs sometimes requires privilege access to a branch. For instance, ++in copy-up/down operation. When a user process is going to make changes ++to a file which exists in the lower readonly branch only, and the mode ++of one of ancestor directories may not be writable by a user ++process. Here aufs copy-up the file with its ancestors and they may ++require privilege to set its owner/group/mode/etc. ++This is a typical case of a application character of aufs (see ++Introduction). ++ ++Aufs uses workqueue synchronously for this case. It creates its own ++workqueue. The workqueue is a kernel thread and has privilege. Aufs ++passes the request to call mkdir or write (for example), and wait for ++its completion. This approach solves a problem of a signal handler ++simply. ++If aufs didn't adopt the workqueue and changed the privilege of the ++process, then the process may receive the unexpected SIGXFSZ or other ++signals. ++ ++Also aufs uses the system global workqueue ("events" kernel thread) too ++for asynchronous tasks, such like handling inotify/fsnotify, re-creating a ++whiteout base and etc. This is unrelated to a privilege. ++Most of aufs operation tries acquiring a rw_semaphore for aufs ++superblock at the beginning, at the same time waits for the completion ++of all queued asynchronous tasks. ++ ++ ++Whiteout ++---------------------------------------------------------------------- ++The whiteout in aufs is very similar to Unionfs's. That is represented ++by its filename. UnionMount takes an approach of a file mode, but I am ++afraid several utilities (find(1) or something) will have to support it. ++ ++Basically the whiteout represents "logical deletion" which stops aufs to ++lookup further, but also it represents "dir is opaque" which also stop ++further lookup. ++ ++In aufs, rmdir(2) and rename(2) for dir uses whiteout alternatively. ++In order to make several functions in a single systemcall to be ++revertible, aufs adopts an approach to rename a directory to a temporary ++unique whiteouted name. ++For example, in rename(2) dir where the target dir already existed, aufs ++renames the target dir to a temporary unique whiteouted name before the ++actual rename on a branch, and then handles other actions (make it opaque, ++update the attributes, etc). If an error happens in these actions, aufs ++simply renames the whiteouted name back and returns an error. If all are ++succeeded, aufs registers a function to remove the whiteouted unique ++temporary name completely and asynchronously to the system global ++workqueue. ++ ++ ++Copy-up ++---------------------------------------------------------------------- ++It is a well-known feature or concept. ++When user modifies a file on a readonly branch, aufs operate "copy-up" ++internally and makes change to the new file on the upper writable branch. ++When the trigger systemcall does not update the timestamps of the parent ++dir, aufs reverts it after copy-up. ++ ++ ++Move-down (aufs3.9 and later) ++---------------------------------------------------------------------- ++"Copy-up" is one of the essential feature in aufs. It copies a file from ++the lower readonly branch to the upper writable branch when a user ++changes something about the file. ++"Move-down" is an opposite action of copy-up. Basically this action is ++ran manually instead of automatically and internally. ++For desgin and implementation, aufs has to consider these issues. ++- whiteout for the file may exist on the lower branch. ++- ancestor directories may not exist on the lower branch. ++- diropq for the ancestor directories may exist on the upper branch. ++- free space on the lower branch will reduce. ++- another access to the file may happen during moving-down, including ++ UDBA (see "Revalidate Dentry and UDBA"). ++- the file should not be hard-linked nor pseudo-linked. they should be ++ handled by auplink utility later. ++ ++Sometimes users want to move-down a file from the upper writable branch ++to the lower readonly or writable branch. For instance, ++- the free space of the upper writable branch is going to run out. ++- create a new intermediate branch between the upper and lower branch. ++- etc. ++ ++For this purpose, use "aumvdown" command in aufs-util.git. +diff -Nurp linux-5.4/Documentation/filesystems/aufs/design/03atomic_open.txt linux-5.4-aufs/Documentation/filesystems/aufs/design/03atomic_open.txt +--- linux-5.4/Documentation/filesystems/aufs/design/03atomic_open.txt 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/Documentation/filesystems/aufs/design/03atomic_open.txt 2019-11-28 01:25:59.060925618 +0200 +@@ -0,0 +1,72 @@ ++ ++# Copyright (C) 2015-2019 Junjiro R. Okajima ++ ++Support for a branch who has its ->atomic_open() ++---------------------------------------------------------------------- ++The filesystems who implement its ->atomic_open() are not majority. For ++example NFSv4 does, and aufs should call NFSv4 ->atomic_open, ++particularly for open(O_CREAT|O_EXCL, 0400) case. Other than ++->atomic_open(), NFSv4 returns an error for this open(2). While I am not ++sure whether all filesystems who have ->atomic_open() behave like this, ++but NFSv4 surely returns the error. ++ ++In order to support ->atomic_open() for aufs, there are a few ++approaches. ++ ++A. Introduce aufs_atomic_open() ++ - calls one of VFS:do_last(), lookup_open() or atomic_open() for ++ branch fs. ++B. Introduce aufs_atomic_open() calling create, open and chmod. this is ++ an aufs user Pip Cet's approach ++ - calls aufs_create(), VFS finish_open() and notify_change(). ++ - pass fake-mode to finish_open(), and then correct the mode by ++ notify_change(). ++C. Extend aufs_open() to call branch fs's ->atomic_open() ++ - no aufs_atomic_open(). ++ - aufs_lookup() registers the TID to an aufs internal object. ++ - aufs_create() does nothing when the matching TID is registered, but ++ registers the mode. ++ - aufs_open() calls branch fs's ->atomic_open() when the matching ++ TID is registered. ++D. Extend aufs_open() to re-try branch fs's ->open() with superuser's ++ credential ++ - no aufs_atomic_open(). ++ - aufs_create() registers the TID to an internal object. this info ++ represents "this process created this file just now." ++ - when aufs gets EACCES from branch fs's ->open(), then confirm the ++ registered TID and re-try open() with superuser's credential. ++ ++Pros and cons for each approach. ++ ++A. ++ - straightforward but highly depends upon VFS internal. ++ - the atomic behavaiour is kept. ++ - some of parameters such as nameidata are hard to reproduce for ++ branch fs. ++ - large overhead. ++B. ++ - easy to implement. ++ - the atomic behavaiour is lost. ++C. ++ - the atomic behavaiour is kept. ++ - dirty and tricky. ++ - VFS checks whether the file is created correctly after calling ++ ->create(), which means this approach doesn't work. ++D. ++ - easy to implement. ++ - the atomic behavaiour is lost. ++ - to open a file with superuser's credential and give it to a user ++ process is a bad idea, since the file object keeps the credential ++ in it. It may affect LSM or something. This approach doesn't work ++ either. ++ ++The approach A is ideal, but it hard to implement. So here is a ++variation of A, which is to be implemented. ++ ++A-1. Introduce aufs_atomic_open() ++ - calls branch fs ->atomic_open() if exists. otherwise calls ++ vfs_create() and finish_open(). ++ - the demerit is that the several checks after branch fs ++ ->atomic_open() are lost. in the ordinary case, the checks are ++ done by VFS:do_last(), lookup_open() and atomic_open(). some can ++ be implemented in aufs, but not all I am afraid. +diff -Nurp linux-5.4/Documentation/filesystems/aufs/design/03lookup.txt linux-5.4-aufs/Documentation/filesystems/aufs/design/03lookup.txt +--- linux-5.4/Documentation/filesystems/aufs/design/03lookup.txt 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/Documentation/filesystems/aufs/design/03lookup.txt 2019-11-28 01:25:59.060925618 +0200 +@@ -0,0 +1,100 @@ ++ ++# Copyright (C) 2005-2019 Junjiro R. Okajima ++ ++Lookup in a Branch ++---------------------------------------------------------------------- ++Since aufs has a character of sub-VFS (see Introduction), it operates ++lookup for branches as VFS does. It may be a heavy work. But almost all ++lookup operation in aufs is the simplest case, ie. lookup only an entry ++directly connected to its parent. Digging down the directory hierarchy ++is unnecessary. VFS has a function lookup_one_len() for that use, and ++aufs calls it. ++ ++When a branch is a remote filesystem, aufs basically relies upon its ++->d_revalidate(), also aufs forces the hardest revalidate tests for ++them. ++For d_revalidate, aufs implements three levels of revalidate tests. See ++"Revalidate Dentry and UDBA" in detail. ++ ++ ++Test Only the Highest One for the Directory Permission (dirperm1 option) ++---------------------------------------------------------------------- ++Let's try case study. ++- aufs has two branches, upper readwrite and lower readonly. ++ /au = /rw + /ro ++- "dirA" exists under /ro, but /rw. and its mode is 0700. ++- user invoked "chmod a+rx /au/dirA" ++- the internal copy-up is activated and "/rw/dirA" is created and its ++ permission bits are set to world readable. ++- then "/au/dirA" becomes world readable? ++ ++In this case, /ro/dirA is still 0700 since it exists in readonly branch, ++or it may be a natively readonly filesystem. If aufs respects the lower ++branch, it should not respond readdir request from other users. But user ++allowed it by chmod. Should really aufs rejects showing the entries ++under /ro/dirA? ++ ++To be honest, I don't have a good solution for this case. So aufs ++implements 'dirperm1' and 'nodirperm1' mount options, and leave it to ++users. ++When dirperm1 is specified, aufs checks only the highest one for the ++directory permission, and shows the entries. Otherwise, as usual, checks ++every dir existing on all branches and rejects the request. ++ ++As a side effect, dirperm1 option improves the performance of aufs ++because the number of permission check is reduced when the number of ++branch is many. ++ ++ ++Revalidate Dentry and UDBA (User's Direct Branch Access) ++---------------------------------------------------------------------- ++Generally VFS helpers re-validate a dentry as a part of lookup. ++0. digging down the directory hierarchy. ++1. lock the parent dir by its i_mutex. ++2. lookup the final (child) entry. ++3. revalidate it. ++4. call the actual operation (create, unlink, etc.) ++5. unlock the parent dir ++ ++If the filesystem implements its ->d_revalidate() (step 3), then it is ++called. Actually aufs implements it and checks the dentry on a branch is ++still valid. ++But it is not enough. Because aufs has to release the lock for the ++parent dir on a branch at the end of ->lookup() (step 2) and ++->d_revalidate() (step 3) while the i_mutex of the aufs dir is still ++held by VFS. ++If the file on a branch is changed directly, eg. bypassing aufs, after ++aufs released the lock, then the subsequent operation may cause ++something unpleasant result. ++ ++This situation is a result of VFS architecture, ->lookup() and ++->d_revalidate() is separated. But I never say it is wrong. It is a good ++design from VFS's point of view. It is just not suitable for sub-VFS ++character in aufs. ++ ++Aufs supports such case by three level of revalidation which is ++selectable by user. ++1. Simple Revalidate ++ Addition to the native flow in VFS's, confirm the child-parent ++ relationship on the branch just after locking the parent dir on the ++ branch in the "actual operation" (step 4). When this validation ++ fails, aufs returns EBUSY. ->d_revalidate() (step 3) in aufs still ++ checks the validation of the dentry on branches. ++2. Monitor Changes Internally by Inotify/Fsnotify ++ Addition to above, in the "actual operation" (step 4) aufs re-lookup ++ the dentry on the branch, and returns EBUSY if it finds different ++ dentry. ++ Additionally, aufs sets the inotify/fsnotify watch for every dir on branches ++ during it is in cache. When the event is notified, aufs registers a ++ function to kernel 'events' thread by schedule_work(). And the ++ function sets some special status to the cached aufs dentry and inode ++ private data. If they are not cached, then aufs has nothing to ++ do. When the same file is accessed through aufs (step 0-3) later, ++ aufs will detect the status and refresh all necessary data. ++ In this mode, aufs has to ignore the event which is fired by aufs ++ itself. ++3. No Extra Validation ++ This is the simplest test and doesn't add any additional revalidation ++ test, and skip the revalidation in step 4. It is useful and improves ++ aufs performance when system surely hide the aufs branches from user, ++ by over-mounting something (or another method). +diff -Nurp linux-5.4/Documentation/filesystems/aufs/design/04branch.txt linux-5.4-aufs/Documentation/filesystems/aufs/design/04branch.txt +--- linux-5.4/Documentation/filesystems/aufs/design/04branch.txt 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/Documentation/filesystems/aufs/design/04branch.txt 2019-11-28 01:25:59.060925618 +0200 +@@ -0,0 +1,61 @@ ++ ++# Copyright (C) 2005-2019 Junjiro R. Okajima ++ ++Branch Manipulation ++ ++Since aufs supports dynamic branch manipulation, ie. add/remove a branch ++and changing its permission/attribute, there are a lot of works to do. ++ ++ ++Add a Branch ++---------------------------------------------------------------------- ++o Confirm the adding dir exists outside of aufs, including loopback ++ mount, and its various attributes. ++o Initialize the xino file and whiteout bases if necessary. ++ See struct.txt. ++ ++o Check the owner/group/mode of the directory ++ When the owner/group/mode of the adding directory differs from the ++ existing branch, aufs issues a warning because it may impose a ++ security risk. ++ For example, when a upper writable branch has a world writable empty ++ top directory, a malicious user can create any files on the writable ++ branch directly, like copy-up and modify manually. If something like ++ /etc/{passwd,shadow} exists on the lower readonly branch but the upper ++ writable branch, and the writable branch is world-writable, then a ++ malicious guy may create /etc/passwd on the writable branch directly ++ and the infected file will be valid in aufs. ++ I am afraid it can be a security issue, but aufs can do nothing except ++ producing a warning. ++ ++ ++Delete a Branch ++---------------------------------------------------------------------- ++o Confirm the deleting branch is not busy ++ To be general, there is one merit to adopt "remount" interface to ++ manipulate branches. It is to discard caches. At deleting a branch, ++ aufs checks the still cached (and connected) dentries and inodes. If ++ there are any, then they are all in-use. An inode without its ++ corresponding dentry can be alive alone (for example, inotify/fsnotify case). ++ ++ For the cached one, aufs checks whether the same named entry exists on ++ other branches. ++ If the cached one is a directory, because aufs provides a merged view ++ to users, as long as one dir is left on any branch aufs can show the ++ dir to users. In this case, the branch can be removed from aufs. ++ Otherwise aufs rejects deleting the branch. ++ ++ If any file on the deleting branch is opened by aufs, then aufs ++ rejects deleting. ++ ++ ++Modify the Permission of a Branch ++---------------------------------------------------------------------- ++o Re-initialize or remove the xino file and whiteout bases if necessary. ++ See struct.txt. ++ ++o rw --> ro: Confirm the modifying branch is not busy ++ Aufs rejects the request if any of these conditions are true. ++ - a file on the branch is mmap-ed. ++ - a regular file on the branch is opened for write and there is no ++ same named entry on the upper branch. +diff -Nurp linux-5.4/Documentation/filesystems/aufs/design/05wbr_policy.txt linux-5.4-aufs/Documentation/filesystems/aufs/design/05wbr_policy.txt +--- linux-5.4/Documentation/filesystems/aufs/design/05wbr_policy.txt 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/Documentation/filesystems/aufs/design/05wbr_policy.txt 2019-11-28 01:25:59.060925618 +0200 +@@ -0,0 +1,51 @@ ++ ++# Copyright (C) 2005-2019 Junjiro R. Okajima ++ ++Policies to Select One among Multiple Writable Branches ++---------------------------------------------------------------------- ++When the number of writable branch is more than one, aufs has to decide ++the target branch for file creation or copy-up. By default, the highest ++writable branch which has the parent (or ancestor) dir of the target ++file is chosen (top-down-parent policy). ++By user's request, aufs implements some other policies to select the ++writable branch, for file creation several policies, round-robin, ++most-free-space, and other policies. For copy-up, top-down-parent, ++bottom-up-parent, bottom-up and others. ++ ++As expected, the round-robin policy selects the branch in circular. When ++you have two writable branches and creates 10 new files, 5 files will be ++created for each branch. mkdir(2) systemcall is an exception. When you ++create 10 new directories, all will be created on the same branch. ++And the most-free-space policy selects the one which has most free ++space among the writable branches. The amount of free space will be ++checked by aufs internally, and users can specify its time interval. ++ ++The policies for copy-up is more simple, ++top-down-parent is equivalent to the same named on in create policy, ++bottom-up-parent selects the writable branch where the parent dir ++exists and the nearest upper one from the copyup-source, ++bottom-up selects the nearest upper writable branch from the ++copyup-source, regardless the existence of the parent dir. ++ ++There are some rules or exceptions to apply these policies. ++- If there is a readonly branch above the policy-selected branch and ++ the parent dir is marked as opaque (a variation of whiteout), or the ++ target (creating) file is whiteout-ed on the upper readonly branch, ++ then the result of the policy is ignored and the target file will be ++ created on the nearest upper writable branch than the readonly branch. ++- If there is a writable branch above the policy-selected branch and ++ the parent dir is marked as opaque or the target file is whiteouted ++ on the branch, then the result of the policy is ignored and the target ++ file will be created on the highest one among the upper writable ++ branches who has diropq or whiteout. In case of whiteout, aufs removes ++ it as usual. ++- link(2) and rename(2) systemcalls are exceptions in every policy. ++ They try selecting the branch where the source exists as possible ++ since copyup a large file will take long time. If it can't be, ++ ie. the branch where the source exists is readonly, then they will ++ follow the copyup policy. ++- There is an exception for rename(2) when the target exists. ++ If the rename target exists, aufs compares the index of the branches ++ where the source and the target exists and selects the higher ++ one. If the selected branch is readonly, then aufs follows the ++ copyup policy. +diff -Nurp linux-5.4/Documentation/filesystems/aufs/design/06dirren.dot linux-5.4-aufs/Documentation/filesystems/aufs/design/06dirren.dot +--- linux-5.4/Documentation/filesystems/aufs/design/06dirren.dot 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/Documentation/filesystems/aufs/design/06dirren.dot 2019-11-28 01:25:59.060925618 +0200 +@@ -0,0 +1,31 @@ ++ ++// to view this graph, run dot(1) command in GRAPHVIZ. ++ ++digraph G { ++node [shape=box]; ++whinfo [label="detailed info file\n(lower_brid_root-hinum, h_inum, namelen, old name)"]; ++ ++node [shape=oval]; ++ ++aufs_rename -> whinfo [label="store/remove"]; ++ ++node [shape=oval]; ++inode_list [label="h_inum list in branch\ncache"]; ++ ++node [shape=box]; ++whinode [label="h_inum list file"]; ++ ++node [shape=oval]; ++brmgmt [label="br_add/del/mod/umount"]; ++ ++brmgmt -> inode_list [label="create/remove"]; ++brmgmt -> whinode [label="load/store"]; ++ ++inode_list -> whinode [style=dashed,dir=both]; ++ ++aufs_rename -> inode_list [label="add/del"]; ++ ++aufs_lookup -> inode_list [label="search"]; ++ ++aufs_lookup -> whinfo [label="load/remove"]; ++} +diff -Nurp linux-5.4/Documentation/filesystems/aufs/design/06dirren.txt linux-5.4-aufs/Documentation/filesystems/aufs/design/06dirren.txt +--- linux-5.4/Documentation/filesystems/aufs/design/06dirren.txt 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/Documentation/filesystems/aufs/design/06dirren.txt 2019-11-28 01:25:59.060925618 +0200 +@@ -0,0 +1,89 @@ ++ ++# Copyright (C) 2017-2019 Junjiro R. Okajima ++ ++Special handling for renaming a directory (DIRREN) ++---------------------------------------------------------------------- ++First, let's assume we have a simple usecase. ++ ++- /u = /rw + /ro ++- /rw/dirA exists ++- /ro/dirA and /ro/dirA/file exist too ++- there is no dirB on both branches ++- a user issues rename("dirA", "dirB") ++ ++Now, what should aufs behave against this rename(2)? ++There are a few possible cases. ++ ++A. returns EROFS. ++ since dirA exists on a readonly branch which cannot be renamed. ++B. returns EXDEV. ++ it is possible to copy-up dirA (only the dir itself), but the child ++ entries ("file" in this case) should not be. it must be a bad ++ approach to copy-up recursively. ++C. returns a success. ++ even the branch /ro is readonly, aufs tries renaming it. Obviously it ++ is a violation of aufs' policy. ++D. construct an extra information which indicates that /ro/dirA should ++ be handled as the name of dirB. ++ overlayfs has a similar feature called REDIRECT. ++ ++Until now, aufs implements the case B only which returns EXDEV, and ++expects the userspace application behaves like mv(1) which tries ++issueing rename(2) recursively. ++ ++A new aufs feature called DIRREN is introduced which implements the case ++D. There are several "extra information" added. ++ ++1. detailed info per renamed directory ++ path: /rw/dirB/$AUFS_WH_DR_INFO_PFX. ++2. the inode-number list of directories on a branch ++ path: /rw/dirB/$AUFS_WH_DR_BRHINO ++ ++The filename of "detailed info per directory" represents the lower ++branch, and its format is ++- a type of the branch id ++ one of these. ++ + uuid (not implemented yet) ++ + fsid ++ + dev ++- the inode-number of the branch root dir ++ ++And it contains these info in a single regular file. ++- magic number ++- branch's inode-number of the logically renamed dir ++- the name of the before-renamed dir ++ ++The "detailed info per directory" file is created in aufs rename(2), and ++loaded in any lookup. ++The info is considered in lookup for the matching case only. Here ++"matching" means that the root of branch (in the info filename) is same ++to the current looking-up branch. After looking-up the before-renamed ++name, the inode-number is compared. And the matched dentry is used. ++ ++The "inode-number list of directories" is a regular file which contains ++simply the inode-numbers on the branch. The file is created or updated ++in removing the branch, and loaded in adding the branch. Its lifetime is ++equal to the branch. ++The list is refered in lookup, and when the current target inode is ++found in the list, the aufs tries loading the "detailed info per ++directory" and get the changed and valid name of the dir. ++ ++Theoretically these "extra informaiton" may be able to be put into XATTR ++in the dir inode. But aufs doesn't choose this way because ++1. XATTR may not be supported by the branch (or its configuration) ++2. XATTR may have its size limit. ++3. XATTR may be less easy to convert than a regular file, when the ++ format of the info is changed in the future. ++At the same time, I agree that the regular file approach is much slower ++than XATTR approach. So, in the future, aufs may take the XATTR or other ++better approach. ++ ++This DIRREN feature is enabled by aufs configuration, and is activated ++by a new mount option. ++ ++For the more complicated case, there is a work with UDBA option, which ++is to dected the direct access to the branches (by-passing aufs) and to ++maintain the cashes in aufs. Since a single cached aufs dentry may ++contains two names, before- and after-rename, the name comparision in ++UDBA handler may not work correctly. In this case, the behaviour will be ++equivalen to udba=reval case. +diff -Nurp linux-5.4/Documentation/filesystems/aufs/design/06fhsm.txt linux-5.4-aufs/Documentation/filesystems/aufs/design/06fhsm.txt +--- linux-5.4/Documentation/filesystems/aufs/design/06fhsm.txt 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/Documentation/filesystems/aufs/design/06fhsm.txt 2019-11-28 01:25:59.060925618 +0200 +@@ -0,0 +1,105 @@ ++ ++# Copyright (C) 2011-2019 Junjiro R. Okajima ++ ++File-based Hierarchical Storage Management (FHSM) ++---------------------------------------------------------------------- ++Hierarchical Storage Management (or HSM) is a well-known feature in the ++storage world. Aufs provides this feature as file-based with multiple ++writable branches, based upon the principle of "Colder, the Lower". ++Here the word "colder" means that the less used files, and "lower" means ++that the position in the order of the stacked branches vertically. ++These multiple writable branches are prioritized, ie. the topmost one ++should be the fastest drive and be used heavily. ++ ++o Characters in aufs FHSM story ++- aufs itself and a new branch attribute. ++- a new ioctl interface to move-down and to establish a connection with ++ the daemon ("move-down" is a converse of "copy-up"). ++- userspace tool and daemon. ++ ++The userspace daemon establishes a connection with aufs and waits for ++the notification. The notified information is very similar to struct ++statfs containing the number of consumed blocks and inodes. ++When the consumed blocks/inodes of a branch exceeds the user-specified ++upper watermark, the daemon activates its move-down process until the ++consumed blocks/inodes reaches the user-specified lower watermark. ++ ++The actual move-down is done by aufs based upon the request from ++user-space since we need to maintain the inode number and the internal ++pointer arrays in aufs. ++ ++Currently aufs FHSM handles the regular files only. Additionally they ++must not be hard-linked nor pseudo-linked. ++ ++ ++o Cowork of aufs and the user-space daemon ++ During the userspace daemon established the connection, aufs sends a ++ small notification to it whenever aufs writes something into the ++ writable branch. But it may cost high since aufs issues statfs(2) ++ internally. So user can specify a new option to cache the ++ info. Actually the notification is controlled by these factors. ++ + the specified cache time. ++ + classified as "force" by aufs internally. ++ Until the specified time expires, aufs doesn't send the info ++ except the forced cases. When aufs decide forcing, the info is always ++ notified to userspace. ++ For example, the number of free inodes is generally large enough and ++ the shortage of it happens rarely. So aufs doesn't force the ++ notification when creating a new file, directory and others. This is ++ the typical case which aufs doesn't force. ++ When aufs writes the actual filedata and the files consumes any of new ++ blocks, the aufs forces notifying. ++ ++ ++o Interfaces in aufs ++- New branch attribute. ++ + fhsm ++ Specifies that the branch is managed by FHSM feature. In other word, ++ participant in the FHSM. ++ When nofhsm is set to the branch, it will not be the source/target ++ branch of the move-down operation. This attribute is set ++ independently from coo and moo attributes, and if you want full ++ FHSM, you should specify them as well. ++- New mount option. ++ + fhsm_sec ++ Specifies a second to suppress many less important info to be ++ notified. ++- New ioctl. ++ + AUFS_CTL_FHSM_FD ++ create a new file descriptor which userspace can read the notification ++ (a subset of struct statfs) from aufs. ++- Module parameter 'brs' ++ It has to be set to 1. Otherwise the new mount option 'fhsm' will not ++ be set. ++- mount helpers /sbin/mount.aufs and /sbin/umount.aufs ++ When there are two or more branches with fhsm attributes, ++ /sbin/mount.aufs invokes the user-space daemon and /sbin/umount.aufs ++ terminates it. As a result of remounting and branch-manipulation, the ++ number of branches with fhsm attribute can be one. In this case, ++ /sbin/mount.aufs will terminate the user-space daemon. ++ ++ ++Finally the operation is done as these steps in kernel-space. ++- make sure that, ++ + no one else is using the file. ++ + the file is not hard-linked. ++ + the file is not pseudo-linked. ++ + the file is a regular file. ++ + the parent dir is not opaqued. ++- find the target writable branch. ++- make sure the file is not whiteout-ed by the upper (than the target) ++ branch. ++- make the parent dir on the target branch. ++- mutex lock the inode on the branch. ++- unlink the whiteout on the target branch (if exists). ++- lookup and create the whiteout-ed temporary name on the target branch. ++- copy the file as the whiteout-ed temporary name on the target branch. ++- rename the whiteout-ed temporary name to the original name. ++- unlink the file on the source branch. ++- maintain the internal pointer array and the external inode number ++ table (XINO). ++- maintain the timestamps and other attributes of the parent dir and the ++ file. ++ ++And of course, in every step, an error may happen. So the operation ++should restore the original file state after an error happens. +diff -Nurp linux-5.4/Documentation/filesystems/aufs/design/06mmap.txt linux-5.4-aufs/Documentation/filesystems/aufs/design/06mmap.txt +--- linux-5.4/Documentation/filesystems/aufs/design/06mmap.txt 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/Documentation/filesystems/aufs/design/06mmap.txt 2019-11-28 01:25:59.060925618 +0200 +@@ -0,0 +1,59 @@ ++ ++# Copyright (C) 2005-2019 Junjiro R. Okajima ++ ++mmap(2) -- File Memory Mapping ++---------------------------------------------------------------------- ++In aufs, the file-mapped pages are handled by a branch fs directly, no ++interaction with aufs. It means aufs_mmap() calls the branch fs's ++->mmap(). ++This approach is simple and good, but there is one problem. ++Under /proc, several entries show the mmapped files by its path (with ++device and inode number), and the printed path will be the path on the ++branch fs's instead of virtual aufs's. ++This is not a problem in most cases, but some utilities lsof(1) (and its ++user) may expect the path on aufs. ++ ++To address this issue, aufs adds a new member called vm_prfile in struct ++vm_area_struct (and struct vm_region). The original vm_file points to ++the file on the branch fs in order to handle everything correctly as ++usual. The new vm_prfile points to a virtual file in aufs, and the ++show-functions in procfs refers to vm_prfile if it is set. ++Also we need to maintain several other places where touching vm_file ++such like ++- fork()/clone() copies vma and the reference count of vm_file is ++ incremented. ++- merging vma maintains the ref count too. ++ ++This is not a good approach. It just fakes the printed path. But it ++leaves all behaviour around f_mapping unchanged. This is surely an ++advantage. ++Actually aufs had adopted another complicated approach which calls ++generic_file_mmap() and handles struct vm_operations_struct. In this ++approach, aufs met a hard problem and I could not solve it without ++switching the approach. ++ ++There may be one more another approach which is ++- bind-mount the branch-root onto the aufs-root internally ++- grab the new vfsmount (ie. struct mount) ++- lazy-umount the branch-root internally ++- in open(2) the aufs-file, open the branch-file with the hidden ++ vfsmount (instead of the original branch's vfsmount) ++- ideally this "bind-mount and lazy-umount" should be done atomically, ++ but it may be possible from userspace by the mount helper. ++ ++Adding the internal hidden vfsmount and using it in opening a file, the ++file path under /proc will be printed correctly. This approach looks ++smarter, but is not possible I am afraid. ++- aufs-root may be bind-mount later. when it happens, another hidden ++ vfsmount will be required. ++- it is hard to get the chance to bind-mount and lazy-umount ++ + in kernel-space, FS can have vfsmount in open(2) via ++ file->f_path, and aufs can know its vfsmount. But several locks are ++ already acquired, and if aufs tries to bind-mount and lazy-umount ++ here, then it may cause a deadlock. ++ + in user-space, bind-mount doesn't invoke the mount helper. ++- since /proc shows dev and ino, aufs has to give vma these info. it ++ means a new member vm_prinode will be necessary. this is essentially ++ equivalent to vm_prfile described above. ++ ++I have to give up this "looks-smater" approach. +diff -Nurp linux-5.4/Documentation/filesystems/aufs/design/06xattr.txt linux-5.4-aufs/Documentation/filesystems/aufs/design/06xattr.txt +--- linux-5.4/Documentation/filesystems/aufs/design/06xattr.txt 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/Documentation/filesystems/aufs/design/06xattr.txt 2019-11-28 01:25:59.060925618 +0200 +@@ -0,0 +1,81 @@ ++ ++# Copyright (C) 2014-2019 Junjiro R. Okajima ++ ++Listing XATTR/EA and getting the value ++---------------------------------------------------------------------- ++For the inode standard attributes (owner, group, timestamps, etc.), aufs ++shows the values from the topmost existing file. This behaviour is good ++for the non-dir entries since the bahaviour exactly matches the shown ++information. But for the directories, aufs considers all the same named ++entries on the lower branches. Which means, if one of the lower entry ++rejects readdir call, then aufs returns an error even if the topmost ++entry allows it. This behaviour is necessary to respect the branch fs's ++security, but can make users confused since the user-visible standard ++attributes don't match the behaviour. ++To address this issue, aufs has a mount option called dirperm1 which ++checks the permission for the topmost entry only, and ignores the lower ++entry's permission. ++ ++A similar issue can happen around XATTR. ++getxattr(2) and listxattr(2) families behave as if dirperm1 option is ++always set. Otherwise these very unpleasant situation would happen. ++- listxattr(2) may return the duplicated entries. ++- users may not be able to remove or reset the XATTR forever, ++ ++ ++XATTR/EA support in the internal (copy,move)-(up,down) ++---------------------------------------------------------------------- ++Generally the extended attributes of inode are categorized as these. ++- "security" for LSM and capability. ++- "system" for posix ACL, 'acl' mount option is required for the branch ++ fs generally. ++- "trusted" for userspace, CAP_SYS_ADMIN is required. ++- "user" for userspace, 'user_xattr' mount option is required for the ++ branch fs generally. ++ ++Moreover there are some other categories. Aufs handles these rather ++unpopular categories as the ordinary ones, ie. there is no special ++condition nor exception. ++ ++In copy-up, the support for XATTR on the dst branch may differ from the ++src branch. In this case, the copy-up operation will get an error and ++the original user operation which triggered the copy-up will fail. It ++can happen that even all copy-up will fail. ++When both of src and dst branches support XATTR and if an error occurs ++during copying XATTR, then the copy-up should fail obviously. That is a ++good reason and aufs should return an error to userspace. But when only ++the src branch support that XATTR, aufs should not return an error. ++For example, the src branch supports ACL but the dst branch doesn't ++because the dst branch may natively un-support it or temporary ++un-support it due to "noacl" mount option. Of course, the dst branch fs ++may NOT return an error even if the XATTR is not supported. It is ++totally up to the branch fs. ++ ++Anyway when the aufs internal copy-up gets an error from the dst branch ++fs, then aufs tries removing the just copied entry and returns the error ++to the userspace. The worst case of this situation will be all copy-up ++will fail. ++ ++For the copy-up operation, there two basic approaches. ++- copy the specified XATTR only (by category above), and return the ++ error unconditionally if it happens. ++- copy all XATTR, and ignore the error on the specified category only. ++ ++In order to support XATTR and to implement the correct behaviour, aufs ++chooses the latter approach and introduces some new branch attributes, ++"icexsec", "icexsys", "icextr", "icexusr", and "icexoth". ++They correspond to the XATTR namespaces (see above). Additionally, to be ++convenient, "icex" is also provided which means all "icex*" attributes ++are set (here the word "icex" stands for "ignore copy-error on XATTR"). ++ ++The meaning of these attributes is to ignore the error from setting ++XATTR on that branch. ++Note that aufs tries copying all XATTR unconditionally, and ignores the ++error from the dst branch according to the specified attributes. ++ ++Some XATTR may have its default value. The default value may come from ++the parent dir or the environment. If the default value is set at the ++file creating-time, it will be overwritten by copy-up. ++Some contradiction may happen I am afraid. ++Do we need another attribute to stop copying XATTR? I am unsure. For ++now, aufs implements the branch attributes to ignore the error. +diff -Nurp linux-5.4/Documentation/filesystems/aufs/design/07export.txt linux-5.4-aufs/Documentation/filesystems/aufs/design/07export.txt +--- linux-5.4/Documentation/filesystems/aufs/design/07export.txt 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/Documentation/filesystems/aufs/design/07export.txt 2019-11-28 01:25:59.060925618 +0200 +@@ -0,0 +1,45 @@ ++ ++# Copyright (C) 2005-2019 Junjiro R. Okajima ++ ++Export Aufs via NFS ++---------------------------------------------------------------------- ++Here is an approach. ++- like xino/xib, add a new file 'xigen' which stores aufs inode ++ generation. ++- iget_locked(): initialize aufs inode generation for a new inode, and ++ store it in xigen file. ++- destroy_inode(): increment aufs inode generation and store it in xigen ++ file. it is necessary even if it is not unlinked, because any data of ++ inode may be changed by UDBA. ++- encode_fh(): for a root dir, simply return FILEID_ROOT. otherwise ++ build file handle by ++ + branch id (4 bytes) ++ + superblock generation (4 bytes) ++ + inode number (4 or 8 bytes) ++ + parent dir inode number (4 or 8 bytes) ++ + inode generation (4 bytes)) ++ + return value of exportfs_encode_fh() for the parent on a branch (4 ++ bytes) ++ + file handle for a branch (by exportfs_encode_fh()) ++- fh_to_dentry(): ++ + find the index of a branch from its id in handle, and check it is ++ still exist in aufs. ++ + 1st level: get the inode number from handle and search it in cache. ++ + 2nd level: if not found in cache, get the parent inode number from ++ the handle and search it in cache. and then open the found parent ++ dir, find the matching inode number by vfs_readdir() and get its ++ name, and call lookup_one_len() for the target dentry. ++ + 3rd level: if the parent dir is not cached, call ++ exportfs_decode_fh() for a branch and get the parent on a branch, ++ build a pathname of it, convert it a pathname in aufs, call ++ path_lookup(). now aufs gets a parent dir dentry, then handle it as ++ the 2nd level. ++ + to open the dir, aufs needs struct vfsmount. aufs keeps vfsmount ++ for every branch, but not itself. to get this, (currently) aufs ++ searches in current->nsproxy->mnt_ns list. it may not be a good ++ idea, but I didn't get other approach. ++ + test the generation of the gotten inode. ++- every inode operation: they may get EBUSY due to UDBA. in this case, ++ convert it into ESTALE for NFSD. ++- readdir(): call lockdep_on/off() because filldir in NFSD calls ++ lookup_one_len(), vfs_getattr(), encode_fh() and others. +diff -Nurp linux-5.4/Documentation/filesystems/aufs/design/08shwh.txt linux-5.4-aufs/Documentation/filesystems/aufs/design/08shwh.txt +--- linux-5.4/Documentation/filesystems/aufs/design/08shwh.txt 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/Documentation/filesystems/aufs/design/08shwh.txt 2019-11-28 01:25:59.060925618 +0200 +@@ -0,0 +1,39 @@ ++ ++# Copyright (C) 2005-2019 Junjiro R. Okajima ++ ++Show Whiteout Mode (shwh) ++---------------------------------------------------------------------- ++Generally aufs hides the name of whiteouts. But in some cases, to show ++them is very useful for users. For instance, creating a new middle layer ++(branch) by merging existing layers. ++ ++(borrowing aufs1 HOW-TO from a user, Michael Towers) ++When you have three branches, ++- Bottom: 'system', squashfs (underlying base system), read-only ++- Middle: 'mods', squashfs, read-only ++- Top: 'overlay', ram (tmpfs), read-write ++ ++The top layer is loaded at boot time and saved at shutdown, to preserve ++the changes made to the system during the session. ++When larger changes have been made, or smaller changes have accumulated, ++the size of the saved top layer data grows. At this point, it would be ++nice to be able to merge the two overlay branches ('mods' and 'overlay') ++and rewrite the 'mods' squashfs, clearing the top layer and thus ++restoring save and load speed. ++ ++This merging is simplified by the use of another aufs mount, of just the ++two overlay branches using the 'shwh' option. ++# mount -t aufs -o ro,shwh,br:/livesys/overlay=ro+wh:/livesys/mods=rr+wh \ ++ aufs /livesys/merge_union ++ ++A merged view of these two branches is then available at ++/livesys/merge_union, and the new feature is that the whiteouts are ++visible! ++Note that in 'shwh' mode the aufs mount must be 'ro', which will disable ++writing to all branches. Also the default mode for all branches is 'ro'. ++It is now possible to save the combined contents of the two overlay ++branches to a new squashfs, e.g.: ++# mksquashfs /livesys/merge_union /path/to/newmods.squash ++ ++This new squashfs archive can be stored on the boot device and the ++initramfs will use it to replace the old one at the next boot. +diff -Nurp linux-5.4/Documentation/filesystems/aufs/design/10dynop.txt linux-5.4-aufs/Documentation/filesystems/aufs/design/10dynop.txt +--- linux-5.4/Documentation/filesystems/aufs/design/10dynop.txt 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/Documentation/filesystems/aufs/design/10dynop.txt 2019-11-28 01:25:59.060925618 +0200 +@@ -0,0 +1,34 @@ ++ ++# Copyright (C) 2010-2019 Junjiro R. Okajima ++ ++Dynamically customizable FS operations ++---------------------------------------------------------------------- ++Generally FS operations (struct inode_operations, struct ++address_space_operations, struct file_operations, etc.) are defined as ++"static const", but it never means that FS have only one set of ++operation. Some FS have multiple sets of them. For instance, ext2 has ++three sets, one for XIP, for NOBH, and for normal. ++Since aufs overrides and redirects these operations, sometimes aufs has ++to change its behaviour according to the branch FS type. More importantly ++VFS acts differently if a function (member in the struct) is set or ++not. It means aufs should have several sets of operations and select one ++among them according to the branch FS definition. ++ ++In order to solve this problem and not to affect the behaviour of VFS, ++aufs defines these operations dynamically. For instance, aufs defines ++dummy direct_IO function for struct address_space_operations, but it may ++not be set to the address_space_operations actually. When the branch FS ++doesn't have it, aufs doesn't set it to its address_space_operations ++while the function definition itself is still alive. So the behaviour ++itself will not change, and it will return an error when direct_IO is ++not set. ++ ++The lifetime of these dynamically generated operation object is ++maintained by aufs branch object. When the branch is removed from aufs, ++the reference counter of the object is decremented. When it reaches ++zero, the dynamically generated operation object will be freed. ++ ++This approach is designed to support AIO (io_submit), Direct I/O and ++XIP (DAX) mainly. ++Currently this approach is applied to address_space_operations for ++regular files only. +diff -Nurp linux-5.4/Documentation/filesystems/aufs/README linux-5.4-aufs/Documentation/filesystems/aufs/README +--- linux-5.4/Documentation/filesystems/aufs/README 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/Documentation/filesystems/aufs/README 2019-11-28 01:25:59.060925618 +0200 +@@ -0,0 +1,399 @@ ++ ++Aufs5 -- advanced multi layered unification filesystem version 5.x ++http://aufs.sf.net ++Junjiro R. Okajima ++ ++ ++0. Introduction ++---------------------------------------- ++In the early days, aufs was entirely re-designed and re-implemented ++Unionfs Version 1.x series. Adding many original ideas, approaches, ++improvements and implementations, it became totally different from ++Unionfs while keeping the basic features. ++Later, Unionfs Version 2.x series began taking some of the same ++approaches to aufs1's. ++Unionfs was being developed by Professor Erez Zadok at Stony Brook ++University and his team. ++ ++Aufs5 supports linux-v5.0 and later, If you want older kernel version ++support, ++- for linux-v4.x series, try aufs4-linux.git or aufs4-standalone.git ++- for linux-v3.x series, try aufs3-linux.git or aufs3-standalone.git ++- for linux-v2.6.16 and later, try aufs2-2.6.git, aufs2-standalone.git ++ or aufs1 from CVS on SourceForge. ++ ++Note: it becomes clear that "Aufs was rejected. Let's give it up." ++ According to Christoph Hellwig, linux rejects all union-type ++ filesystems but UnionMount. ++ ++ ++PS. Al Viro seems have a plan to merge aufs as well as overlayfs and ++ UnionMount, and he pointed out an issue around a directory mutex ++ lock and aufs addressed it. But it is still unsure whether aufs will ++ be merged (or any other union solution). ++ ++ ++ ++1. Features ++---------------------------------------- ++- unite several directories into a single virtual filesystem. The member ++ directory is called as a branch. ++- you can specify the permission flags to the branch, which are 'readonly', ++ 'readwrite' and 'whiteout-able.' ++- by upper writable branch, internal copyup and whiteout, files/dirs on ++ readonly branch are modifiable logically. ++- dynamic branch manipulation, add, del. ++- etc... ++ ++Also there are many enhancements in aufs, such as: ++- test only the highest one for the directory permission (dirperm1) ++- copyup on open (coo=) ++- 'move' policy for copy-up between two writable branches, after ++ checking free space. ++- xattr, acl ++- readdir(3) in userspace. ++- keep inode number by external inode number table ++- keep the timestamps of file/dir in internal copyup operation ++- seekable directory, supporting NFS readdir. ++- whiteout is hardlinked in order to reduce the consumption of inodes ++ on branch ++- do not copyup, nor create a whiteout when it is unnecessary ++- revert a single systemcall when an error occurs in aufs ++- remount interface instead of ioctl ++- maintain /etc/mtab by an external command, /sbin/mount.aufs. ++- loopback mounted filesystem as a branch ++- kernel thread for removing the dir who has a plenty of whiteouts ++- support copyup sparse file (a file which has a 'hole' in it) ++- default permission flags for branches ++- selectable permission flags for ro branch, whether whiteout can ++ exist or not ++- export via NFS. ++- support /fs/aufs and /aufs. ++- support multiple writable branches, some policies to select one ++ among multiple writable branches. ++- a new semantics for link(2) and rename(2) to support multiple ++ writable branches. ++- no glibc changes are required. ++- pseudo hardlink (hardlink over branches) ++- allow a direct access manually to a file on branch, e.g. bypassing aufs. ++ including NFS or remote filesystem branch. ++- userspace wrapper for pathconf(3)/fpathconf(3) with _PC_LINK_MAX. ++- and more... ++ ++Currently these features are dropped temporary from aufs5. ++See design/08plan.txt in detail. ++- nested mount, i.e. aufs as readonly no-whiteout branch of another aufs ++ (robr) ++- statistics of aufs thread (/sys/fs/aufs/stat) ++ ++Features or just an idea in the future (see also design/*.txt), ++- reorder the branch index without del/re-add. ++- permanent xino files for NFSD ++- an option for refreshing the opened files after add/del branches ++- light version, without branch manipulation. (unnecessary?) ++- copyup in userspace ++- inotify in userspace ++- readv/writev ++ ++ ++2. Download ++---------------------------------------- ++There are three GIT trees for aufs5, aufs5-linux.git, ++aufs5-standalone.git, and aufs-util.git. Note that there is no "5" in ++"aufs-util.git." ++While the aufs-util is always necessary, you need either of aufs5-linux ++or aufs5-standalone. ++ ++The aufs5-linux tree includes the whole linux mainline GIT tree, ++git://git.kernel.org/.../torvalds/linux.git. ++And you cannot select CONFIG_AUFS_FS=m for this version, eg. you cannot ++build aufs5 as an external kernel module. ++Several extra patches are not included in this tree. Only ++aufs5-standalone tree contains them. They are described in the later ++section "Configuration and Compilation." ++ ++On the other hand, the aufs5-standalone tree has only aufs source files ++and necessary patches, and you can select CONFIG_AUFS_FS=m. ++But you need to apply all aufs patches manually. ++ ++You will find GIT branches whose name is in form of "aufs5.x" where "x" ++represents the linux kernel version, "linux-5.x". For instance, ++"aufs5.0" is for linux-5.0. For latest "linux-5.x-rcN", use ++"aufs5.x-rcN" branch. ++ ++o aufs5-linux tree ++$ git clone --reference /your/linux/git/tree \ ++ git://github.com/sfjro/aufs5-linux.git aufs5-linux.git ++- if you don't have linux GIT tree, then remove "--reference ..." ++$ cd aufs5-linux.git ++$ git checkout origin/aufs5.0 ++ ++Or You may want to directly git-pull aufs into your linux GIT tree, and ++leave the patch-work to GIT. ++$ cd /your/linux/git/tree ++$ git remote add aufs5 git://github.com/sfjro/aufs5-linux.git ++$ git fetch aufs5 ++$ git checkout -b my5.0 v5.0 ++$ (add your local change...) ++$ git pull aufs5 aufs5.0 ++- now you have v5.0 + your_changes + aufs5.0 in you my5.0 branch. ++- you may need to solve some conflicts between your_changes and ++ aufs5.0. in this case, git-rerere is recommended so that you can ++ solve the similar conflicts automatically when you upgrade to 5.1 or ++ later in the future. ++ ++o aufs5-standalone tree ++$ git clone git://github.com/sfjro/aufs5-standalone.git aufs5-standalone.git ++$ cd aufs5-standalone.git ++$ git checkout origin/aufs5.0 ++ ++o aufs-util tree ++$ git clone git://git.code.sf.net/p/aufs/aufs-util aufs-util.git ++- note that the public aufs-util.git is on SourceForge instead of ++ GitHUB. ++$ cd aufs-util.git ++$ git checkout origin/aufs5.0 ++ ++Note: The 5.x-rcN branch is to be used with `rc' kernel versions ONLY. ++The minor version number, 'x' in '5.x', of aufs may not always ++follow the minor version number of the kernel. ++Because changes in the kernel that cause the use of a new ++minor version number do not always require changes to aufs-util. ++ ++Since aufs-util has its own minor version number, you may not be ++able to find a GIT branch in aufs-util for your kernel's ++exact minor version number. ++In this case, you should git-checkout the branch for the ++nearest lower number. ++ ++For (an unreleased) example: ++If you are using "linux-5.10" and the "aufs5.10" branch ++does not exist in aufs-util repository, then "aufs5.9", "aufs5.8" ++or something numerically smaller is the branch for your kernel. ++ ++Also you can view all branches by ++ $ git branch -a ++ ++ ++3. Configuration and Compilation ++---------------------------------------- ++Make sure you have git-checkout'ed the correct branch. ++ ++For aufs5-linux tree, ++- enable CONFIG_AUFS_FS. ++- set other aufs configurations if necessary. ++ ++For aufs5-standalone tree, ++There are several ways to build. ++ ++1. ++- apply ./aufs5-kbuild.patch to your kernel source files. ++- apply ./aufs5-base.patch too. ++- apply ./aufs5-mmap.patch too. ++- apply ./aufs5-standalone.patch too, if you have a plan to set ++ CONFIG_AUFS_FS=m. otherwise you don't need ./aufs5-standalone.patch. ++- copy ./{Documentation,fs,include/uapi/linux/aufs_type.h} files to your ++ kernel source tree. Never copy $PWD/include/uapi/linux/Kbuild. ++- enable CONFIG_AUFS_FS, you can select either ++ =m or =y. ++- and build your kernel as usual. ++- install the built kernel. ++- install the header files too by "make headers_install" to the ++ directory where you specify. By default, it is $PWD/usr. ++ "make help" shows a brief note for headers_install. ++- and reboot your system. ++ ++2. ++- module only (CONFIG_AUFS_FS=m). ++- apply ./aufs5-base.patch to your kernel source files. ++- apply ./aufs5-mmap.patch too. ++- apply ./aufs5-standalone.patch too. ++- build your kernel, don't forget "make headers_install", and reboot. ++- edit ./config.mk and set other aufs configurations if necessary. ++ Note: You should read $PWD/fs/aufs/Kconfig carefully which describes ++ every aufs configurations. ++- build the module by simple "make". ++- you can specify ${KDIR} make variable which points to your kernel ++ source tree. ++- install the files ++ + run "make install" to install the aufs module, or copy the built ++ $PWD/aufs.ko to /lib/modules/... and run depmod -a (or reboot simply). ++ + run "make install_headers" (instead of headers_install) to install ++ the modified aufs header file (you can specify DESTDIR which is ++ available in aufs standalone version's Makefile only), or copy ++ $PWD/usr/include/linux/aufs_type.h to /usr/include/linux or wherever ++ you like manually. By default, the target directory is $PWD/usr. ++- no need to apply aufs5-kbuild.patch, nor copying source files to your ++ kernel source tree. ++ ++Note: The header file aufs_type.h is necessary to build aufs-util ++ as well as "make headers_install" in the kernel source tree. ++ headers_install is subject to be forgotten, but it is essentially ++ necessary, not only for building aufs-util. ++ You may not meet problems without headers_install in some older ++ version though. ++ ++And then, ++- read README in aufs-util, build and install it ++- note that your distribution may contain an obsoleted version of ++ aufs_type.h in /usr/include/linux or something. When you build aufs ++ utilities, make sure that your compiler refers the correct aufs header ++ file which is built by "make headers_install." ++- if you want to use readdir(3) in userspace or pathconf(3) wrapper, ++ then run "make install_ulib" too. And refer to the aufs manual in ++ detail. ++ ++There several other patches in aufs5-standalone.git. They are all ++optional. When you meet some problems, they will help you. ++- aufs5-loopback.patch ++ Supports a nested loopback mount in a branch-fs. This patch is ++ unnecessary until aufs produces a message like "you may want to try ++ another patch for loopback file". ++- proc_mounts.patch ++ When there are many mountpoints and many mount(2)/umount(2) are ++ running, then /proc/mounts may not show the all mountpoints. This ++ patch makes /proc/mounts always show the full mountpoints list. ++ If you don't want to apply this patch and meet such problem, then you ++ need to increase the value of 'ProcMounts_Times' make-variable in ++ aufs-util.git as a second best solution. ++- vfs-ino.patch ++ Modifies a system global kernel internal function get_next_ino() in ++ order to stop assigning 0 for an inode-number. Not directly related to ++ aufs, but recommended generally. ++- tmpfs-idr.patch ++ Keeps the tmpfs inode number as the lowest value. Effective to reduce ++ the size of aufs XINO files for tmpfs branch. Also it prevents the ++ duplication of inode number, which is important for backup tools and ++ other utilities. When you find aufs XINO files for tmpfs branch ++ growing too much, try this patch. ++- lockdep-debug.patch ++ Because aufs is not only an ordinary filesystem (callee of VFS), but ++ also a caller of VFS functions for branch filesystems, subclassing of ++ the internal locks for LOCKDEP is necessary. LOCKDEP is a debugging ++ feature of linux kernel. If you enable CONFIG_LOCKDEP, then you will ++ need to apply this debug patch to expand several constant values. ++ If don't know what LOCKDEP is, then you don't have apply this patch. ++ ++ ++4. Usage ++---------------------------------------- ++At first, make sure aufs-util are installed, and please read the aufs ++manual, aufs.5 in aufs-util.git tree. ++$ man -l aufs.5 ++ ++And then, ++$ mkdir /tmp/rw /tmp/aufs ++# mount -t aufs -o br=/tmp/rw:${HOME} none /tmp/aufs ++ ++Here is another example. The result is equivalent. ++# mount -t aufs -o br=/tmp/rw=rw:${HOME}=ro none /tmp/aufs ++ Or ++# mount -t aufs -o br:/tmp/rw none /tmp/aufs ++# mount -o remount,append:${HOME} /tmp/aufs ++ ++Then, you can see whole tree of your home dir through /tmp/aufs. If ++you modify a file under /tmp/aufs, the one on your home directory is ++not affected, instead the same named file will be newly created under ++/tmp/rw. And all of your modification to a file will be applied to ++the one under /tmp/rw. This is called the file based Copy on Write ++(COW) method. ++Aufs mount options are described in aufs.5. ++If you run chroot or something and make your aufs as a root directory, ++then you need to customize the shutdown script. See the aufs manual in ++detail. ++ ++Additionally, there are some sample usages of aufs which are a ++diskless system with network booting, and LiveCD over NFS. ++See sample dir in CVS tree on SourceForge. ++ ++ ++5. Contact ++---------------------------------------- ++When you have any problems or strange behaviour in aufs, please let me ++know with: ++- /proc/mounts (instead of the output of mount(8)) ++- /sys/module/aufs/* ++- /sys/fs/aufs/* (if you have them) ++- /debug/aufs/* (if you have them) ++- linux kernel version ++ if your kernel is not plain, for example modified by distributor, ++ the url where i can download its source is necessary too. ++- aufs version which was printed at loading the module or booting the ++ system, instead of the date you downloaded. ++- configuration (define/undefine CONFIG_AUFS_xxx) ++- kernel configuration or /proc/config.gz (if you have it) ++- behaviour which you think to be incorrect ++- actual operation, reproducible one is better ++- mailto: aufs-users at lists.sourceforge.net ++ ++Usually, I don't watch the Public Areas(Bugs, Support Requests, Patches, ++and Feature Requests) on SourceForge. Please join and write to ++aufs-users ML. ++ ++ ++6. Acknowledgements ++---------------------------------------- ++Thanks to everyone who have tried and are using aufs, whoever ++have reported a bug or any feedback. ++ ++Especially donators: ++Tomas Matejicek(slax.org) made a donation (much more than once). ++ Since Apr 2010, Tomas M (the author of Slax and Linux Live ++ scripts) is making "doubling" donations. ++ Unfortunately I cannot list all of the donators, but I really ++ appreciate. ++ It ends Aug 2010, but the ordinary donation URL is still available. ++ ++Dai Itasaka made a donation (2007/8). ++Chuck Smith made a donation (2008/4, 10 and 12). ++Henk Schoneveld made a donation (2008/9). ++Chih-Wei Huang, ASUS, CTC donated Eee PC 4G (2008/10). ++Francois Dupoux made a donation (2008/11). ++Bruno Cesar Ribas and Luis Carlos Erpen de Bona, C3SL serves public ++ aufs2 GIT tree (2009/2). ++William Grant made a donation (2009/3). ++Patrick Lane made a donation (2009/4). ++The Mail Archive (mail-archive.com) made donations (2009/5). ++Nippy Networks (Ed Wildgoose) made a donation (2009/7). ++New Dream Network, LLC (www.dreamhost.com) made a donation (2009/11). ++Pavel Pronskiy made a donation (2011/2). ++Iridium and Inmarsat satellite phone retailer (www.mailasail.com), Nippy ++ Networks (Ed Wildgoose) made a donation for hardware (2011/3). ++Max Lekomcev (DOM-TV project) made a donation (2011/7, 12, 2012/3, 6 and ++11). ++Sam Liddicott made a donation (2011/9). ++Era Scarecrow made a donation (2013/4). ++Bor Ratajc made a donation (2013/4). ++Alessandro Gorreta made a donation (2013/4). ++POIRETTE Marc made a donation (2013/4). ++Alessandro Gorreta made a donation (2013/4). ++lauri kasvandik made a donation (2013/5). ++"pemasu from Finland" made a donation (2013/7). ++The Parted Magic Project made a donation (2013/9 and 11). ++Pavel Barta made a donation (2013/10). ++Nikolay Pertsev made a donation (2014/5). ++James B made a donation (2014/7 and 2015/7). ++Stefano Di Biase made a donation (2014/8). ++Daniel Epellei made a donation (2015/1). ++OmegaPhil made a donation (2016/1, 2018/4). ++Tomasz Szewczyk made a donation (2016/4). ++James Burry made a donation (2016/12). ++Carsten Rose made a donation (2018/9). ++Porteus Kiosk made a donation (2018/10). ++ ++Thank you very much. ++Donations are always, including future donations, very important and ++helpful for me to keep on developing aufs. ++ ++ ++7. ++---------------------------------------- ++If you are an experienced user, no explanation is needed. Aufs is ++just a linux filesystem. ++ ++ ++Enjoy! ++ ++# Local variables: ; ++# mode: text; ++# End: ; +diff -Nurp linux-5.4/drivers/block/loop.c linux-5.4-aufs/drivers/block/loop.c +--- linux-5.4/drivers/block/loop.c 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/drivers/block/loop.c 2019-11-28 01:25:59.062925618 +0200 +@@ -738,6 +738,24 @@ out_err: + return error; + } + ++/* ++ * for AUFS ++ * no get/put for file. ++ */ ++struct file *loop_backing_file(struct super_block *sb) ++{ ++ struct file *ret; ++ struct loop_device *l; ++ ++ ret = NULL; ++ if (MAJOR(sb->s_dev) == LOOP_MAJOR) { ++ l = sb->s_bdev->bd_disk->private_data; ++ ret = l->lo_backing_file; ++ } ++ return ret; ++} ++EXPORT_SYMBOL_GPL(loop_backing_file); ++ + /* loop sysfs attributes */ + + static ssize_t loop_attr_show(struct device *dev, char *page, +diff -Nurp linux-5.4/fs/aufs/aufs.h linux-5.4-aufs/fs/aufs/aufs.h +--- linux-5.4/fs/aufs/aufs.h 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/aufs.h 2019-11-28 01:25:59.062925618 +0200 +@@ -0,0 +1,49 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * all header files ++ */ ++ ++#ifndef __AUFS_H__ ++#define __AUFS_H__ ++ ++#ifdef __KERNEL__ ++ ++#define AuStub(type, name, body, ...) \ ++ static inline type name(__VA_ARGS__) { body; } ++ ++#define AuStubVoid(name, ...) \ ++ AuStub(void, name, , __VA_ARGS__) ++#define AuStubInt0(name, ...) \ ++ AuStub(int, name, return 0, __VA_ARGS__) ++ ++#include "debug.h" ++ ++#include "branch.h" ++#include "cpup.h" ++#include "dcsub.h" ++#include "dbgaufs.h" ++#include "dentry.h" ++#include "dir.h" ++#include "dirren.h" ++#include "dynop.h" ++#include "file.h" ++#include "fstype.h" ++#include "hbl.h" ++#include "inode.h" ++#include "lcnt.h" ++#include "loop.h" ++#include "module.h" ++#include "opts.h" ++#include "rwsem.h" ++#include "super.h" ++#include "sysaufs.h" ++#include "vfsub.h" ++#include "whout.h" ++#include "wkq.h" ++ ++#endif /* __KERNEL__ */ ++#endif /* __AUFS_H__ */ +diff -Nurp linux-5.4/fs/aufs/branch.c linux-5.4-aufs/fs/aufs/branch.c +--- linux-5.4/fs/aufs/branch.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/branch.c 2019-11-28 01:25:59.062925618 +0200 +@@ -0,0 +1,1415 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * branch management ++ */ ++ ++#include ++#include ++#include "aufs.h" ++ ++/* ++ * free a single branch ++ */ ++static void au_br_do_free(struct au_branch *br) ++{ ++ int i; ++ struct au_wbr *wbr; ++ struct au_dykey **key; ++ ++ au_hnotify_fin_br(br); ++ /* always, regardless the mount option */ ++ au_dr_hino_free(&br->br_dirren); ++ au_xino_put(br); ++ ++ AuLCntZero(au_lcnt_read(&br->br_nfiles, /*do_rev*/0)); ++ au_lcnt_fin(&br->br_nfiles, /*do_sync*/0); ++ AuLCntZero(au_lcnt_read(&br->br_count, /*do_rev*/0)); ++ au_lcnt_fin(&br->br_count, /*do_sync*/0); ++ ++ wbr = br->br_wbr; ++ if (wbr) { ++ for (i = 0; i < AuBrWh_Last; i++) ++ dput(wbr->wbr_wh[i]); ++ AuDebugOn(atomic_read(&wbr->wbr_wh_running)); ++ AuRwDestroy(&wbr->wbr_wh_rwsem); ++ } ++ ++ if (br->br_fhsm) { ++ au_br_fhsm_fin(br->br_fhsm); ++ au_kfree_try_rcu(br->br_fhsm); ++ } ++ ++ key = br->br_dykey; ++ for (i = 0; i < AuBrDynOp; i++, key++) ++ if (*key) ++ au_dy_put(*key); ++ else ++ break; ++ ++ /* recursive lock, s_umount of branch's */ ++ /* synchronize_rcu(); */ /* why? */ ++ lockdep_off(); ++ path_put(&br->br_path); ++ lockdep_on(); ++ au_kfree_rcu(wbr); ++ au_lcnt_wait_for_fin(&br->br_nfiles); ++ au_lcnt_wait_for_fin(&br->br_count); ++ /* I don't know why, but percpu_refcount requires this */ ++ /* synchronize_rcu(); */ ++ au_kfree_rcu(br); ++} ++ ++/* ++ * frees all branches ++ */ ++void au_br_free(struct au_sbinfo *sbinfo) ++{ ++ aufs_bindex_t bmax; ++ struct au_branch **br; ++ ++ AuRwMustWriteLock(&sbinfo->si_rwsem); ++ ++ bmax = sbinfo->si_bbot + 1; ++ br = sbinfo->si_branch; ++ while (bmax--) ++ au_br_do_free(*br++); ++} ++ ++/* ++ * find the index of a branch which is specified by @br_id. ++ */ ++int au_br_index(struct super_block *sb, aufs_bindex_t br_id) ++{ ++ aufs_bindex_t bindex, bbot; ++ ++ bbot = au_sbbot(sb); ++ for (bindex = 0; bindex <= bbot; bindex++) ++ if (au_sbr_id(sb, bindex) == br_id) ++ return bindex; ++ return -1; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * add a branch ++ */ ++ ++static int test_overlap(struct super_block *sb, struct dentry *h_adding, ++ struct dentry *h_root) ++{ ++ if (unlikely(h_adding == h_root ++ || au_test_loopback_overlap(sb, h_adding))) ++ return 1; ++ if (h_adding->d_sb != h_root->d_sb) ++ return 0; ++ return au_test_subdir(h_adding, h_root) ++ || au_test_subdir(h_root, h_adding); ++} ++ ++/* ++ * returns a newly allocated branch. @new_nbranch is a number of branches ++ * after adding a branch. ++ */ ++static struct au_branch *au_br_alloc(struct super_block *sb, int new_nbranch, ++ int perm) ++{ ++ struct au_branch *add_branch; ++ struct dentry *root; ++ struct inode *inode; ++ int err; ++ ++ err = -ENOMEM; ++ add_branch = kzalloc(sizeof(*add_branch), GFP_NOFS); ++ if (unlikely(!add_branch)) ++ goto out; ++ add_branch->br_xino = au_xino_alloc(/*nfile*/1); ++ if (unlikely(!add_branch->br_xino)) ++ goto out_br; ++ err = au_hnotify_init_br(add_branch, perm); ++ if (unlikely(err)) ++ goto out_xino; ++ ++ if (au_br_writable(perm)) { ++ /* may be freed separately at changing the branch permission */ ++ add_branch->br_wbr = kzalloc(sizeof(*add_branch->br_wbr), ++ GFP_NOFS); ++ if (unlikely(!add_branch->br_wbr)) ++ goto out_hnotify; ++ } ++ ++ if (au_br_fhsm(perm)) { ++ err = au_fhsm_br_alloc(add_branch); ++ if (unlikely(err)) ++ goto out_wbr; ++ } ++ ++ root = sb->s_root; ++ err = au_sbr_realloc(au_sbi(sb), new_nbranch, /*may_shrink*/0); ++ if (!err) ++ err = au_di_realloc(au_di(root), new_nbranch, /*may_shrink*/0); ++ if (!err) { ++ inode = d_inode(root); ++ err = au_hinode_realloc(au_ii(inode), new_nbranch, ++ /*may_shrink*/0); ++ } ++ if (!err) ++ return add_branch; /* success */ ++ ++out_wbr: ++ au_kfree_rcu(add_branch->br_wbr); ++out_hnotify: ++ au_hnotify_fin_br(add_branch); ++out_xino: ++ au_xino_put(add_branch); ++out_br: ++ au_kfree_rcu(add_branch); ++out: ++ return ERR_PTR(err); ++} ++ ++/* ++ * test if the branch permission is legal or not. ++ */ ++static int test_br(struct inode *inode, int brperm, char *path) ++{ ++ int err; ++ ++ err = (au_br_writable(brperm) && IS_RDONLY(inode)); ++ if (!err) ++ goto out; ++ ++ err = -EINVAL; ++ pr_err("write permission for readonly mount or inode, %s\n", path); ++ ++out: ++ return err; ++} ++ ++/* ++ * returns: ++ * 0: success, the caller will add it ++ * plus: success, it is already unified, the caller should ignore it ++ * minus: error ++ */ ++static int test_add(struct super_block *sb, struct au_opt_add *add, int remount) ++{ ++ int err; ++ aufs_bindex_t bbot, bindex; ++ struct dentry *root, *h_dentry; ++ struct inode *inode, *h_inode; ++ ++ root = sb->s_root; ++ bbot = au_sbbot(sb); ++ if (unlikely(bbot >= 0 ++ && au_find_dbindex(root, add->path.dentry) >= 0)) { ++ err = 1; ++ if (!remount) { ++ err = -EINVAL; ++ pr_err("%s duplicated\n", add->pathname); ++ } ++ goto out; ++ } ++ ++ err = -ENOSPC; /* -E2BIG; */ ++ if (unlikely(AUFS_BRANCH_MAX <= add->bindex ++ || AUFS_BRANCH_MAX - 1 <= bbot)) { ++ pr_err("number of branches exceeded %s\n", add->pathname); ++ goto out; ++ } ++ ++ err = -EDOM; ++ if (unlikely(add->bindex < 0 || bbot + 1 < add->bindex)) { ++ pr_err("bad index %d\n", add->bindex); ++ goto out; ++ } ++ ++ inode = d_inode(add->path.dentry); ++ err = -ENOENT; ++ if (unlikely(!inode->i_nlink)) { ++ pr_err("no existence %s\n", add->pathname); ++ goto out; ++ } ++ ++ err = -EINVAL; ++ if (unlikely(inode->i_sb == sb)) { ++ pr_err("%s must be outside\n", add->pathname); ++ goto out; ++ } ++ ++ if (unlikely(au_test_fs_unsuppoted(inode->i_sb))) { ++ pr_err("unsupported filesystem, %s (%s)\n", ++ add->pathname, au_sbtype(inode->i_sb)); ++ goto out; ++ } ++ ++ if (unlikely(inode->i_sb->s_stack_depth)) { ++ pr_err("already stacked, %s (%s)\n", ++ add->pathname, au_sbtype(inode->i_sb)); ++ goto out; ++ } ++ ++ err = test_br(d_inode(add->path.dentry), add->perm, add->pathname); ++ if (unlikely(err)) ++ goto out; ++ ++ if (bbot < 0) ++ return 0; /* success */ ++ ++ err = -EINVAL; ++ for (bindex = 0; bindex <= bbot; bindex++) ++ if (unlikely(test_overlap(sb, add->path.dentry, ++ au_h_dptr(root, bindex)))) { ++ pr_err("%s is overlapped\n", add->pathname); ++ goto out; ++ } ++ ++ err = 0; ++ if (au_opt_test(au_mntflags(sb), WARN_PERM)) { ++ h_dentry = au_h_dptr(root, 0); ++ h_inode = d_inode(h_dentry); ++ if ((h_inode->i_mode & S_IALLUGO) != (inode->i_mode & S_IALLUGO) ++ || !uid_eq(h_inode->i_uid, inode->i_uid) ++ || !gid_eq(h_inode->i_gid, inode->i_gid)) ++ pr_warn("uid/gid/perm %s %u/%u/0%o, %u/%u/0%o\n", ++ add->pathname, ++ i_uid_read(inode), i_gid_read(inode), ++ (inode->i_mode & S_IALLUGO), ++ i_uid_read(h_inode), i_gid_read(h_inode), ++ (h_inode->i_mode & S_IALLUGO)); ++ } ++ ++out: ++ return err; ++} ++ ++/* ++ * initialize or clean the whiteouts for an adding branch ++ */ ++static int au_br_init_wh(struct super_block *sb, struct au_branch *br, ++ int new_perm) ++{ ++ int err, old_perm; ++ aufs_bindex_t bindex; ++ struct inode *h_inode; ++ struct au_wbr *wbr; ++ struct au_hinode *hdir; ++ struct dentry *h_dentry; ++ ++ err = vfsub_mnt_want_write(au_br_mnt(br)); ++ if (unlikely(err)) ++ goto out; ++ ++ wbr = br->br_wbr; ++ old_perm = br->br_perm; ++ br->br_perm = new_perm; ++ hdir = NULL; ++ h_inode = NULL; ++ bindex = au_br_index(sb, br->br_id); ++ if (0 <= bindex) { ++ hdir = au_hi(d_inode(sb->s_root), bindex); ++ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT); ++ } else { ++ h_dentry = au_br_dentry(br); ++ h_inode = d_inode(h_dentry); ++ inode_lock_nested(h_inode, AuLsc_I_PARENT); ++ } ++ if (!wbr) ++ err = au_wh_init(br, sb); ++ else { ++ wbr_wh_write_lock(wbr); ++ err = au_wh_init(br, sb); ++ wbr_wh_write_unlock(wbr); ++ } ++ if (hdir) ++ au_hn_inode_unlock(hdir); ++ else ++ inode_unlock(h_inode); ++ vfsub_mnt_drop_write(au_br_mnt(br)); ++ br->br_perm = old_perm; ++ ++ if (!err && wbr && !au_br_writable(new_perm)) { ++ au_kfree_rcu(wbr); ++ br->br_wbr = NULL; ++ } ++ ++out: ++ return err; ++} ++ ++static int au_wbr_init(struct au_branch *br, struct super_block *sb, ++ int perm) ++{ ++ int err; ++ struct kstatfs kst; ++ struct au_wbr *wbr; ++ ++ wbr = br->br_wbr; ++ au_rw_init(&wbr->wbr_wh_rwsem); ++ atomic_set(&wbr->wbr_wh_running, 0); ++ ++ /* ++ * a limit for rmdir/rename a dir ++ * cf. AUFS_MAX_NAMELEN in include/uapi/linux/aufs_type.h ++ */ ++ err = vfs_statfs(&br->br_path, &kst); ++ if (unlikely(err)) ++ goto out; ++ err = -EINVAL; ++ if (kst.f_namelen >= NAME_MAX) ++ err = au_br_init_wh(sb, br, perm); ++ else ++ pr_err("%pd(%s), unsupported namelen %ld\n", ++ au_br_dentry(br), ++ au_sbtype(au_br_dentry(br)->d_sb), kst.f_namelen); ++ ++out: ++ return err; ++} ++ ++/* initialize a new branch */ ++static int au_br_init(struct au_branch *br, struct super_block *sb, ++ struct au_opt_add *add) ++{ ++ int err; ++ struct au_branch *brbase; ++ struct file *xf; ++ struct inode *h_inode; ++ ++ err = 0; ++ br->br_perm = add->perm; ++ br->br_path = add->path; /* set first, path_get() later */ ++ spin_lock_init(&br->br_dykey_lock); ++ au_lcnt_init(&br->br_nfiles, /*release*/NULL); ++ au_lcnt_init(&br->br_count, /*release*/NULL); ++ br->br_id = au_new_br_id(sb); ++ AuDebugOn(br->br_id < 0); ++ ++ /* always, regardless the given option */ ++ err = au_dr_br_init(sb, br, &add->path); ++ if (unlikely(err)) ++ goto out_err; ++ ++ if (au_br_writable(add->perm)) { ++ err = au_wbr_init(br, sb, add->perm); ++ if (unlikely(err)) ++ goto out_err; ++ } ++ ++ if (au_opt_test(au_mntflags(sb), XINO)) { ++ brbase = au_sbr(sb, 0); ++ xf = au_xino_file(brbase->br_xino, /*idx*/-1); ++ AuDebugOn(!xf); ++ h_inode = d_inode(add->path.dentry); ++ err = au_xino_init_br(sb, br, h_inode->i_ino, &xf->f_path); ++ if (unlikely(err)) { ++ AuDebugOn(au_xino_file(br->br_xino, /*idx*/-1)); ++ goto out_err; ++ } ++ } ++ ++ sysaufs_br_init(br); ++ path_get(&br->br_path); ++ goto out; /* success */ ++ ++out_err: ++ memset(&br->br_path, 0, sizeof(br->br_path)); ++out: ++ return err; ++} ++ ++static void au_br_do_add_brp(struct au_sbinfo *sbinfo, aufs_bindex_t bindex, ++ struct au_branch *br, aufs_bindex_t bbot, ++ aufs_bindex_t amount) ++{ ++ struct au_branch **brp; ++ ++ AuRwMustWriteLock(&sbinfo->si_rwsem); ++ ++ brp = sbinfo->si_branch + bindex; ++ memmove(brp + 1, brp, sizeof(*brp) * amount); ++ *brp = br; ++ sbinfo->si_bbot++; ++ if (unlikely(bbot < 0)) ++ sbinfo->si_bbot = 0; ++} ++ ++static void au_br_do_add_hdp(struct au_dinfo *dinfo, aufs_bindex_t bindex, ++ aufs_bindex_t bbot, aufs_bindex_t amount) ++{ ++ struct au_hdentry *hdp; ++ ++ AuRwMustWriteLock(&dinfo->di_rwsem); ++ ++ hdp = au_hdentry(dinfo, bindex); ++ memmove(hdp + 1, hdp, sizeof(*hdp) * amount); ++ au_h_dentry_init(hdp); ++ dinfo->di_bbot++; ++ if (unlikely(bbot < 0)) ++ dinfo->di_btop = 0; ++} ++ ++static void au_br_do_add_hip(struct au_iinfo *iinfo, aufs_bindex_t bindex, ++ aufs_bindex_t bbot, aufs_bindex_t amount) ++{ ++ struct au_hinode *hip; ++ ++ AuRwMustWriteLock(&iinfo->ii_rwsem); ++ ++ hip = au_hinode(iinfo, bindex); ++ memmove(hip + 1, hip, sizeof(*hip) * amount); ++ au_hinode_init(hip); ++ iinfo->ii_bbot++; ++ if (unlikely(bbot < 0)) ++ iinfo->ii_btop = 0; ++} ++ ++static void au_br_do_add(struct super_block *sb, struct au_branch *br, ++ aufs_bindex_t bindex) ++{ ++ struct dentry *root, *h_dentry; ++ struct inode *root_inode, *h_inode; ++ aufs_bindex_t bbot, amount; ++ ++ root = sb->s_root; ++ root_inode = d_inode(root); ++ bbot = au_sbbot(sb); ++ amount = bbot + 1 - bindex; ++ h_dentry = au_br_dentry(br); ++ au_sbilist_lock(); ++ au_br_do_add_brp(au_sbi(sb), bindex, br, bbot, amount); ++ au_br_do_add_hdp(au_di(root), bindex, bbot, amount); ++ au_br_do_add_hip(au_ii(root_inode), bindex, bbot, amount); ++ au_set_h_dptr(root, bindex, dget(h_dentry)); ++ h_inode = d_inode(h_dentry); ++ au_set_h_iptr(root_inode, bindex, au_igrab(h_inode), /*flags*/0); ++ au_sbilist_unlock(); ++} ++ ++int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount) ++{ ++ int err; ++ aufs_bindex_t bbot, add_bindex; ++ struct dentry *root, *h_dentry; ++ struct inode *root_inode; ++ struct au_branch *add_branch; ++ ++ root = sb->s_root; ++ root_inode = d_inode(root); ++ IMustLock(root_inode); ++ IiMustWriteLock(root_inode); ++ err = test_add(sb, add, remount); ++ if (unlikely(err < 0)) ++ goto out; ++ if (err) { ++ err = 0; ++ goto out; /* success */ ++ } ++ ++ bbot = au_sbbot(sb); ++ add_branch = au_br_alloc(sb, bbot + 2, add->perm); ++ err = PTR_ERR(add_branch); ++ if (IS_ERR(add_branch)) ++ goto out; ++ ++ err = au_br_init(add_branch, sb, add); ++ if (unlikely(err)) { ++ au_br_do_free(add_branch); ++ goto out; ++ } ++ ++ add_bindex = add->bindex; ++ sysaufs_brs_del(sb, add_bindex); /* remove successors */ ++ au_br_do_add(sb, add_branch, add_bindex); ++ sysaufs_brs_add(sb, add_bindex); /* append successors */ ++ dbgaufs_brs_add(sb, add_bindex, /*topdown*/0); /* rename successors */ ++ ++ h_dentry = add->path.dentry; ++ if (!add_bindex) { ++ au_cpup_attr_all(root_inode, /*force*/1); ++ sb->s_maxbytes = h_dentry->d_sb->s_maxbytes; ++ } else ++ au_add_nlink(root_inode, d_inode(h_dentry)); ++ ++out: ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static unsigned long long au_farray_cb(struct super_block *sb, void *a, ++ unsigned long long max __maybe_unused, ++ void *arg) ++{ ++ unsigned long long n; ++ struct file **p, *f; ++ struct hlist_bl_head *files; ++ struct hlist_bl_node *pos; ++ struct au_finfo *finfo; ++ ++ n = 0; ++ p = a; ++ files = &au_sbi(sb)->si_files; ++ hlist_bl_lock(files); ++ hlist_bl_for_each_entry(finfo, pos, files, fi_hlist) { ++ f = finfo->fi_file; ++ if (file_count(f) ++ && !special_file(file_inode(f)->i_mode)) { ++ get_file(f); ++ *p++ = f; ++ n++; ++ AuDebugOn(n > max); ++ } ++ } ++ hlist_bl_unlock(files); ++ ++ return n; ++} ++ ++static struct file **au_farray_alloc(struct super_block *sb, ++ unsigned long long *max) ++{ ++ struct au_sbinfo *sbi; ++ ++ sbi = au_sbi(sb); ++ *max = au_lcnt_read(&sbi->si_nfiles, /*do_rev*/1); ++ return au_array_alloc(max, au_farray_cb, sb, /*arg*/NULL); ++} ++ ++static void au_farray_free(struct file **a, unsigned long long max) ++{ ++ unsigned long long ull; ++ ++ for (ull = 0; ull < max; ull++) ++ if (a[ull]) ++ fput(a[ull]); ++ kvfree(a); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * delete a branch ++ */ ++ ++/* to show the line number, do not make it inlined function */ ++#define AuVerbose(do_info, fmt, ...) do { \ ++ if (do_info) \ ++ pr_info(fmt, ##__VA_ARGS__); \ ++} while (0) ++ ++static int au_test_ibusy(struct inode *inode, aufs_bindex_t btop, ++ aufs_bindex_t bbot) ++{ ++ return (inode && !S_ISDIR(inode->i_mode)) || btop == bbot; ++} ++ ++static int au_test_dbusy(struct dentry *dentry, aufs_bindex_t btop, ++ aufs_bindex_t bbot) ++{ ++ return au_test_ibusy(d_inode(dentry), btop, bbot); ++} ++ ++/* ++ * test if the branch is deletable or not. ++ */ ++static int test_dentry_busy(struct dentry *root, aufs_bindex_t bindex, ++ unsigned int sigen, const unsigned int verbose) ++{ ++ int err, i, j, ndentry; ++ aufs_bindex_t btop, bbot; ++ struct au_dcsub_pages dpages; ++ struct au_dpage *dpage; ++ struct dentry *d; ++ ++ err = au_dpages_init(&dpages, GFP_NOFS); ++ if (unlikely(err)) ++ goto out; ++ err = au_dcsub_pages(&dpages, root, NULL, NULL); ++ if (unlikely(err)) ++ goto out_dpages; ++ ++ for (i = 0; !err && i < dpages.ndpage; i++) { ++ dpage = dpages.dpages + i; ++ ndentry = dpage->ndentry; ++ for (j = 0; !err && j < ndentry; j++) { ++ d = dpage->dentries[j]; ++ AuDebugOn(au_dcount(d) <= 0); ++ if (!au_digen_test(d, sigen)) { ++ di_read_lock_child(d, AuLock_IR); ++ if (unlikely(au_dbrange_test(d))) { ++ di_read_unlock(d, AuLock_IR); ++ continue; ++ } ++ } else { ++ di_write_lock_child(d); ++ if (unlikely(au_dbrange_test(d))) { ++ di_write_unlock(d); ++ continue; ++ } ++ err = au_reval_dpath(d, sigen); ++ if (!err) ++ di_downgrade_lock(d, AuLock_IR); ++ else { ++ di_write_unlock(d); ++ break; ++ } ++ } ++ ++ /* AuDbgDentry(d); */ ++ btop = au_dbtop(d); ++ bbot = au_dbbot(d); ++ if (btop <= bindex ++ && bindex <= bbot ++ && au_h_dptr(d, bindex) ++ && au_test_dbusy(d, btop, bbot)) { ++ err = -EBUSY; ++ AuVerbose(verbose, "busy %pd\n", d); ++ AuDbgDentry(d); ++ } ++ di_read_unlock(d, AuLock_IR); ++ } ++ } ++ ++out_dpages: ++ au_dpages_free(&dpages); ++out: ++ return err; ++} ++ ++static int test_inode_busy(struct super_block *sb, aufs_bindex_t bindex, ++ unsigned int sigen, const unsigned int verbose) ++{ ++ int err; ++ unsigned long long max, ull; ++ struct inode *i, **array; ++ aufs_bindex_t btop, bbot; ++ ++ array = au_iarray_alloc(sb, &max); ++ err = PTR_ERR(array); ++ if (IS_ERR(array)) ++ goto out; ++ ++ err = 0; ++ AuDbg("b%d\n", bindex); ++ for (ull = 0; !err && ull < max; ull++) { ++ i = array[ull]; ++ if (unlikely(!i)) ++ break; ++ if (i->i_ino == AUFS_ROOT_INO) ++ continue; ++ ++ /* AuDbgInode(i); */ ++ if (au_iigen(i, NULL) == sigen) ++ ii_read_lock_child(i); ++ else { ++ ii_write_lock_child(i); ++ err = au_refresh_hinode_self(i); ++ au_iigen_dec(i); ++ if (!err) ++ ii_downgrade_lock(i); ++ else { ++ ii_write_unlock(i); ++ break; ++ } ++ } ++ ++ btop = au_ibtop(i); ++ bbot = au_ibbot(i); ++ if (btop <= bindex ++ && bindex <= bbot ++ && au_h_iptr(i, bindex) ++ && au_test_ibusy(i, btop, bbot)) { ++ err = -EBUSY; ++ AuVerbose(verbose, "busy i%lu\n", i->i_ino); ++ AuDbgInode(i); ++ } ++ ii_read_unlock(i); ++ } ++ au_iarray_free(array, max); ++ ++out: ++ return err; ++} ++ ++static int test_children_busy(struct dentry *root, aufs_bindex_t bindex, ++ const unsigned int verbose) ++{ ++ int err; ++ unsigned int sigen; ++ ++ sigen = au_sigen(root->d_sb); ++ DiMustNoWaiters(root); ++ IiMustNoWaiters(d_inode(root)); ++ di_write_unlock(root); ++ err = test_dentry_busy(root, bindex, sigen, verbose); ++ if (!err) ++ err = test_inode_busy(root->d_sb, bindex, sigen, verbose); ++ di_write_lock_child(root); /* aufs_write_lock() calls ..._child() */ ++ ++ return err; ++} ++ ++static int test_dir_busy(struct file *file, aufs_bindex_t br_id, ++ struct file **to_free, int *idx) ++{ ++ int err; ++ unsigned char matched, root; ++ aufs_bindex_t bindex, bbot; ++ struct au_fidir *fidir; ++ struct au_hfile *hfile; ++ ++ err = 0; ++ root = IS_ROOT(file->f_path.dentry); ++ if (root) { ++ get_file(file); ++ to_free[*idx] = file; ++ (*idx)++; ++ goto out; ++ } ++ ++ matched = 0; ++ fidir = au_fi(file)->fi_hdir; ++ AuDebugOn(!fidir); ++ bbot = au_fbbot_dir(file); ++ for (bindex = au_fbtop(file); bindex <= bbot; bindex++) { ++ hfile = fidir->fd_hfile + bindex; ++ if (!hfile->hf_file) ++ continue; ++ ++ if (hfile->hf_br->br_id == br_id) { ++ matched = 1; ++ break; ++ } ++ } ++ if (matched) ++ err = -EBUSY; ++ ++out: ++ return err; ++} ++ ++static int test_file_busy(struct super_block *sb, aufs_bindex_t br_id, ++ struct file **to_free, int opened) ++{ ++ int err, idx; ++ unsigned long long ull, max; ++ aufs_bindex_t btop; ++ struct file *file, **array; ++ struct dentry *root; ++ struct au_hfile *hfile; ++ ++ array = au_farray_alloc(sb, &max); ++ err = PTR_ERR(array); ++ if (IS_ERR(array)) ++ goto out; ++ ++ err = 0; ++ idx = 0; ++ root = sb->s_root; ++ di_write_unlock(root); ++ for (ull = 0; ull < max; ull++) { ++ file = array[ull]; ++ if (unlikely(!file)) ++ break; ++ ++ /* AuDbg("%pD\n", file); */ ++ fi_read_lock(file); ++ btop = au_fbtop(file); ++ if (!d_is_dir(file->f_path.dentry)) { ++ hfile = &au_fi(file)->fi_htop; ++ if (hfile->hf_br->br_id == br_id) ++ err = -EBUSY; ++ } else ++ err = test_dir_busy(file, br_id, to_free, &idx); ++ fi_read_unlock(file); ++ if (unlikely(err)) ++ break; ++ } ++ di_write_lock_child(root); ++ au_farray_free(array, max); ++ AuDebugOn(idx > opened); ++ ++out: ++ return err; ++} ++ ++static void br_del_file(struct file **to_free, unsigned long long opened, ++ aufs_bindex_t br_id) ++{ ++ unsigned long long ull; ++ aufs_bindex_t bindex, btop, bbot, bfound; ++ struct file *file; ++ struct au_fidir *fidir; ++ struct au_hfile *hfile; ++ ++ for (ull = 0; ull < opened; ull++) { ++ file = to_free[ull]; ++ if (unlikely(!file)) ++ break; ++ ++ /* AuDbg("%pD\n", file); */ ++ AuDebugOn(!d_is_dir(file->f_path.dentry)); ++ bfound = -1; ++ fidir = au_fi(file)->fi_hdir; ++ AuDebugOn(!fidir); ++ fi_write_lock(file); ++ btop = au_fbtop(file); ++ bbot = au_fbbot_dir(file); ++ for (bindex = btop; bindex <= bbot; bindex++) { ++ hfile = fidir->fd_hfile + bindex; ++ if (!hfile->hf_file) ++ continue; ++ ++ if (hfile->hf_br->br_id == br_id) { ++ bfound = bindex; ++ break; ++ } ++ } ++ AuDebugOn(bfound < 0); ++ au_set_h_fptr(file, bfound, NULL); ++ if (bfound == btop) { ++ for (btop++; btop <= bbot; btop++) ++ if (au_hf_dir(file, btop)) { ++ au_set_fbtop(file, btop); ++ break; ++ } ++ } ++ fi_write_unlock(file); ++ } ++} ++ ++static void au_br_do_del_brp(struct au_sbinfo *sbinfo, ++ const aufs_bindex_t bindex, ++ const aufs_bindex_t bbot) ++{ ++ struct au_branch **brp, **p; ++ ++ AuRwMustWriteLock(&sbinfo->si_rwsem); ++ ++ brp = sbinfo->si_branch + bindex; ++ if (bindex < bbot) ++ memmove(brp, brp + 1, sizeof(*brp) * (bbot - bindex)); ++ sbinfo->si_branch[0 + bbot] = NULL; ++ sbinfo->si_bbot--; ++ ++ p = au_krealloc(sbinfo->si_branch, sizeof(*p) * bbot, AuGFP_SBILIST, ++ /*may_shrink*/1); ++ if (p) ++ sbinfo->si_branch = p; ++ /* harmless error */ ++} ++ ++static void au_br_do_del_hdp(struct au_dinfo *dinfo, const aufs_bindex_t bindex, ++ const aufs_bindex_t bbot) ++{ ++ struct au_hdentry *hdp, *p; ++ ++ AuRwMustWriteLock(&dinfo->di_rwsem); ++ ++ hdp = au_hdentry(dinfo, bindex); ++ if (bindex < bbot) ++ memmove(hdp, hdp + 1, sizeof(*hdp) * (bbot - bindex)); ++ /* au_h_dentry_init(au_hdentry(dinfo, bbot); */ ++ dinfo->di_bbot--; ++ ++ p = au_krealloc(dinfo->di_hdentry, sizeof(*p) * bbot, AuGFP_SBILIST, ++ /*may_shrink*/1); ++ if (p) ++ dinfo->di_hdentry = p; ++ /* harmless error */ ++} ++ ++static void au_br_do_del_hip(struct au_iinfo *iinfo, const aufs_bindex_t bindex, ++ const aufs_bindex_t bbot) ++{ ++ struct au_hinode *hip, *p; ++ ++ AuRwMustWriteLock(&iinfo->ii_rwsem); ++ ++ hip = au_hinode(iinfo, bindex); ++ if (bindex < bbot) ++ memmove(hip, hip + 1, sizeof(*hip) * (bbot - bindex)); ++ /* au_hinode_init(au_hinode(iinfo, bbot)); */ ++ iinfo->ii_bbot--; ++ ++ p = au_krealloc(iinfo->ii_hinode, sizeof(*p) * bbot, AuGFP_SBILIST, ++ /*may_shrink*/1); ++ if (p) ++ iinfo->ii_hinode = p; ++ /* harmless error */ ++} ++ ++static void au_br_do_del(struct super_block *sb, aufs_bindex_t bindex, ++ struct au_branch *br) ++{ ++ aufs_bindex_t bbot; ++ struct au_sbinfo *sbinfo; ++ struct dentry *root, *h_root; ++ struct inode *inode, *h_inode; ++ struct au_hinode *hinode; ++ ++ SiMustWriteLock(sb); ++ ++ root = sb->s_root; ++ inode = d_inode(root); ++ sbinfo = au_sbi(sb); ++ bbot = sbinfo->si_bbot; ++ ++ h_root = au_h_dptr(root, bindex); ++ hinode = au_hi(inode, bindex); ++ h_inode = au_igrab(hinode->hi_inode); ++ au_hiput(hinode); ++ ++ au_sbilist_lock(); ++ au_br_do_del_brp(sbinfo, bindex, bbot); ++ au_br_do_del_hdp(au_di(root), bindex, bbot); ++ au_br_do_del_hip(au_ii(inode), bindex, bbot); ++ au_sbilist_unlock(); ++ ++ /* ignore an error */ ++ au_dr_br_fin(sb, br); /* always, regardless the mount option */ ++ ++ dput(h_root); ++ iput(h_inode); ++ au_br_do_free(br); ++} ++ ++static unsigned long long empty_cb(struct super_block *sb, void *array, ++ unsigned long long max, void *arg) ++{ ++ return max; ++} ++ ++int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount) ++{ ++ int err, rerr, i; ++ unsigned long long opened; ++ unsigned int mnt_flags; ++ aufs_bindex_t bindex, bbot, br_id; ++ unsigned char do_wh, verbose; ++ struct au_branch *br; ++ struct au_wbr *wbr; ++ struct dentry *root; ++ struct file **to_free; ++ ++ err = 0; ++ opened = 0; ++ to_free = NULL; ++ root = sb->s_root; ++ bindex = au_find_dbindex(root, del->h_path.dentry); ++ if (bindex < 0) { ++ if (remount) ++ goto out; /* success */ ++ err = -ENOENT; ++ pr_err("%s no such branch\n", del->pathname); ++ goto out; ++ } ++ AuDbg("bindex b%d\n", bindex); ++ ++ err = -EBUSY; ++ mnt_flags = au_mntflags(sb); ++ verbose = !!au_opt_test(mnt_flags, VERBOSE); ++ bbot = au_sbbot(sb); ++ if (unlikely(!bbot)) { ++ AuVerbose(verbose, "no more branches left\n"); ++ goto out; ++ } ++ ++ br = au_sbr(sb, bindex); ++ AuDebugOn(!path_equal(&br->br_path, &del->h_path)); ++ if (unlikely(au_lcnt_read(&br->br_count, /*do_rev*/1))) { ++ AuVerbose(verbose, "br %pd2 is busy now\n", del->h_path.dentry); ++ goto out; ++ } ++ ++ br_id = br->br_id; ++ opened = au_lcnt_read(&br->br_nfiles, /*do_rev*/1); ++ if (unlikely(opened)) { ++ to_free = au_array_alloc(&opened, empty_cb, sb, NULL); ++ err = PTR_ERR(to_free); ++ if (IS_ERR(to_free)) ++ goto out; ++ ++ err = test_file_busy(sb, br_id, to_free, opened); ++ if (unlikely(err)) { ++ AuVerbose(verbose, "%llu file(s) opened\n", opened); ++ goto out; ++ } ++ } ++ ++ wbr = br->br_wbr; ++ do_wh = wbr && (wbr->wbr_whbase || wbr->wbr_plink || wbr->wbr_orph); ++ if (do_wh) { ++ /* instead of WbrWhMustWriteLock(wbr) */ ++ SiMustWriteLock(sb); ++ for (i = 0; i < AuBrWh_Last; i++) { ++ dput(wbr->wbr_wh[i]); ++ wbr->wbr_wh[i] = NULL; ++ } ++ } ++ ++ err = test_children_busy(root, bindex, verbose); ++ if (unlikely(err)) { ++ if (do_wh) ++ goto out_wh; ++ goto out; ++ } ++ ++ err = 0; ++ if (to_free) { ++ /* ++ * now we confirmed the branch is deletable. ++ * let's free the remaining opened dirs on the branch. ++ */ ++ di_write_unlock(root); ++ br_del_file(to_free, opened, br_id); ++ di_write_lock_child(root); ++ } ++ ++ sysaufs_brs_del(sb, bindex); /* remove successors */ ++ dbgaufs_xino_del(br); /* remove one */ ++ au_br_do_del(sb, bindex, br); ++ sysaufs_brs_add(sb, bindex); /* append successors */ ++ dbgaufs_brs_add(sb, bindex, /*topdown*/1); /* rename successors */ ++ ++ if (!bindex) { ++ au_cpup_attr_all(d_inode(root), /*force*/1); ++ sb->s_maxbytes = au_sbr_sb(sb, 0)->s_maxbytes; ++ } else ++ au_sub_nlink(d_inode(root), d_inode(del->h_path.dentry)); ++ if (au_opt_test(mnt_flags, PLINK)) ++ au_plink_half_refresh(sb, br_id); ++ ++ goto out; /* success */ ++ ++out_wh: ++ /* revert */ ++ rerr = au_br_init_wh(sb, br, br->br_perm); ++ if (rerr) ++ pr_warn("failed re-creating base whiteout, %s. (%d)\n", ++ del->pathname, rerr); ++out: ++ if (to_free) ++ au_farray_free(to_free, opened); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int au_ibusy(struct super_block *sb, struct aufs_ibusy __user *arg) ++{ ++ int err; ++ aufs_bindex_t btop, bbot; ++ struct aufs_ibusy ibusy; ++ struct inode *inode, *h_inode; ++ ++ err = -EPERM; ++ if (unlikely(!capable(CAP_SYS_ADMIN))) ++ goto out; ++ ++ err = copy_from_user(&ibusy, arg, sizeof(ibusy)); ++ if (!err) ++ /* VERIFY_WRITE */ ++ err = !access_ok(&arg->h_ino, sizeof(arg->h_ino)); ++ if (unlikely(err)) { ++ err = -EFAULT; ++ AuTraceErr(err); ++ goto out; ++ } ++ ++ err = -EINVAL; ++ si_read_lock(sb, AuLock_FLUSH); ++ if (unlikely(ibusy.bindex < 0 || ibusy.bindex > au_sbbot(sb))) ++ goto out_unlock; ++ ++ err = 0; ++ ibusy.h_ino = 0; /* invalid */ ++ inode = ilookup(sb, ibusy.ino); ++ if (!inode ++ || inode->i_ino == AUFS_ROOT_INO ++ || au_is_bad_inode(inode)) ++ goto out_unlock; ++ ++ ii_read_lock_child(inode); ++ btop = au_ibtop(inode); ++ bbot = au_ibbot(inode); ++ if (btop <= ibusy.bindex && ibusy.bindex <= bbot) { ++ h_inode = au_h_iptr(inode, ibusy.bindex); ++ if (h_inode && au_test_ibusy(inode, btop, bbot)) ++ ibusy.h_ino = h_inode->i_ino; ++ } ++ ii_read_unlock(inode); ++ iput(inode); ++ ++out_unlock: ++ si_read_unlock(sb); ++ if (!err) { ++ err = __put_user(ibusy.h_ino, &arg->h_ino); ++ if (unlikely(err)) { ++ err = -EFAULT; ++ AuTraceErr(err); ++ } ++ } ++out: ++ return err; ++} ++ ++long au_ibusy_ioctl(struct file *file, unsigned long arg) ++{ ++ return au_ibusy(file->f_path.dentry->d_sb, (void __user *)arg); ++} ++ ++#ifdef CONFIG_COMPAT ++long au_ibusy_compat_ioctl(struct file *file, unsigned long arg) ++{ ++ return au_ibusy(file->f_path.dentry->d_sb, compat_ptr(arg)); ++} ++#endif ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * change a branch permission ++ */ ++ ++static void au_warn_ima(void) ++{ ++#ifdef CONFIG_IMA ++ /* since it doesn't support mark_files_ro() */ ++ AuWarn1("RW -> RO makes IMA to produce wrong message\n"); ++#endif ++} ++ ++static int do_need_sigen_inc(int a, int b) ++{ ++ return au_br_whable(a) && !au_br_whable(b); ++} ++ ++static int need_sigen_inc(int old, int new) ++{ ++ return do_need_sigen_inc(old, new) ++ || do_need_sigen_inc(new, old); ++} ++ ++static int au_br_mod_files_ro(struct super_block *sb, aufs_bindex_t bindex) ++{ ++ int err, do_warn; ++ unsigned int mnt_flags; ++ unsigned long long ull, max; ++ aufs_bindex_t br_id; ++ unsigned char verbose, writer; ++ struct file *file, *hf, **array; ++ struct au_hfile *hfile; ++ struct inode *h_inode; ++ ++ mnt_flags = au_mntflags(sb); ++ verbose = !!au_opt_test(mnt_flags, VERBOSE); ++ ++ array = au_farray_alloc(sb, &max); ++ err = PTR_ERR(array); ++ if (IS_ERR(array)) ++ goto out; ++ ++ do_warn = 0; ++ br_id = au_sbr_id(sb, bindex); ++ for (ull = 0; ull < max; ull++) { ++ file = array[ull]; ++ if (unlikely(!file)) ++ break; ++ ++ /* AuDbg("%pD\n", file); */ ++ fi_read_lock(file); ++ if (unlikely(au_test_mmapped(file))) { ++ err = -EBUSY; ++ AuVerbose(verbose, "mmapped %pD\n", file); ++ AuDbgFile(file); ++ FiMustNoWaiters(file); ++ fi_read_unlock(file); ++ goto out_array; ++ } ++ ++ hfile = &au_fi(file)->fi_htop; ++ hf = hfile->hf_file; ++ if (!d_is_reg(file->f_path.dentry) ++ || !(file->f_mode & FMODE_WRITE) ++ || hfile->hf_br->br_id != br_id ++ || !(hf->f_mode & FMODE_WRITE)) ++ array[ull] = NULL; ++ else { ++ do_warn = 1; ++ get_file(file); ++ } ++ ++ FiMustNoWaiters(file); ++ fi_read_unlock(file); ++ fput(file); ++ } ++ ++ err = 0; ++ if (do_warn) ++ au_warn_ima(); ++ ++ for (ull = 0; ull < max; ull++) { ++ file = array[ull]; ++ if (!file) ++ continue; ++ ++ /* todo: already flushed? */ ++ /* ++ * fs/super.c:mark_files_ro() is gone, but aufs keeps its ++ * approach which resets f_mode and calls mnt_drop_write() and ++ * file_release_write() for each file, because the branch ++ * attribute in aufs world is totally different from the native ++ * fs rw/ro mode. ++ */ ++ /* fi_read_lock(file); */ ++ hfile = &au_fi(file)->fi_htop; ++ hf = hfile->hf_file; ++ /* fi_read_unlock(file); */ ++ spin_lock(&hf->f_lock); ++ writer = !!(hf->f_mode & FMODE_WRITER); ++ hf->f_mode &= ~(FMODE_WRITE | FMODE_WRITER); ++ spin_unlock(&hf->f_lock); ++ if (writer) { ++ h_inode = file_inode(hf); ++ put_write_access(h_inode); ++ __mnt_drop_write(hf->f_path.mnt); ++ if ((hf->f_mode & (FMODE_READ | FMODE_WRITE)) ++ == FMODE_READ) ++ i_readcount_inc(h_inode); ++ } ++ } ++ ++out_array: ++ au_farray_free(array, max); ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount, ++ int *do_refresh) ++{ ++ int err, rerr; ++ aufs_bindex_t bindex; ++ struct dentry *root; ++ struct au_branch *br; ++ struct au_br_fhsm *bf; ++ ++ root = sb->s_root; ++ bindex = au_find_dbindex(root, mod->h_root); ++ if (bindex < 0) { ++ if (remount) ++ return 0; /* success */ ++ err = -ENOENT; ++ pr_err("%s no such branch\n", mod->path); ++ goto out; ++ } ++ AuDbg("bindex b%d\n", bindex); ++ ++ err = test_br(d_inode(mod->h_root), mod->perm, mod->path); ++ if (unlikely(err)) ++ goto out; ++ ++ br = au_sbr(sb, bindex); ++ AuDebugOn(mod->h_root != au_br_dentry(br)); ++ if (br->br_perm == mod->perm) ++ return 0; /* success */ ++ ++ /* pre-allocate for non-fhsm --> fhsm */ ++ bf = NULL; ++ if (!au_br_fhsm(br->br_perm) && au_br_fhsm(mod->perm)) { ++ err = au_fhsm_br_alloc(br); ++ if (unlikely(err)) ++ goto out; ++ bf = br->br_fhsm; ++ br->br_fhsm = NULL; ++ } ++ ++ if (au_br_writable(br->br_perm)) { ++ /* remove whiteout base */ ++ err = au_br_init_wh(sb, br, mod->perm); ++ if (unlikely(err)) ++ goto out_bf; ++ ++ if (!au_br_writable(mod->perm)) { ++ /* rw --> ro, file might be mmapped */ ++ DiMustNoWaiters(root); ++ IiMustNoWaiters(d_inode(root)); ++ di_write_unlock(root); ++ err = au_br_mod_files_ro(sb, bindex); ++ /* aufs_write_lock() calls ..._child() */ ++ di_write_lock_child(root); ++ ++ if (unlikely(err)) { ++ rerr = -ENOMEM; ++ br->br_wbr = kzalloc(sizeof(*br->br_wbr), ++ GFP_NOFS); ++ if (br->br_wbr) ++ rerr = au_wbr_init(br, sb, br->br_perm); ++ if (unlikely(rerr)) { ++ AuIOErr("nested error %d (%d)\n", ++ rerr, err); ++ br->br_perm = mod->perm; ++ } ++ } ++ } ++ } else if (au_br_writable(mod->perm)) { ++ /* ro --> rw */ ++ err = -ENOMEM; ++ br->br_wbr = kzalloc(sizeof(*br->br_wbr), GFP_NOFS); ++ if (br->br_wbr) { ++ err = au_wbr_init(br, sb, mod->perm); ++ if (unlikely(err)) { ++ au_kfree_rcu(br->br_wbr); ++ br->br_wbr = NULL; ++ } ++ } ++ } ++ if (unlikely(err)) ++ goto out_bf; ++ ++ if (au_br_fhsm(br->br_perm)) { ++ if (!au_br_fhsm(mod->perm)) { ++ /* fhsm --> non-fhsm */ ++ au_br_fhsm_fin(br->br_fhsm); ++ au_kfree_rcu(br->br_fhsm); ++ br->br_fhsm = NULL; ++ } ++ } else if (au_br_fhsm(mod->perm)) ++ /* non-fhsm --> fhsm */ ++ br->br_fhsm = bf; ++ ++ *do_refresh |= need_sigen_inc(br->br_perm, mod->perm); ++ br->br_perm = mod->perm; ++ goto out; /* success */ ++ ++out_bf: ++ au_kfree_try_rcu(bf); ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++int au_br_stfs(struct au_branch *br, struct aufs_stfs *stfs) ++{ ++ int err; ++ struct kstatfs kstfs; ++ ++ err = vfs_statfs(&br->br_path, &kstfs); ++ if (!err) { ++ stfs->f_blocks = kstfs.f_blocks; ++ stfs->f_bavail = kstfs.f_bavail; ++ stfs->f_files = kstfs.f_files; ++ stfs->f_ffree = kstfs.f_ffree; ++ } ++ ++ return err; ++} +diff -Nurp linux-5.4/fs/aufs/branch.h linux-5.4-aufs/fs/aufs/branch.h +--- linux-5.4/fs/aufs/branch.h 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/branch.h 2019-11-28 01:25:59.062925618 +0200 +@@ -0,0 +1,353 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * branch filesystems and xino for them ++ */ ++ ++#ifndef __AUFS_BRANCH_H__ ++#define __AUFS_BRANCH_H__ ++ ++#ifdef __KERNEL__ ++ ++#include ++#include "dirren.h" ++#include "dynop.h" ++#include "lcnt.h" ++#include "rwsem.h" ++#include "super.h" ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* a xino file */ ++struct au_xino { ++ struct file **xi_file; ++ unsigned int xi_nfile; ++ ++ struct { ++ spinlock_t spin; ++ ino_t *array; ++ int total; ++ /* reserved for future use */ ++ /* unsigned long *bitmap; */ ++ wait_queue_head_t wqh; ++ } xi_nondir; ++ ++ struct mutex xi_mtx; /* protects xi_file array */ ++ struct hlist_bl_head xi_writing; ++ ++ atomic_t xi_truncating; ++ ++ struct kref xi_kref; ++}; ++ ++/* File-based Hierarchical Storage Management */ ++struct au_br_fhsm { ++#ifdef CONFIG_AUFS_FHSM ++ struct mutex bf_lock; ++ unsigned long bf_jiffy; ++ struct aufs_stfs bf_stfs; ++ int bf_readable; ++#endif ++}; ++ ++/* members for writable branch only */ ++enum {AuBrWh_BASE, AuBrWh_PLINK, AuBrWh_ORPH, AuBrWh_Last}; ++struct au_wbr { ++ struct au_rwsem wbr_wh_rwsem; ++ struct dentry *wbr_wh[AuBrWh_Last]; ++ atomic_t wbr_wh_running; ++#define wbr_whbase wbr_wh[AuBrWh_BASE] /* whiteout base */ ++#define wbr_plink wbr_wh[AuBrWh_PLINK] /* pseudo-link dir */ ++#define wbr_orph wbr_wh[AuBrWh_ORPH] /* dir for orphans */ ++ ++ /* mfs mode */ ++ unsigned long long wbr_bytes; ++}; ++ ++/* ext2 has 3 types of operations at least, ext3 has 4 */ ++#define AuBrDynOp (AuDyLast * 4) ++ ++#ifdef CONFIG_AUFS_HFSNOTIFY ++/* support for asynchronous destruction */ ++struct au_br_hfsnotify { ++ struct fsnotify_group *hfsn_group; ++}; ++#endif ++ ++/* sysfs entries */ ++struct au_brsysfs { ++ char name[16]; ++ struct attribute attr; ++}; ++ ++enum { ++ AuBrSysfs_BR, ++ AuBrSysfs_BRID, ++ AuBrSysfs_Last ++}; ++ ++/* protected by superblock rwsem */ ++struct au_branch { ++ struct au_xino *br_xino; ++ ++ aufs_bindex_t br_id; ++ ++ int br_perm; ++ struct path br_path; ++ spinlock_t br_dykey_lock; ++ struct au_dykey *br_dykey[AuBrDynOp]; ++ au_lcnt_t br_nfiles; /* opened files */ ++ au_lcnt_t br_count; /* in-use for other */ ++ ++ struct au_wbr *br_wbr; ++ struct au_br_fhsm *br_fhsm; ++ ++#ifdef CONFIG_AUFS_HFSNOTIFY ++ struct au_br_hfsnotify *br_hfsn; ++#endif ++ ++#ifdef CONFIG_SYSFS ++ /* entries under sysfs per mount-point */ ++ struct au_brsysfs br_sysfs[AuBrSysfs_Last]; ++#endif ++ ++#ifdef CONFIG_DEBUG_FS ++ struct dentry *br_dbgaufs; /* xino */ ++#endif ++ ++ struct au_dr_br br_dirren; ++}; ++ ++/* ---------------------------------------------------------------------- */ ++ ++static inline struct vfsmount *au_br_mnt(struct au_branch *br) ++{ ++ return br->br_path.mnt; ++} ++ ++static inline struct dentry *au_br_dentry(struct au_branch *br) ++{ ++ return br->br_path.dentry; ++} ++ ++static inline struct super_block *au_br_sb(struct au_branch *br) ++{ ++ return au_br_mnt(br)->mnt_sb; ++} ++ ++static inline int au_br_rdonly(struct au_branch *br) ++{ ++ return (sb_rdonly(au_br_sb(br)) ++ || !au_br_writable(br->br_perm)) ++ ? -EROFS : 0; ++} ++ ++static inline int au_br_hnotifyable(int brperm __maybe_unused) ++{ ++#ifdef CONFIG_AUFS_HNOTIFY ++ return !(brperm & AuBrPerm_RR); ++#else ++ return 0; ++#endif ++} ++ ++static inline int au_br_test_oflag(int oflag, struct au_branch *br) ++{ ++ int err, exec_flag; ++ ++ err = 0; ++ exec_flag = oflag & __FMODE_EXEC; ++ if (unlikely(exec_flag && path_noexec(&br->br_path))) ++ err = -EACCES; ++ ++ return err; ++} ++ ++static inline void au_xino_get(struct au_branch *br) ++{ ++ struct au_xino *xi; ++ ++ xi = br->br_xino; ++ if (xi) ++ kref_get(&xi->xi_kref); ++} ++ ++static inline int au_xino_count(struct au_branch *br) ++{ ++ int v; ++ struct au_xino *xi; ++ ++ v = 0; ++ xi = br->br_xino; ++ if (xi) ++ v = kref_read(&xi->xi_kref); ++ ++ return v; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* branch.c */ ++struct au_sbinfo; ++void au_br_free(struct au_sbinfo *sinfo); ++int au_br_index(struct super_block *sb, aufs_bindex_t br_id); ++struct au_opt_add; ++int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount); ++struct au_opt_del; ++int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount); ++long au_ibusy_ioctl(struct file *file, unsigned long arg); ++#ifdef CONFIG_COMPAT ++long au_ibusy_compat_ioctl(struct file *file, unsigned long arg); ++#endif ++struct au_opt_mod; ++int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount, ++ int *do_refresh); ++struct aufs_stfs; ++int au_br_stfs(struct au_branch *br, struct aufs_stfs *stfs); ++ ++/* xino.c */ ++static const loff_t au_loff_max = LLONG_MAX; ++ ++aufs_bindex_t au_xi_root(struct super_block *sb, struct dentry *dentry); ++struct file *au_xino_create(struct super_block *sb, char *fpath, int silent, ++ int wbrtop); ++struct file *au_xino_create2(struct super_block *sb, struct path *base, ++ struct file *copy_src); ++struct au_xi_new { ++ struct au_xino *xi; /* switch between xino and xigen */ ++ int idx; ++ struct path *base; ++ struct file *copy_src; ++}; ++struct file *au_xi_new(struct super_block *sb, struct au_xi_new *xinew); ++ ++int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, ++ ino_t *ino); ++int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, ++ ino_t ino); ++ssize_t xino_fread(vfs_readf_t func, struct file *file, void *buf, size_t size, ++ loff_t *pos); ++ssize_t xino_fwrite(vfs_writef_t func, struct file *file, void *buf, ++ size_t size, loff_t *pos); ++ ++int au_xib_trunc(struct super_block *sb); ++int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex, int idx_begin); ++ ++struct au_xino *au_xino_alloc(unsigned int nfile); ++int au_xino_put(struct au_branch *br); ++struct file *au_xino_file1(struct au_xino *xi); ++ ++struct au_opt_xino; ++void au_xino_clr(struct super_block *sb); ++int au_xino_set(struct super_block *sb, struct au_opt_xino *xiopt, int remount); ++struct file *au_xino_def(struct super_block *sb); ++int au_xino_init_br(struct super_block *sb, struct au_branch *br, ino_t hino, ++ struct path *base); ++ ++ino_t au_xino_new_ino(struct super_block *sb); ++void au_xino_delete_inode(struct inode *inode, const int unlinked); ++ ++void au_xinondir_leave(struct super_block *sb, aufs_bindex_t bindex, ++ ino_t h_ino, int idx); ++int au_xinondir_enter(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, ++ int *idx); ++ ++int au_xino_path(struct seq_file *seq, struct file *file); ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* @idx is signed to accept -1 meaning the first file */ ++static inline struct file *au_xino_file(struct au_xino *xi, int idx) ++{ ++ struct file *file; ++ ++ file = NULL; ++ if (!xi) ++ goto out; ++ ++ if (idx >= 0) { ++ if (idx < xi->xi_nfile) ++ file = xi->xi_file[idx]; ++ } else ++ file = au_xino_file1(xi); ++ ++out: ++ return file; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* Superblock to branch */ ++static inline ++aufs_bindex_t au_sbr_id(struct super_block *sb, aufs_bindex_t bindex) ++{ ++ return au_sbr(sb, bindex)->br_id; ++} ++ ++static inline ++struct vfsmount *au_sbr_mnt(struct super_block *sb, aufs_bindex_t bindex) ++{ ++ return au_br_mnt(au_sbr(sb, bindex)); ++} ++ ++static inline ++struct super_block *au_sbr_sb(struct super_block *sb, aufs_bindex_t bindex) ++{ ++ return au_br_sb(au_sbr(sb, bindex)); ++} ++ ++static inline int au_sbr_perm(struct super_block *sb, aufs_bindex_t bindex) ++{ ++ return au_sbr(sb, bindex)->br_perm; ++} ++ ++static inline int au_sbr_whable(struct super_block *sb, aufs_bindex_t bindex) ++{ ++ return au_br_whable(au_sbr_perm(sb, bindex)); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++#define wbr_wh_read_lock(wbr) au_rw_read_lock(&(wbr)->wbr_wh_rwsem) ++#define wbr_wh_write_lock(wbr) au_rw_write_lock(&(wbr)->wbr_wh_rwsem) ++#define wbr_wh_read_trylock(wbr) au_rw_read_trylock(&(wbr)->wbr_wh_rwsem) ++#define wbr_wh_write_trylock(wbr) au_rw_write_trylock(&(wbr)->wbr_wh_rwsem) ++/* ++#define wbr_wh_read_trylock_nested(wbr) \ ++ au_rw_read_trylock_nested(&(wbr)->wbr_wh_rwsem) ++#define wbr_wh_write_trylock_nested(wbr) \ ++ au_rw_write_trylock_nested(&(wbr)->wbr_wh_rwsem) ++*/ ++ ++#define wbr_wh_read_unlock(wbr) au_rw_read_unlock(&(wbr)->wbr_wh_rwsem) ++#define wbr_wh_write_unlock(wbr) au_rw_write_unlock(&(wbr)->wbr_wh_rwsem) ++#define wbr_wh_downgrade_lock(wbr) au_rw_dgrade_lock(&(wbr)->wbr_wh_rwsem) ++ ++#define WbrWhMustNoWaiters(wbr) AuRwMustNoWaiters(&(wbr)->wbr_wh_rwsem) ++#define WbrWhMustAnyLock(wbr) AuRwMustAnyLock(&(wbr)->wbr_wh_rwsem) ++#define WbrWhMustWriteLock(wbr) AuRwMustWriteLock(&(wbr)->wbr_wh_rwsem) ++ ++/* ---------------------------------------------------------------------- */ ++ ++#ifdef CONFIG_AUFS_FHSM ++static inline void au_br_fhsm_init(struct au_br_fhsm *brfhsm) ++{ ++ mutex_init(&brfhsm->bf_lock); ++ brfhsm->bf_jiffy = 0; ++ brfhsm->bf_readable = 0; ++} ++ ++static inline void au_br_fhsm_fin(struct au_br_fhsm *brfhsm) ++{ ++ mutex_destroy(&brfhsm->bf_lock); ++} ++#else ++AuStubVoid(au_br_fhsm_init, struct au_br_fhsm *brfhsm) ++AuStubVoid(au_br_fhsm_fin, struct au_br_fhsm *brfhsm) ++#endif ++ ++#endif /* __KERNEL__ */ ++#endif /* __AUFS_BRANCH_H__ */ +diff -Nurp linux-5.4/fs/aufs/cpup.c linux-5.4-aufs/fs/aufs/cpup.c +--- linux-5.4/fs/aufs/cpup.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/cpup.c 2019-11-28 01:25:59.063925618 +0200 +@@ -0,0 +1,1445 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * copy-up functions, see wbr_policy.c for copy-down ++ */ ++ ++#include ++#include ++#include ++#include "aufs.h" ++ ++void au_cpup_attr_flags(struct inode *dst, unsigned int iflags) ++{ ++ const unsigned int mask = S_DEAD | S_SWAPFILE | S_PRIVATE ++ | S_NOATIME | S_NOCMTIME | S_AUTOMOUNT; ++ ++ BUILD_BUG_ON(sizeof(iflags) != sizeof(dst->i_flags)); ++ ++ dst->i_flags |= iflags & ~mask; ++ if (au_test_fs_notime(dst->i_sb)) ++ dst->i_flags |= S_NOATIME | S_NOCMTIME; ++} ++ ++void au_cpup_attr_timesizes(struct inode *inode) ++{ ++ struct inode *h_inode; ++ ++ h_inode = au_h_iptr(inode, au_ibtop(inode)); ++ fsstack_copy_attr_times(inode, h_inode); ++ fsstack_copy_inode_size(inode, h_inode); ++} ++ ++void au_cpup_attr_nlink(struct inode *inode, int force) ++{ ++ struct inode *h_inode; ++ struct super_block *sb; ++ aufs_bindex_t bindex, bbot; ++ ++ sb = inode->i_sb; ++ bindex = au_ibtop(inode); ++ h_inode = au_h_iptr(inode, bindex); ++ if (!force ++ && !S_ISDIR(h_inode->i_mode) ++ && au_opt_test(au_mntflags(sb), PLINK) ++ && au_plink_test(inode)) ++ return; ++ ++ /* ++ * 0 can happen in revalidating. ++ * h_inode->i_mutex may not be held here, but it is harmless since once ++ * i_nlink reaches 0, it will never become positive except O_TMPFILE ++ * case. ++ * todo: O_TMPFILE+linkat(AT_SYMLINK_FOLLOW) bypassing aufs may cause ++ * the incorrect link count. ++ */ ++ set_nlink(inode, h_inode->i_nlink); ++ ++ /* ++ * fewer nlink makes find(1) noisy, but larger nlink doesn't. ++ * it may includes whplink directory. ++ */ ++ if (S_ISDIR(h_inode->i_mode)) { ++ bbot = au_ibbot(inode); ++ for (bindex++; bindex <= bbot; bindex++) { ++ h_inode = au_h_iptr(inode, bindex); ++ if (h_inode) ++ au_add_nlink(inode, h_inode); ++ } ++ } ++} ++ ++void au_cpup_attr_changeable(struct inode *inode) ++{ ++ struct inode *h_inode; ++ ++ h_inode = au_h_iptr(inode, au_ibtop(inode)); ++ inode->i_mode = h_inode->i_mode; ++ inode->i_uid = h_inode->i_uid; ++ inode->i_gid = h_inode->i_gid; ++ au_cpup_attr_timesizes(inode); ++ au_cpup_attr_flags(inode, h_inode->i_flags); ++} ++ ++void au_cpup_igen(struct inode *inode, struct inode *h_inode) ++{ ++ struct au_iinfo *iinfo = au_ii(inode); ++ ++ IiMustWriteLock(inode); ++ ++ iinfo->ii_higen = h_inode->i_generation; ++ iinfo->ii_hsb1 = h_inode->i_sb; ++} ++ ++void au_cpup_attr_all(struct inode *inode, int force) ++{ ++ struct inode *h_inode; ++ ++ h_inode = au_h_iptr(inode, au_ibtop(inode)); ++ au_cpup_attr_changeable(inode); ++ if (inode->i_nlink > 0) ++ au_cpup_attr_nlink(inode, force); ++ inode->i_rdev = h_inode->i_rdev; ++ inode->i_blkbits = h_inode->i_blkbits; ++ au_cpup_igen(inode, h_inode); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* Note: dt_dentry and dt_h_dentry are not dget/dput-ed */ ++ ++/* keep the timestamps of the parent dir when cpup */ ++void au_dtime_store(struct au_dtime *dt, struct dentry *dentry, ++ struct path *h_path) ++{ ++ struct inode *h_inode; ++ ++ dt->dt_dentry = dentry; ++ dt->dt_h_path = *h_path; ++ h_inode = d_inode(h_path->dentry); ++ dt->dt_atime = h_inode->i_atime; ++ dt->dt_mtime = h_inode->i_mtime; ++ /* smp_mb(); */ ++} ++ ++void au_dtime_revert(struct au_dtime *dt) ++{ ++ struct iattr attr; ++ int err; ++ ++ attr.ia_atime = dt->dt_atime; ++ attr.ia_mtime = dt->dt_mtime; ++ attr.ia_valid = ATTR_FORCE | ATTR_MTIME | ATTR_MTIME_SET ++ | ATTR_ATIME | ATTR_ATIME_SET; ++ ++ /* no delegation since this is a directory */ ++ err = vfsub_notify_change(&dt->dt_h_path, &attr, /*delegated*/NULL); ++ if (unlikely(err)) ++ pr_warn("restoring timestamps failed(%d). ignored\n", err); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* internal use only */ ++struct au_cpup_reg_attr { ++ int valid; ++ struct kstat st; ++ unsigned int iflags; /* inode->i_flags */ ++}; ++ ++static noinline_for_stack ++int cpup_iattr(struct dentry *dst, aufs_bindex_t bindex, struct dentry *h_src, ++ struct au_cpup_reg_attr *h_src_attr) ++{ ++ int err, sbits, icex; ++ unsigned int mnt_flags; ++ unsigned char verbose; ++ struct iattr ia; ++ struct path h_path; ++ struct inode *h_isrc, *h_idst; ++ struct kstat *h_st; ++ struct au_branch *br; ++ ++ h_path.dentry = au_h_dptr(dst, bindex); ++ h_idst = d_inode(h_path.dentry); ++ br = au_sbr(dst->d_sb, bindex); ++ h_path.mnt = au_br_mnt(br); ++ h_isrc = d_inode(h_src); ++ ia.ia_valid = ATTR_FORCE | ATTR_UID | ATTR_GID ++ | ATTR_ATIME | ATTR_MTIME ++ | ATTR_ATIME_SET | ATTR_MTIME_SET; ++ if (h_src_attr && h_src_attr->valid) { ++ h_st = &h_src_attr->st; ++ ia.ia_uid = h_st->uid; ++ ia.ia_gid = h_st->gid; ++ ia.ia_atime = h_st->atime; ++ ia.ia_mtime = h_st->mtime; ++ if (h_idst->i_mode != h_st->mode ++ && !S_ISLNK(h_idst->i_mode)) { ++ ia.ia_valid |= ATTR_MODE; ++ ia.ia_mode = h_st->mode; ++ } ++ sbits = !!(h_st->mode & (S_ISUID | S_ISGID)); ++ au_cpup_attr_flags(h_idst, h_src_attr->iflags); ++ } else { ++ ia.ia_uid = h_isrc->i_uid; ++ ia.ia_gid = h_isrc->i_gid; ++ ia.ia_atime = h_isrc->i_atime; ++ ia.ia_mtime = h_isrc->i_mtime; ++ if (h_idst->i_mode != h_isrc->i_mode ++ && !S_ISLNK(h_idst->i_mode)) { ++ ia.ia_valid |= ATTR_MODE; ++ ia.ia_mode = h_isrc->i_mode; ++ } ++ sbits = !!(h_isrc->i_mode & (S_ISUID | S_ISGID)); ++ au_cpup_attr_flags(h_idst, h_isrc->i_flags); ++ } ++ /* no delegation since it is just created */ ++ err = vfsub_notify_change(&h_path, &ia, /*delegated*/NULL); ++ ++ /* is this nfs only? */ ++ if (!err && sbits && au_test_nfs(h_path.dentry->d_sb)) { ++ ia.ia_valid = ATTR_FORCE | ATTR_MODE; ++ ia.ia_mode = h_isrc->i_mode; ++ err = vfsub_notify_change(&h_path, &ia, /*delegated*/NULL); ++ } ++ ++ icex = br->br_perm & AuBrAttr_ICEX; ++ if (!err) { ++ mnt_flags = au_mntflags(dst->d_sb); ++ verbose = !!au_opt_test(mnt_flags, VERBOSE); ++ err = au_cpup_xattr(h_path.dentry, h_src, icex, verbose); ++ } ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int au_do_copy_file(struct file *dst, struct file *src, loff_t len, ++ char *buf, unsigned long blksize) ++{ ++ int err; ++ size_t sz, rbytes, wbytes; ++ unsigned char all_zero; ++ char *p, *zp; ++ struct inode *h_inode; ++ /* reduce stack usage */ ++ struct iattr *ia; ++ ++ zp = page_address(ZERO_PAGE(0)); ++ if (unlikely(!zp)) ++ return -ENOMEM; /* possible? */ ++ ++ err = 0; ++ all_zero = 0; ++ while (len) { ++ AuDbg("len %lld\n", len); ++ sz = blksize; ++ if (len < blksize) ++ sz = len; ++ ++ rbytes = 0; ++ /* todo: signal_pending? */ ++ while (!rbytes || err == -EAGAIN || err == -EINTR) { ++ rbytes = vfsub_read_k(src, buf, sz, &src->f_pos); ++ err = rbytes; ++ } ++ if (unlikely(err < 0)) ++ break; ++ ++ all_zero = 0; ++ if (len >= rbytes && rbytes == blksize) ++ all_zero = !memcmp(buf, zp, rbytes); ++ if (!all_zero) { ++ wbytes = rbytes; ++ p = buf; ++ while (wbytes) { ++ size_t b; ++ ++ b = vfsub_write_k(dst, p, wbytes, &dst->f_pos); ++ err = b; ++ /* todo: signal_pending? */ ++ if (unlikely(err == -EAGAIN || err == -EINTR)) ++ continue; ++ if (unlikely(err < 0)) ++ break; ++ wbytes -= b; ++ p += b; ++ } ++ if (unlikely(err < 0)) ++ break; ++ } else { ++ loff_t res; ++ ++ AuLabel(hole); ++ res = vfsub_llseek(dst, rbytes, SEEK_CUR); ++ err = res; ++ if (unlikely(res < 0)) ++ break; ++ } ++ len -= rbytes; ++ err = 0; ++ } ++ ++ /* the last block may be a hole */ ++ if (!err && all_zero) { ++ AuLabel(last hole); ++ ++ err = 1; ++ if (au_test_nfs(dst->f_path.dentry->d_sb)) { ++ /* nfs requires this step to make last hole */ ++ /* is this only nfs? */ ++ do { ++ /* todo: signal_pending? */ ++ err = vfsub_write_k(dst, "\0", 1, &dst->f_pos); ++ } while (err == -EAGAIN || err == -EINTR); ++ if (err == 1) ++ dst->f_pos--; ++ } ++ ++ if (err == 1) { ++ ia = (void *)buf; ++ ia->ia_size = dst->f_pos; ++ ia->ia_valid = ATTR_SIZE | ATTR_FILE; ++ ia->ia_file = dst; ++ h_inode = file_inode(dst); ++ inode_lock_nested(h_inode, AuLsc_I_CHILD2); ++ /* no delegation since it is just created */ ++ err = vfsub_notify_change(&dst->f_path, ia, ++ /*delegated*/NULL); ++ inode_unlock(h_inode); ++ } ++ } ++ ++ return err; ++} ++ ++int au_copy_file(struct file *dst, struct file *src, loff_t len) ++{ ++ int err; ++ unsigned long blksize; ++ unsigned char do_kfree; ++ char *buf; ++ struct super_block *h_sb; ++ ++ err = -ENOMEM; ++ h_sb = file_inode(dst)->i_sb; ++ blksize = h_sb->s_blocksize; ++ if (!blksize || PAGE_SIZE < blksize) ++ blksize = PAGE_SIZE; ++ AuDbg("blksize %lu\n", blksize); ++ do_kfree = (blksize != PAGE_SIZE && blksize >= sizeof(struct iattr *)); ++ if (do_kfree) ++ buf = kmalloc(blksize, GFP_NOFS); ++ else ++ buf = (void *)__get_free_page(GFP_NOFS); ++ if (unlikely(!buf)) ++ goto out; ++ ++ if (len > (1 << 22)) ++ AuDbg("copying a large file %lld\n", (long long)len); ++ ++ src->f_pos = 0; ++ dst->f_pos = 0; ++ err = au_do_copy_file(dst, src, len, buf, blksize); ++ if (do_kfree) { ++ AuDebugOn(!au_kfree_do_sz_test(blksize)); ++ au_kfree_do_rcu(buf); ++ } else ++ free_page((unsigned long)buf); ++ ++out: ++ return err; ++} ++ ++static int au_do_copy(struct file *dst, struct file *src, loff_t len) ++{ ++ int err; ++ struct super_block *h_src_sb; ++ struct inode *h_src_inode; ++ ++ h_src_inode = file_inode(src); ++ h_src_sb = h_src_inode->i_sb; ++ ++ /* XFS acquires inode_lock */ ++ if (!au_test_xfs(h_src_sb)) ++ err = au_copy_file(dst, src, len); ++ else { ++ inode_unlock_shared(h_src_inode); ++ err = au_copy_file(dst, src, len); ++ inode_lock_shared_nested(h_src_inode, AuLsc_I_CHILD); ++ } ++ ++ return err; ++} ++ ++static int au_clone_or_copy(struct file *dst, struct file *src, loff_t len) ++{ ++ int err; ++ loff_t lo; ++ struct super_block *h_src_sb; ++ struct inode *h_src_inode; ++ ++ h_src_inode = file_inode(src); ++ h_src_sb = h_src_inode->i_sb; ++ if (h_src_sb != file_inode(dst)->i_sb ++ || !dst->f_op->remap_file_range) { ++ err = au_do_copy(dst, src, len); ++ goto out; ++ } ++ ++ if (!au_test_nfs(h_src_sb)) { ++ inode_unlock_shared(h_src_inode); ++ lo = vfsub_clone_file_range(src, dst, len); ++ inode_lock_shared_nested(h_src_inode, AuLsc_I_CHILD); ++ } else ++ lo = vfsub_clone_file_range(src, dst, len); ++ if (lo == len) { ++ err = 0; ++ goto out; /* success */ ++ } else if (lo >= 0) ++ /* todo: possible? */ ++ /* paritially succeeded */ ++ AuDbg("lo %lld, len %lld. Retrying.\n", lo, len); ++ else if (lo != -EOPNOTSUPP) { ++ /* older XFS has a condition in cloning */ ++ err = lo; ++ goto out; ++ } ++ ++ /* the backend fs on NFS may not support cloning */ ++ err = au_do_copy(dst, src, len); ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++/* ++ * to support a sparse file which is opened with O_APPEND, ++ * we need to close the file. ++ */ ++static int au_cp_regular(struct au_cp_generic *cpg) ++{ ++ int err, i; ++ enum { SRC, DST }; ++ struct { ++ aufs_bindex_t bindex; ++ unsigned int flags; ++ struct dentry *dentry; ++ int force_wr; ++ struct file *file; ++ } *f, file[] = { ++ { ++ .bindex = cpg->bsrc, ++ .flags = O_RDONLY | O_NOATIME | O_LARGEFILE, ++ }, ++ { ++ .bindex = cpg->bdst, ++ .flags = O_WRONLY | O_NOATIME | O_LARGEFILE, ++ .force_wr = !!au_ftest_cpup(cpg->flags, RWDST), ++ } ++ }; ++ struct au_branch *br; ++ struct super_block *sb, *h_src_sb; ++ struct inode *h_src_inode; ++ struct task_struct *tsk = current; ++ ++ /* bsrc branch can be ro/rw. */ ++ sb = cpg->dentry->d_sb; ++ f = file; ++ for (i = 0; i < 2; i++, f++) { ++ f->dentry = au_h_dptr(cpg->dentry, f->bindex); ++ f->file = au_h_open(cpg->dentry, f->bindex, f->flags, ++ /*file*/NULL, f->force_wr); ++ if (IS_ERR(f->file)) { ++ err = PTR_ERR(f->file); ++ if (i == SRC) ++ goto out; ++ else ++ goto out_src; ++ } ++ } ++ ++ /* try stopping to update while we copyup */ ++ h_src_inode = d_inode(file[SRC].dentry); ++ h_src_sb = h_src_inode->i_sb; ++ if (!au_test_nfs(h_src_sb)) ++ IMustLock(h_src_inode); ++ err = au_clone_or_copy(file[DST].file, file[SRC].file, cpg->len); ++ ++ /* i wonder if we had O_NO_DELAY_FPUT flag */ ++ if (tsk->flags & PF_KTHREAD) ++ __fput_sync(file[DST].file); ++ else { ++ /* it happened actually */ ++ fput(file[DST].file); ++ /* ++ * too bad. ++ * we have to call both since we don't know which place the file ++ * was added to. ++ */ ++ task_work_run(); ++ flush_delayed_fput(); ++ } ++ br = au_sbr(sb, file[DST].bindex); ++ au_lcnt_dec(&br->br_nfiles); ++ ++out_src: ++ fput(file[SRC].file); ++ br = au_sbr(sb, file[SRC].bindex); ++ au_lcnt_dec(&br->br_nfiles); ++out: ++ return err; ++} ++ ++static int au_do_cpup_regular(struct au_cp_generic *cpg, ++ struct au_cpup_reg_attr *h_src_attr) ++{ ++ int err, rerr; ++ loff_t l; ++ struct path h_path; ++ struct inode *h_src_inode, *h_dst_inode; ++ ++ err = 0; ++ h_src_inode = au_h_iptr(d_inode(cpg->dentry), cpg->bsrc); ++ l = i_size_read(h_src_inode); ++ if (cpg->len == -1 || l < cpg->len) ++ cpg->len = l; ++ if (cpg->len) { ++ /* try stopping to update while we are referencing */ ++ inode_lock_shared_nested(h_src_inode, AuLsc_I_CHILD); ++ au_pin_hdir_unlock(cpg->pin); ++ ++ h_path.dentry = au_h_dptr(cpg->dentry, cpg->bsrc); ++ h_path.mnt = au_sbr_mnt(cpg->dentry->d_sb, cpg->bsrc); ++ h_src_attr->iflags = h_src_inode->i_flags; ++ if (!au_test_nfs(h_src_inode->i_sb)) ++ err = vfsub_getattr(&h_path, &h_src_attr->st); ++ else { ++ inode_unlock_shared(h_src_inode); ++ err = vfsub_getattr(&h_path, &h_src_attr->st); ++ inode_lock_shared_nested(h_src_inode, AuLsc_I_CHILD); ++ } ++ if (unlikely(err)) { ++ inode_unlock_shared(h_src_inode); ++ goto out; ++ } ++ h_src_attr->valid = 1; ++ if (!au_test_nfs(h_src_inode->i_sb)) { ++ err = au_cp_regular(cpg); ++ inode_unlock_shared(h_src_inode); ++ } else { ++ inode_unlock_shared(h_src_inode); ++ err = au_cp_regular(cpg); ++ } ++ rerr = au_pin_hdir_relock(cpg->pin); ++ if (!err && rerr) ++ err = rerr; ++ } ++ if (!err && (h_src_inode->i_state & I_LINKABLE)) { ++ h_path.dentry = au_h_dptr(cpg->dentry, cpg->bdst); ++ h_dst_inode = d_inode(h_path.dentry); ++ spin_lock(&h_dst_inode->i_lock); ++ h_dst_inode->i_state |= I_LINKABLE; ++ spin_unlock(&h_dst_inode->i_lock); ++ } ++ ++out: ++ return err; ++} ++ ++static int au_do_cpup_symlink(struct path *h_path, struct dentry *h_src, ++ struct inode *h_dir) ++{ ++ int err, symlen; ++ mm_segment_t old_fs; ++ union { ++ char *k; ++ char __user *u; ++ } sym; ++ ++ err = -ENOMEM; ++ sym.k = (void *)__get_free_page(GFP_NOFS); ++ if (unlikely(!sym.k)) ++ goto out; ++ ++ /* unnecessary to support mmap_sem since symlink is not mmap-able */ ++ old_fs = get_fs(); ++ set_fs(KERNEL_DS); ++ symlen = vfs_readlink(h_src, sym.u, PATH_MAX); ++ err = symlen; ++ set_fs(old_fs); ++ ++ if (symlen > 0) { ++ sym.k[symlen] = 0; ++ err = vfsub_symlink(h_dir, h_path, sym.k); ++ } ++ free_page((unsigned long)sym.k); ++ ++out: ++ return err; ++} ++ ++/* ++ * regardless 'acl' option, reset all ACL. ++ * All ACL will be copied up later from the original entry on the lower branch. ++ */ ++static int au_reset_acl(struct inode *h_dir, struct path *h_path, umode_t mode) ++{ ++ int err; ++ struct dentry *h_dentry; ++ struct inode *h_inode; ++ ++ h_dentry = h_path->dentry; ++ h_inode = d_inode(h_dentry); ++ /* forget_all_cached_acls(h_inode)); */ ++ err = vfsub_removexattr(h_dentry, XATTR_NAME_POSIX_ACL_ACCESS); ++ AuTraceErr(err); ++ if (err == -EOPNOTSUPP) ++ err = 0; ++ if (!err) ++ err = vfsub_acl_chmod(h_inode, mode); ++ ++ AuTraceErr(err); ++ return err; ++} ++ ++static int au_do_cpup_dir(struct au_cp_generic *cpg, struct dentry *dst_parent, ++ struct inode *h_dir, struct path *h_path) ++{ ++ int err; ++ struct inode *dir, *inode; ++ ++ err = vfsub_removexattr(h_path->dentry, XATTR_NAME_POSIX_ACL_DEFAULT); ++ AuTraceErr(err); ++ if (err == -EOPNOTSUPP) ++ err = 0; ++ if (unlikely(err)) ++ goto out; ++ ++ /* ++ * strange behaviour from the users view, ++ * particularly setattr case ++ */ ++ dir = d_inode(dst_parent); ++ if (au_ibtop(dir) == cpg->bdst) ++ au_cpup_attr_nlink(dir, /*force*/1); ++ inode = d_inode(cpg->dentry); ++ au_cpup_attr_nlink(inode, /*force*/1); ++ ++out: ++ return err; ++} ++ ++static noinline_for_stack ++int cpup_entry(struct au_cp_generic *cpg, struct dentry *dst_parent, ++ struct au_cpup_reg_attr *h_src_attr) ++{ ++ int err; ++ umode_t mode; ++ unsigned int mnt_flags; ++ unsigned char isdir, isreg, force; ++ const unsigned char do_dt = !!au_ftest_cpup(cpg->flags, DTIME); ++ struct au_dtime dt; ++ struct path h_path; ++ struct dentry *h_src, *h_dst, *h_parent; ++ struct inode *h_inode, *h_dir; ++ struct super_block *sb; ++ ++ /* bsrc branch can be ro/rw. */ ++ h_src = au_h_dptr(cpg->dentry, cpg->bsrc); ++ h_inode = d_inode(h_src); ++ AuDebugOn(h_inode != au_h_iptr(d_inode(cpg->dentry), cpg->bsrc)); ++ ++ /* try stopping to be referenced while we are creating */ ++ h_dst = au_h_dptr(cpg->dentry, cpg->bdst); ++ if (au_ftest_cpup(cpg->flags, RENAME)) ++ AuDebugOn(strncmp(h_dst->d_name.name, AUFS_WH_PFX, ++ AUFS_WH_PFX_LEN)); ++ h_parent = h_dst->d_parent; /* dir inode is locked */ ++ h_dir = d_inode(h_parent); ++ IMustLock(h_dir); ++ AuDebugOn(h_parent != h_dst->d_parent); ++ ++ sb = cpg->dentry->d_sb; ++ h_path.mnt = au_sbr_mnt(sb, cpg->bdst); ++ if (do_dt) { ++ h_path.dentry = h_parent; ++ au_dtime_store(&dt, dst_parent, &h_path); ++ } ++ h_path.dentry = h_dst; ++ ++ isreg = 0; ++ isdir = 0; ++ mode = h_inode->i_mode; ++ switch (mode & S_IFMT) { ++ case S_IFREG: ++ isreg = 1; ++ err = vfsub_create(h_dir, &h_path, 0600, /*want_excl*/true); ++ if (!err) ++ err = au_do_cpup_regular(cpg, h_src_attr); ++ break; ++ case S_IFDIR: ++ isdir = 1; ++ err = vfsub_mkdir(h_dir, &h_path, mode); ++ if (!err) ++ err = au_do_cpup_dir(cpg, dst_parent, h_dir, &h_path); ++ break; ++ case S_IFLNK: ++ err = au_do_cpup_symlink(&h_path, h_src, h_dir); ++ break; ++ case S_IFCHR: ++ case S_IFBLK: ++ AuDebugOn(!capable(CAP_MKNOD)); ++ /*FALLTHROUGH*/ ++ case S_IFIFO: ++ case S_IFSOCK: ++ err = vfsub_mknod(h_dir, &h_path, mode, h_inode->i_rdev); ++ break; ++ default: ++ AuIOErr("Unknown inode type 0%o\n", mode); ++ err = -EIO; ++ } ++ if (!err) ++ err = au_reset_acl(h_dir, &h_path, mode); ++ ++ mnt_flags = au_mntflags(sb); ++ if (!au_opt_test(mnt_flags, UDBA_NONE) ++ && !isdir ++ && au_opt_test(mnt_flags, XINO) ++ && (h_inode->i_nlink == 1 ++ || (h_inode->i_state & I_LINKABLE)) ++ /* todo: unnecessary? */ ++ /* && d_inode(cpg->dentry)->i_nlink == 1 */ ++ && cpg->bdst < cpg->bsrc ++ && !au_ftest_cpup(cpg->flags, KEEPLINO)) ++ au_xino_write(sb, cpg->bsrc, h_inode->i_ino, /*ino*/0); ++ /* ignore this error */ ++ ++ if (!err) { ++ force = 0; ++ if (isreg) { ++ force = !!cpg->len; ++ if (cpg->len == -1) ++ force = !!i_size_read(h_inode); ++ } ++ au_fhsm_wrote(sb, cpg->bdst, force); ++ } ++ ++ if (do_dt) ++ au_dtime_revert(&dt); ++ return err; ++} ++ ++static int au_do_ren_after_cpup(struct au_cp_generic *cpg, struct path *h_path) ++{ ++ int err; ++ struct dentry *dentry, *h_dentry, *h_parent, *parent; ++ struct inode *h_dir; ++ aufs_bindex_t bdst; ++ ++ dentry = cpg->dentry; ++ bdst = cpg->bdst; ++ h_dentry = au_h_dptr(dentry, bdst); ++ if (!au_ftest_cpup(cpg->flags, OVERWRITE)) { ++ dget(h_dentry); ++ au_set_h_dptr(dentry, bdst, NULL); ++ err = au_lkup_neg(dentry, bdst, /*wh*/0); ++ if (!err) ++ h_path->dentry = dget(au_h_dptr(dentry, bdst)); ++ au_set_h_dptr(dentry, bdst, h_dentry); ++ } else { ++ err = 0; ++ parent = dget_parent(dentry); ++ h_parent = au_h_dptr(parent, bdst); ++ dput(parent); ++ h_path->dentry = vfsub_lkup_one(&dentry->d_name, h_parent); ++ if (IS_ERR(h_path->dentry)) ++ err = PTR_ERR(h_path->dentry); ++ } ++ if (unlikely(err)) ++ goto out; ++ ++ h_parent = h_dentry->d_parent; /* dir inode is locked */ ++ h_dir = d_inode(h_parent); ++ IMustLock(h_dir); ++ AuDbg("%pd %pd\n", h_dentry, h_path->dentry); ++ /* no delegation since it is just created */ ++ err = vfsub_rename(h_dir, h_dentry, h_dir, h_path, /*delegated*/NULL, ++ /*flags*/0); ++ dput(h_path->dentry); ++ ++out: ++ return err; ++} ++ ++/* ++ * copyup the @dentry from @bsrc to @bdst. ++ * the caller must set the both of lower dentries. ++ * @len is for truncating when it is -1 copyup the entire file. ++ * in link/rename cases, @dst_parent may be different from the real one. ++ * basic->bsrc can be larger than basic->bdst. ++ * aufs doesn't touch the credential so ++ * security_inode_copy_up{,_xattr}() are unnecessary. ++ */ ++static int au_cpup_single(struct au_cp_generic *cpg, struct dentry *dst_parent) ++{ ++ int err, rerr; ++ aufs_bindex_t old_ibtop; ++ unsigned char isdir, plink; ++ struct dentry *h_src, *h_dst, *h_parent; ++ struct inode *dst_inode, *h_dir, *inode, *delegated, *src_inode; ++ struct super_block *sb; ++ struct au_branch *br; ++ /* to reduce stack size */ ++ struct { ++ struct au_dtime dt; ++ struct path h_path; ++ struct au_cpup_reg_attr h_src_attr; ++ } *a; ++ ++ err = -ENOMEM; ++ a = kmalloc(sizeof(*a), GFP_NOFS); ++ if (unlikely(!a)) ++ goto out; ++ a->h_src_attr.valid = 0; ++ ++ sb = cpg->dentry->d_sb; ++ br = au_sbr(sb, cpg->bdst); ++ a->h_path.mnt = au_br_mnt(br); ++ h_dst = au_h_dptr(cpg->dentry, cpg->bdst); ++ h_parent = h_dst->d_parent; /* dir inode is locked */ ++ h_dir = d_inode(h_parent); ++ IMustLock(h_dir); ++ ++ h_src = au_h_dptr(cpg->dentry, cpg->bsrc); ++ inode = d_inode(cpg->dentry); ++ ++ if (!dst_parent) ++ dst_parent = dget_parent(cpg->dentry); ++ else ++ dget(dst_parent); ++ ++ plink = !!au_opt_test(au_mntflags(sb), PLINK); ++ dst_inode = au_h_iptr(inode, cpg->bdst); ++ if (dst_inode) { ++ if (unlikely(!plink)) { ++ err = -EIO; ++ AuIOErr("hi%lu(i%lu) exists on b%d " ++ "but plink is disabled\n", ++ dst_inode->i_ino, inode->i_ino, cpg->bdst); ++ goto out_parent; ++ } ++ ++ if (dst_inode->i_nlink) { ++ const int do_dt = au_ftest_cpup(cpg->flags, DTIME); ++ ++ h_src = au_plink_lkup(inode, cpg->bdst); ++ err = PTR_ERR(h_src); ++ if (IS_ERR(h_src)) ++ goto out_parent; ++ if (unlikely(d_is_negative(h_src))) { ++ err = -EIO; ++ AuIOErr("i%lu exists on b%d " ++ "but not pseudo-linked\n", ++ inode->i_ino, cpg->bdst); ++ dput(h_src); ++ goto out_parent; ++ } ++ ++ if (do_dt) { ++ a->h_path.dentry = h_parent; ++ au_dtime_store(&a->dt, dst_parent, &a->h_path); ++ } ++ ++ a->h_path.dentry = h_dst; ++ delegated = NULL; ++ err = vfsub_link(h_src, h_dir, &a->h_path, &delegated); ++ if (!err && au_ftest_cpup(cpg->flags, RENAME)) ++ err = au_do_ren_after_cpup(cpg, &a->h_path); ++ if (do_dt) ++ au_dtime_revert(&a->dt); ++ if (unlikely(err == -EWOULDBLOCK)) { ++ pr_warn("cannot retry for NFSv4 delegation" ++ " for an internal link\n"); ++ iput(delegated); ++ } ++ dput(h_src); ++ goto out_parent; ++ } else ++ /* todo: cpup_wh_file? */ ++ /* udba work */ ++ au_update_ibrange(inode, /*do_put_zero*/1); ++ } ++ ++ isdir = S_ISDIR(inode->i_mode); ++ old_ibtop = au_ibtop(inode); ++ err = cpup_entry(cpg, dst_parent, &a->h_src_attr); ++ if (unlikely(err)) ++ goto out_rev; ++ dst_inode = d_inode(h_dst); ++ inode_lock_nested(dst_inode, AuLsc_I_CHILD2); ++ /* todo: necessary? */ ++ /* au_pin_hdir_unlock(cpg->pin); */ ++ ++ err = cpup_iattr(cpg->dentry, cpg->bdst, h_src, &a->h_src_attr); ++ if (unlikely(err)) { ++ /* todo: necessary? */ ++ /* au_pin_hdir_relock(cpg->pin); */ /* ignore an error */ ++ inode_unlock(dst_inode); ++ goto out_rev; ++ } ++ ++ if (cpg->bdst < old_ibtop) { ++ if (S_ISREG(inode->i_mode)) { ++ err = au_dy_iaop(inode, cpg->bdst, dst_inode); ++ if (unlikely(err)) { ++ /* ignore an error */ ++ /* au_pin_hdir_relock(cpg->pin); */ ++ inode_unlock(dst_inode); ++ goto out_rev; ++ } ++ } ++ au_set_ibtop(inode, cpg->bdst); ++ } else ++ au_set_ibbot(inode, cpg->bdst); ++ au_set_h_iptr(inode, cpg->bdst, au_igrab(dst_inode), ++ au_hi_flags(inode, isdir)); ++ ++ /* todo: necessary? */ ++ /* err = au_pin_hdir_relock(cpg->pin); */ ++ inode_unlock(dst_inode); ++ if (unlikely(err)) ++ goto out_rev; ++ ++ src_inode = d_inode(h_src); ++ if (!isdir ++ && (src_inode->i_nlink > 1 ++ || src_inode->i_state & I_LINKABLE) ++ && plink) ++ au_plink_append(inode, cpg->bdst, h_dst); ++ ++ if (au_ftest_cpup(cpg->flags, RENAME)) { ++ a->h_path.dentry = h_dst; ++ err = au_do_ren_after_cpup(cpg, &a->h_path); ++ } ++ if (!err) ++ goto out_parent; /* success */ ++ ++ /* revert */ ++out_rev: ++ a->h_path.dentry = h_parent; ++ au_dtime_store(&a->dt, dst_parent, &a->h_path); ++ a->h_path.dentry = h_dst; ++ rerr = 0; ++ if (d_is_positive(h_dst)) { ++ if (!isdir) { ++ /* no delegation since it is just created */ ++ rerr = vfsub_unlink(h_dir, &a->h_path, ++ /*delegated*/NULL, /*force*/0); ++ } else ++ rerr = vfsub_rmdir(h_dir, &a->h_path); ++ } ++ au_dtime_revert(&a->dt); ++ if (rerr) { ++ AuIOErr("failed removing broken entry(%d, %d)\n", err, rerr); ++ err = -EIO; ++ } ++out_parent: ++ dput(dst_parent); ++ au_kfree_rcu(a); ++out: ++ return err; ++} ++ ++#if 0 /* reserved */ ++struct au_cpup_single_args { ++ int *errp; ++ struct au_cp_generic *cpg; ++ struct dentry *dst_parent; ++}; ++ ++static void au_call_cpup_single(void *args) ++{ ++ struct au_cpup_single_args *a = args; ++ ++ au_pin_hdir_acquire_nest(a->cpg->pin); ++ *a->errp = au_cpup_single(a->cpg, a->dst_parent); ++ au_pin_hdir_release(a->cpg->pin); ++} ++#endif ++ ++/* ++ * prevent SIGXFSZ in copy-up. ++ * testing CAP_MKNOD is for generic fs, ++ * but CAP_FSETID is for xfs only, currently. ++ */ ++static int au_cpup_sio_test(struct au_pin *pin, umode_t mode) ++{ ++ int do_sio; ++ struct super_block *sb; ++ struct inode *h_dir; ++ ++ do_sio = 0; ++ sb = au_pinned_parent(pin)->d_sb; ++ if (!au_wkq_test() ++ && (!au_sbi(sb)->si_plink_maint_pid ++ || au_plink_maint(sb, AuLock_NOPLM))) { ++ switch (mode & S_IFMT) { ++ case S_IFREG: ++ /* no condition about RLIMIT_FSIZE and the file size */ ++ do_sio = 1; ++ break; ++ case S_IFCHR: ++ case S_IFBLK: ++ do_sio = !capable(CAP_MKNOD); ++ break; ++ } ++ if (!do_sio) ++ do_sio = ((mode & (S_ISUID | S_ISGID)) ++ && !capable(CAP_FSETID)); ++ /* this workaround may be removed in the future */ ++ if (!do_sio) { ++ h_dir = au_pinned_h_dir(pin); ++ do_sio = h_dir->i_mode & S_ISVTX; ++ } ++ } ++ ++ return do_sio; ++} ++ ++#if 0 /* reserved */ ++int au_sio_cpup_single(struct au_cp_generic *cpg, struct dentry *dst_parent) ++{ ++ int err, wkq_err; ++ struct dentry *h_dentry; ++ ++ h_dentry = au_h_dptr(cpg->dentry, cpg->bsrc); ++ if (!au_cpup_sio_test(pin, d_inode(h_dentry)->i_mode)) ++ err = au_cpup_single(cpg, dst_parent); ++ else { ++ struct au_cpup_single_args args = { ++ .errp = &err, ++ .cpg = cpg, ++ .dst_parent = dst_parent ++ }; ++ wkq_err = au_wkq_wait(au_call_cpup_single, &args); ++ if (unlikely(wkq_err)) ++ err = wkq_err; ++ } ++ ++ return err; ++} ++#endif ++ ++/* ++ * copyup the @dentry from the first active lower branch to @bdst, ++ * using au_cpup_single(). ++ */ ++static int au_cpup_simple(struct au_cp_generic *cpg) ++{ ++ int err; ++ unsigned int flags_orig; ++ struct dentry *dentry; ++ ++ AuDebugOn(cpg->bsrc < 0); ++ ++ dentry = cpg->dentry; ++ DiMustWriteLock(dentry); ++ ++ err = au_lkup_neg(dentry, cpg->bdst, /*wh*/1); ++ if (!err) { ++ flags_orig = cpg->flags; ++ au_fset_cpup(cpg->flags, RENAME); ++ err = au_cpup_single(cpg, NULL); ++ cpg->flags = flags_orig; ++ if (!err) ++ return 0; /* success */ ++ ++ /* revert */ ++ au_set_h_dptr(dentry, cpg->bdst, NULL); ++ au_set_dbtop(dentry, cpg->bsrc); ++ } ++ ++ return err; ++} ++ ++struct au_cpup_simple_args { ++ int *errp; ++ struct au_cp_generic *cpg; ++}; ++ ++static void au_call_cpup_simple(void *args) ++{ ++ struct au_cpup_simple_args *a = args; ++ ++ au_pin_hdir_acquire_nest(a->cpg->pin); ++ *a->errp = au_cpup_simple(a->cpg); ++ au_pin_hdir_release(a->cpg->pin); ++} ++ ++static int au_do_sio_cpup_simple(struct au_cp_generic *cpg) ++{ ++ int err, wkq_err; ++ struct dentry *dentry, *parent; ++ struct file *h_file; ++ struct inode *h_dir; ++ ++ dentry = cpg->dentry; ++ h_file = NULL; ++ if (au_ftest_cpup(cpg->flags, HOPEN)) { ++ AuDebugOn(cpg->bsrc < 0); ++ h_file = au_h_open_pre(dentry, cpg->bsrc, /*force_wr*/0); ++ err = PTR_ERR(h_file); ++ if (IS_ERR(h_file)) ++ goto out; ++ } ++ ++ parent = dget_parent(dentry); ++ h_dir = au_h_iptr(d_inode(parent), cpg->bdst); ++ if (!au_test_h_perm_sio(h_dir, MAY_EXEC | MAY_WRITE) ++ && !au_cpup_sio_test(cpg->pin, d_inode(dentry)->i_mode)) ++ err = au_cpup_simple(cpg); ++ else { ++ struct au_cpup_simple_args args = { ++ .errp = &err, ++ .cpg = cpg ++ }; ++ wkq_err = au_wkq_wait(au_call_cpup_simple, &args); ++ if (unlikely(wkq_err)) ++ err = wkq_err; ++ } ++ ++ dput(parent); ++ if (h_file) ++ au_h_open_post(dentry, cpg->bsrc, h_file); ++ ++out: ++ return err; ++} ++ ++int au_sio_cpup_simple(struct au_cp_generic *cpg) ++{ ++ aufs_bindex_t bsrc, bbot; ++ struct dentry *dentry, *h_dentry; ++ ++ if (cpg->bsrc < 0) { ++ dentry = cpg->dentry; ++ bbot = au_dbbot(dentry); ++ for (bsrc = cpg->bdst + 1; bsrc <= bbot; bsrc++) { ++ h_dentry = au_h_dptr(dentry, bsrc); ++ if (h_dentry) { ++ AuDebugOn(d_is_negative(h_dentry)); ++ break; ++ } ++ } ++ AuDebugOn(bsrc > bbot); ++ cpg->bsrc = bsrc; ++ } ++ AuDebugOn(cpg->bsrc <= cpg->bdst); ++ return au_do_sio_cpup_simple(cpg); ++} ++ ++int au_sio_cpdown_simple(struct au_cp_generic *cpg) ++{ ++ AuDebugOn(cpg->bdst <= cpg->bsrc); ++ return au_do_sio_cpup_simple(cpg); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * copyup the deleted file for writing. ++ */ ++static int au_do_cpup_wh(struct au_cp_generic *cpg, struct dentry *wh_dentry, ++ struct file *file) ++{ ++ int err; ++ unsigned int flags_orig; ++ aufs_bindex_t bsrc_orig; ++ struct au_dinfo *dinfo; ++ struct { ++ struct au_hdentry *hd; ++ struct dentry *h_dentry; ++ } hdst, hsrc; ++ ++ dinfo = au_di(cpg->dentry); ++ AuRwMustWriteLock(&dinfo->di_rwsem); ++ ++ bsrc_orig = cpg->bsrc; ++ cpg->bsrc = dinfo->di_btop; ++ hdst.hd = au_hdentry(dinfo, cpg->bdst); ++ hdst.h_dentry = hdst.hd->hd_dentry; ++ hdst.hd->hd_dentry = wh_dentry; ++ dinfo->di_btop = cpg->bdst; ++ ++ hsrc.h_dentry = NULL; ++ if (file) { ++ hsrc.hd = au_hdentry(dinfo, cpg->bsrc); ++ hsrc.h_dentry = hsrc.hd->hd_dentry; ++ hsrc.hd->hd_dentry = au_hf_top(file)->f_path.dentry; ++ } ++ flags_orig = cpg->flags; ++ cpg->flags = !AuCpup_DTIME; ++ err = au_cpup_single(cpg, /*h_parent*/NULL); ++ cpg->flags = flags_orig; ++ if (file) { ++ if (!err) ++ err = au_reopen_nondir(file); ++ hsrc.hd->hd_dentry = hsrc.h_dentry; ++ } ++ hdst.hd->hd_dentry = hdst.h_dentry; ++ dinfo->di_btop = cpg->bsrc; ++ cpg->bsrc = bsrc_orig; ++ ++ return err; ++} ++ ++static int au_cpup_wh(struct au_cp_generic *cpg, struct file *file) ++{ ++ int err; ++ aufs_bindex_t bdst; ++ struct au_dtime dt; ++ struct dentry *dentry, *parent, *h_parent, *wh_dentry; ++ struct au_branch *br; ++ struct path h_path; ++ ++ dentry = cpg->dentry; ++ bdst = cpg->bdst; ++ br = au_sbr(dentry->d_sb, bdst); ++ parent = dget_parent(dentry); ++ h_parent = au_h_dptr(parent, bdst); ++ wh_dentry = au_whtmp_lkup(h_parent, br, &dentry->d_name); ++ err = PTR_ERR(wh_dentry); ++ if (IS_ERR(wh_dentry)) ++ goto out; ++ ++ h_path.dentry = h_parent; ++ h_path.mnt = au_br_mnt(br); ++ au_dtime_store(&dt, parent, &h_path); ++ err = au_do_cpup_wh(cpg, wh_dentry, file); ++ if (unlikely(err)) ++ goto out_wh; ++ ++ dget(wh_dentry); ++ h_path.dentry = wh_dentry; ++ if (!d_is_dir(wh_dentry)) { ++ /* no delegation since it is just created */ ++ err = vfsub_unlink(d_inode(h_parent), &h_path, ++ /*delegated*/NULL, /*force*/0); ++ } else ++ err = vfsub_rmdir(d_inode(h_parent), &h_path); ++ if (unlikely(err)) { ++ AuIOErr("failed remove copied-up tmp file %pd(%d)\n", ++ wh_dentry, err); ++ err = -EIO; ++ } ++ au_dtime_revert(&dt); ++ au_set_hi_wh(d_inode(dentry), bdst, wh_dentry); ++ ++out_wh: ++ dput(wh_dentry); ++out: ++ dput(parent); ++ return err; ++} ++ ++struct au_cpup_wh_args { ++ int *errp; ++ struct au_cp_generic *cpg; ++ struct file *file; ++}; ++ ++static void au_call_cpup_wh(void *args) ++{ ++ struct au_cpup_wh_args *a = args; ++ ++ au_pin_hdir_acquire_nest(a->cpg->pin); ++ *a->errp = au_cpup_wh(a->cpg, a->file); ++ au_pin_hdir_release(a->cpg->pin); ++} ++ ++int au_sio_cpup_wh(struct au_cp_generic *cpg, struct file *file) ++{ ++ int err, wkq_err; ++ aufs_bindex_t bdst; ++ struct dentry *dentry, *parent, *h_orph, *h_parent; ++ struct inode *dir, *h_dir, *h_tmpdir; ++ struct au_wbr *wbr; ++ struct au_pin wh_pin, *pin_orig; ++ ++ dentry = cpg->dentry; ++ bdst = cpg->bdst; ++ parent = dget_parent(dentry); ++ dir = d_inode(parent); ++ h_orph = NULL; ++ h_parent = NULL; ++ h_dir = au_igrab(au_h_iptr(dir, bdst)); ++ h_tmpdir = h_dir; ++ pin_orig = NULL; ++ if (!h_dir->i_nlink) { ++ wbr = au_sbr(dentry->d_sb, bdst)->br_wbr; ++ h_orph = wbr->wbr_orph; ++ ++ h_parent = dget(au_h_dptr(parent, bdst)); ++ au_set_h_dptr(parent, bdst, dget(h_orph)); ++ h_tmpdir = d_inode(h_orph); ++ au_set_h_iptr(dir, bdst, au_igrab(h_tmpdir), /*flags*/0); ++ ++ inode_lock_nested(h_tmpdir, AuLsc_I_PARENT3); ++ /* todo: au_h_open_pre()? */ ++ ++ pin_orig = cpg->pin; ++ au_pin_init(&wh_pin, dentry, bdst, AuLsc_DI_PARENT, ++ AuLsc_I_PARENT3, cpg->pin->udba, AuPin_DI_LOCKED); ++ cpg->pin = &wh_pin; ++ } ++ ++ if (!au_test_h_perm_sio(h_tmpdir, MAY_EXEC | MAY_WRITE) ++ && !au_cpup_sio_test(cpg->pin, d_inode(dentry)->i_mode)) ++ err = au_cpup_wh(cpg, file); ++ else { ++ struct au_cpup_wh_args args = { ++ .errp = &err, ++ .cpg = cpg, ++ .file = file ++ }; ++ wkq_err = au_wkq_wait(au_call_cpup_wh, &args); ++ if (unlikely(wkq_err)) ++ err = wkq_err; ++ } ++ ++ if (h_orph) { ++ inode_unlock(h_tmpdir); ++ /* todo: au_h_open_post()? */ ++ au_set_h_iptr(dir, bdst, au_igrab(h_dir), /*flags*/0); ++ au_set_h_dptr(parent, bdst, h_parent); ++ AuDebugOn(!pin_orig); ++ cpg->pin = pin_orig; ++ } ++ iput(h_dir); ++ dput(parent); ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * generic routine for both of copy-up and copy-down. ++ */ ++/* cf. revalidate function in file.c */ ++int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst, ++ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst, ++ struct au_pin *pin, ++ struct dentry *h_parent, void *arg), ++ void *arg) ++{ ++ int err; ++ struct au_pin pin; ++ struct dentry *d, *parent, *h_parent, *real_parent, *h_dentry; ++ ++ err = 0; ++ parent = dget_parent(dentry); ++ if (IS_ROOT(parent)) ++ goto out; ++ ++ au_pin_init(&pin, dentry, bdst, AuLsc_DI_PARENT2, AuLsc_I_PARENT2, ++ au_opt_udba(dentry->d_sb), AuPin_MNT_WRITE); ++ ++ /* do not use au_dpage */ ++ real_parent = parent; ++ while (1) { ++ dput(parent); ++ parent = dget_parent(dentry); ++ h_parent = au_h_dptr(parent, bdst); ++ if (h_parent) ++ goto out; /* success */ ++ ++ /* find top dir which is necessary to cpup */ ++ do { ++ d = parent; ++ dput(parent); ++ parent = dget_parent(d); ++ di_read_lock_parent3(parent, !AuLock_IR); ++ h_parent = au_h_dptr(parent, bdst); ++ di_read_unlock(parent, !AuLock_IR); ++ } while (!h_parent); ++ ++ if (d != real_parent) ++ di_write_lock_child3(d); ++ ++ /* somebody else might create while we were sleeping */ ++ h_dentry = au_h_dptr(d, bdst); ++ if (!h_dentry || d_is_negative(h_dentry)) { ++ if (h_dentry) ++ au_update_dbtop(d); ++ ++ au_pin_set_dentry(&pin, d); ++ err = au_do_pin(&pin); ++ if (!err) { ++ err = cp(d, bdst, &pin, h_parent, arg); ++ au_unpin(&pin); ++ } ++ } ++ ++ if (d != real_parent) ++ di_write_unlock(d); ++ if (unlikely(err)) ++ break; ++ } ++ ++out: ++ dput(parent); ++ return err; ++} ++ ++static int au_cpup_dir(struct dentry *dentry, aufs_bindex_t bdst, ++ struct au_pin *pin, ++ struct dentry *h_parent __maybe_unused, ++ void *arg __maybe_unused) ++{ ++ struct au_cp_generic cpg = { ++ .dentry = dentry, ++ .bdst = bdst, ++ .bsrc = -1, ++ .len = 0, ++ .pin = pin, ++ .flags = AuCpup_DTIME ++ }; ++ return au_sio_cpup_simple(&cpg); ++} ++ ++int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst) ++{ ++ return au_cp_dirs(dentry, bdst, au_cpup_dir, NULL); ++} ++ ++int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst) ++{ ++ int err; ++ struct dentry *parent; ++ struct inode *dir; ++ ++ parent = dget_parent(dentry); ++ dir = d_inode(parent); ++ err = 0; ++ if (au_h_iptr(dir, bdst)) ++ goto out; ++ ++ di_read_unlock(parent, AuLock_IR); ++ di_write_lock_parent(parent); ++ /* someone else might change our inode while we were sleeping */ ++ if (!au_h_iptr(dir, bdst)) ++ err = au_cpup_dirs(dentry, bdst); ++ di_downgrade_lock(parent, AuLock_IR); ++ ++out: ++ dput(parent); ++ return err; ++} +diff -Nurp linux-5.4/fs/aufs/cpup.h linux-5.4-aufs/fs/aufs/cpup.h +--- linux-5.4/fs/aufs/cpup.h 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/cpup.h 2019-11-28 01:25:59.063925618 +0200 +@@ -0,0 +1,87 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * copy-up/down functions ++ */ ++ ++#ifndef __AUFS_CPUP_H__ ++#define __AUFS_CPUP_H__ ++ ++#ifdef __KERNEL__ ++ ++#include ++ ++struct inode; ++struct file; ++struct au_pin; ++ ++void au_cpup_attr_flags(struct inode *dst, unsigned int iflags); ++void au_cpup_attr_timesizes(struct inode *inode); ++void au_cpup_attr_nlink(struct inode *inode, int force); ++void au_cpup_attr_changeable(struct inode *inode); ++void au_cpup_igen(struct inode *inode, struct inode *h_inode); ++void au_cpup_attr_all(struct inode *inode, int force); ++ ++/* ---------------------------------------------------------------------- */ ++ ++struct au_cp_generic { ++ struct dentry *dentry; ++ aufs_bindex_t bdst, bsrc; ++ loff_t len; ++ struct au_pin *pin; ++ unsigned int flags; ++}; ++ ++/* cpup flags */ ++#define AuCpup_DTIME 1 /* do dtime_store/revert */ ++#define AuCpup_KEEPLINO (1 << 1) /* do not clear the lower xino, ++ for link(2) */ ++#define AuCpup_RENAME (1 << 2) /* rename after cpup */ ++#define AuCpup_HOPEN (1 << 3) /* call h_open_pre/post() in ++ cpup */ ++#define AuCpup_OVERWRITE (1 << 4) /* allow overwriting the ++ existing entry */ ++#define AuCpup_RWDST (1 << 5) /* force write target even if ++ the branch is marked as RO */ ++ ++#ifndef CONFIG_AUFS_BR_HFSPLUS ++#undef AuCpup_HOPEN ++#define AuCpup_HOPEN 0 ++#endif ++ ++#define au_ftest_cpup(flags, name) ((flags) & AuCpup_##name) ++#define au_fset_cpup(flags, name) \ ++ do { (flags) |= AuCpup_##name; } while (0) ++#define au_fclr_cpup(flags, name) \ ++ do { (flags) &= ~AuCpup_##name; } while (0) ++ ++int au_copy_file(struct file *dst, struct file *src, loff_t len); ++int au_sio_cpup_simple(struct au_cp_generic *cpg); ++int au_sio_cpdown_simple(struct au_cp_generic *cpg); ++int au_sio_cpup_wh(struct au_cp_generic *cpg, struct file *file); ++ ++int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst, ++ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst, ++ struct au_pin *pin, ++ struct dentry *h_parent, void *arg), ++ void *arg); ++int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst); ++int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst); ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* keep timestamps when copyup */ ++struct au_dtime { ++ struct dentry *dt_dentry; ++ struct path dt_h_path; ++ struct timespec64 dt_atime, dt_mtime; ++}; ++void au_dtime_store(struct au_dtime *dt, struct dentry *dentry, ++ struct path *h_path); ++void au_dtime_revert(struct au_dtime *dt); ++ ++#endif /* __KERNEL__ */ ++#endif /* __AUFS_CPUP_H__ */ +diff -Nurp linux-5.4/fs/aufs/dbgaufs.c linux-5.4-aufs/fs/aufs/dbgaufs.c +--- linux-5.4/fs/aufs/dbgaufs.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/dbgaufs.c 2019-11-28 01:25:59.063925618 +0200 +@@ -0,0 +1,513 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * debugfs interface ++ */ ++ ++#include ++#include "aufs.h" ++ ++#ifndef CONFIG_SYSFS ++#error DEBUG_FS depends upon SYSFS ++#endif ++ ++static struct dentry *dbgaufs; ++static const mode_t dbgaufs_mode = 0444; ++ ++/* 20 is max digits length of ulong 64 */ ++struct dbgaufs_arg { ++ int n; ++ char a[20 * 4]; ++}; ++ ++/* ++ * common function for all XINO files ++ */ ++static int dbgaufs_xi_release(struct inode *inode __maybe_unused, ++ struct file *file) ++{ ++ void *p; ++ ++ p = file->private_data; ++ if (p) { ++ /* this is struct dbgaufs_arg */ ++ AuDebugOn(!au_kfree_sz_test(p)); ++ au_kfree_do_rcu(p); ++ } ++ return 0; ++} ++ ++static int dbgaufs_xi_open(struct file *xf, struct file *file, int do_fcnt, ++ int cnt) ++{ ++ int err; ++ struct kstat st; ++ struct dbgaufs_arg *p; ++ ++ err = -ENOMEM; ++ p = kmalloc(sizeof(*p), GFP_NOFS); ++ if (unlikely(!p)) ++ goto out; ++ ++ err = 0; ++ p->n = 0; ++ file->private_data = p; ++ if (!xf) ++ goto out; ++ ++ err = vfsub_getattr(&xf->f_path, &st); ++ if (!err) { ++ if (do_fcnt) ++ p->n = snprintf ++ (p->a, sizeof(p->a), "%d, %llux%u %lld\n", ++ cnt, st.blocks, st.blksize, ++ (long long)st.size); ++ else ++ p->n = snprintf(p->a, sizeof(p->a), "%llux%u %lld\n", ++ st.blocks, st.blksize, ++ (long long)st.size); ++ AuDebugOn(p->n >= sizeof(p->a)); ++ } else { ++ p->n = snprintf(p->a, sizeof(p->a), "err %d\n", err); ++ err = 0; ++ } ++ ++out: ++ return err; ++} ++ ++static ssize_t dbgaufs_xi_read(struct file *file, char __user *buf, ++ size_t count, loff_t *ppos) ++{ ++ struct dbgaufs_arg *p; ++ ++ p = file->private_data; ++ return simple_read_from_buffer(buf, count, ppos, p->a, p->n); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++struct dbgaufs_plink_arg { ++ int n; ++ char a[]; ++}; ++ ++static int dbgaufs_plink_release(struct inode *inode __maybe_unused, ++ struct file *file) ++{ ++ free_page((unsigned long)file->private_data); ++ return 0; ++} ++ ++static int dbgaufs_plink_open(struct inode *inode, struct file *file) ++{ ++ int err, i, limit; ++ unsigned long n, sum; ++ struct dbgaufs_plink_arg *p; ++ struct au_sbinfo *sbinfo; ++ struct super_block *sb; ++ struct hlist_bl_head *hbl; ++ ++ err = -ENOMEM; ++ p = (void *)get_zeroed_page(GFP_NOFS); ++ if (unlikely(!p)) ++ goto out; ++ ++ err = -EFBIG; ++ sbinfo = inode->i_private; ++ sb = sbinfo->si_sb; ++ si_noflush_read_lock(sb); ++ if (au_opt_test(au_mntflags(sb), PLINK)) { ++ limit = PAGE_SIZE - sizeof(p->n); ++ ++ /* the number of buckets */ ++ n = snprintf(p->a + p->n, limit, "%d\n", AuPlink_NHASH); ++ p->n += n; ++ limit -= n; ++ ++ sum = 0; ++ for (i = 0, hbl = sbinfo->si_plink; i < AuPlink_NHASH; ++ i++, hbl++) { ++ n = au_hbl_count(hbl); ++ sum += n; ++ ++ n = snprintf(p->a + p->n, limit, "%lu ", n); ++ p->n += n; ++ limit -= n; ++ if (unlikely(limit <= 0)) ++ goto out_free; ++ } ++ p->a[p->n - 1] = '\n'; ++ ++ /* the sum of plinks */ ++ n = snprintf(p->a + p->n, limit, "%lu\n", sum); ++ p->n += n; ++ limit -= n; ++ if (unlikely(limit <= 0)) ++ goto out_free; ++ } else { ++#define str "1\n0\n0\n" ++ p->n = sizeof(str) - 1; ++ strcpy(p->a, str); ++#undef str ++ } ++ si_read_unlock(sb); ++ ++ err = 0; ++ file->private_data = p; ++ goto out; /* success */ ++ ++out_free: ++ free_page((unsigned long)p); ++out: ++ return err; ++} ++ ++static ssize_t dbgaufs_plink_read(struct file *file, char __user *buf, ++ size_t count, loff_t *ppos) ++{ ++ struct dbgaufs_plink_arg *p; ++ ++ p = file->private_data; ++ return simple_read_from_buffer(buf, count, ppos, p->a, p->n); ++} ++ ++static const struct file_operations dbgaufs_plink_fop = { ++ .owner = THIS_MODULE, ++ .open = dbgaufs_plink_open, ++ .release = dbgaufs_plink_release, ++ .read = dbgaufs_plink_read ++}; ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int dbgaufs_xib_open(struct inode *inode, struct file *file) ++{ ++ int err; ++ struct au_sbinfo *sbinfo; ++ struct super_block *sb; ++ ++ sbinfo = inode->i_private; ++ sb = sbinfo->si_sb; ++ si_noflush_read_lock(sb); ++ err = dbgaufs_xi_open(sbinfo->si_xib, file, /*do_fcnt*/0, /*cnt*/0); ++ si_read_unlock(sb); ++ return err; ++} ++ ++static const struct file_operations dbgaufs_xib_fop = { ++ .owner = THIS_MODULE, ++ .open = dbgaufs_xib_open, ++ .release = dbgaufs_xi_release, ++ .read = dbgaufs_xi_read ++}; ++ ++/* ---------------------------------------------------------------------- */ ++ ++#define DbgaufsXi_PREFIX "xi" ++ ++static int dbgaufs_xino_open(struct inode *inode, struct file *file) ++{ ++ int err, idx; ++ long l; ++ aufs_bindex_t bindex; ++ char *p, a[sizeof(DbgaufsXi_PREFIX) + 8]; ++ struct au_sbinfo *sbinfo; ++ struct super_block *sb; ++ struct au_xino *xi; ++ struct file *xf; ++ struct qstr *name; ++ struct au_branch *br; ++ ++ err = -ENOENT; ++ name = &file->f_path.dentry->d_name; ++ if (unlikely(name->len < sizeof(DbgaufsXi_PREFIX) ++ || memcmp(name->name, DbgaufsXi_PREFIX, ++ sizeof(DbgaufsXi_PREFIX) - 1))) ++ goto out; ++ ++ AuDebugOn(name->len >= sizeof(a)); ++ memcpy(a, name->name, name->len); ++ a[name->len] = '\0'; ++ p = strchr(a, '-'); ++ if (p) ++ *p = '\0'; ++ err = kstrtol(a + sizeof(DbgaufsXi_PREFIX) - 1, 10, &l); ++ if (unlikely(err)) ++ goto out; ++ bindex = l; ++ idx = 0; ++ if (p) { ++ err = kstrtol(p + 1, 10, &l); ++ if (unlikely(err)) ++ goto out; ++ idx = l; ++ } ++ ++ err = -ENOENT; ++ sbinfo = inode->i_private; ++ sb = sbinfo->si_sb; ++ si_noflush_read_lock(sb); ++ if (unlikely(bindex < 0 || bindex > au_sbbot(sb))) ++ goto out_si; ++ br = au_sbr(sb, bindex); ++ xi = br->br_xino; ++ if (unlikely(idx >= xi->xi_nfile)) ++ goto out_si; ++ xf = au_xino_file(xi, idx); ++ if (xf) ++ err = dbgaufs_xi_open(xf, file, /*do_fcnt*/1, ++ au_xino_count(br)); ++ ++out_si: ++ si_read_unlock(sb); ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++static const struct file_operations dbgaufs_xino_fop = { ++ .owner = THIS_MODULE, ++ .open = dbgaufs_xino_open, ++ .release = dbgaufs_xi_release, ++ .read = dbgaufs_xi_read ++}; ++ ++void dbgaufs_xino_del(struct au_branch *br) ++{ ++ struct dentry *dbgaufs; ++ ++ dbgaufs = br->br_dbgaufs; ++ if (!dbgaufs) ++ return; ++ ++ br->br_dbgaufs = NULL; ++ /* debugfs acquires the parent i_mutex */ ++ lockdep_off(); ++ debugfs_remove(dbgaufs); ++ lockdep_on(); ++} ++ ++void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex) ++{ ++ aufs_bindex_t bbot; ++ struct au_branch *br; ++ ++ if (!au_sbi(sb)->si_dbgaufs) ++ return; ++ ++ bbot = au_sbbot(sb); ++ for (; bindex <= bbot; bindex++) { ++ br = au_sbr(sb, bindex); ++ dbgaufs_xino_del(br); ++ } ++} ++ ++static void dbgaufs_br_do_add(struct super_block *sb, aufs_bindex_t bindex, ++ unsigned int idx, struct dentry *parent, ++ struct au_sbinfo *sbinfo) ++{ ++ struct au_branch *br; ++ struct dentry *d; ++ /* "xi" bindex(5) "-" idx(2) NULL */ ++ char name[sizeof(DbgaufsXi_PREFIX) + 8]; ++ ++ if (!idx) ++ snprintf(name, sizeof(name), DbgaufsXi_PREFIX "%d", bindex); ++ else ++ snprintf(name, sizeof(name), DbgaufsXi_PREFIX "%d-%u", ++ bindex, idx); ++ br = au_sbr(sb, bindex); ++ if (br->br_dbgaufs) { ++ struct qstr qstr = QSTR_INIT(name, strlen(name)); ++ ++ if (!au_qstreq(&br->br_dbgaufs->d_name, &qstr)) { ++ /* debugfs acquires the parent i_mutex */ ++ lockdep_off(); ++ d = debugfs_rename(parent, br->br_dbgaufs, parent, ++ name); ++ lockdep_on(); ++ if (unlikely(!d)) ++ pr_warn("failed renaming %pd/%s, ignored.\n", ++ parent, name); ++ } ++ } else { ++ lockdep_off(); ++ br->br_dbgaufs = debugfs_create_file(name, dbgaufs_mode, parent, ++ sbinfo, &dbgaufs_xino_fop); ++ lockdep_on(); ++ if (unlikely(!br->br_dbgaufs)) ++ pr_warn("failed creating %pd/%s, ignored.\n", ++ parent, name); ++ } ++} ++ ++static void dbgaufs_br_add(struct super_block *sb, aufs_bindex_t bindex, ++ struct dentry *parent, struct au_sbinfo *sbinfo) ++{ ++ struct au_branch *br; ++ struct au_xino *xi; ++ unsigned int u; ++ ++ br = au_sbr(sb, bindex); ++ xi = br->br_xino; ++ for (u = 0; u < xi->xi_nfile; u++) ++ dbgaufs_br_do_add(sb, bindex, u, parent, sbinfo); ++} ++ ++void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex, int topdown) ++{ ++ struct au_sbinfo *sbinfo; ++ struct dentry *parent; ++ aufs_bindex_t bbot; ++ ++ if (!au_opt_test(au_mntflags(sb), XINO)) ++ return; ++ ++ sbinfo = au_sbi(sb); ++ parent = sbinfo->si_dbgaufs; ++ if (!parent) ++ return; ++ ++ bbot = au_sbbot(sb); ++ if (topdown) ++ for (; bindex <= bbot; bindex++) ++ dbgaufs_br_add(sb, bindex, parent, sbinfo); ++ else ++ for (; bbot >= bindex; bbot--) ++ dbgaufs_br_add(sb, bbot, parent, sbinfo); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++#ifdef CONFIG_AUFS_EXPORT ++static int dbgaufs_xigen_open(struct inode *inode, struct file *file) ++{ ++ int err; ++ struct au_sbinfo *sbinfo; ++ struct super_block *sb; ++ ++ sbinfo = inode->i_private; ++ sb = sbinfo->si_sb; ++ si_noflush_read_lock(sb); ++ err = dbgaufs_xi_open(sbinfo->si_xigen, file, /*do_fcnt*/0, /*cnt*/0); ++ si_read_unlock(sb); ++ return err; ++} ++ ++static const struct file_operations dbgaufs_xigen_fop = { ++ .owner = THIS_MODULE, ++ .open = dbgaufs_xigen_open, ++ .release = dbgaufs_xi_release, ++ .read = dbgaufs_xi_read ++}; ++ ++static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo) ++{ ++ int err; ++ ++ /* ++ * This function is a dynamic '__init' function actually, ++ * so the tiny check for si_rwsem is unnecessary. ++ */ ++ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */ ++ ++ err = -EIO; ++ sbinfo->si_dbgaufs_xigen = debugfs_create_file ++ ("xigen", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo, ++ &dbgaufs_xigen_fop); ++ if (sbinfo->si_dbgaufs_xigen) ++ err = 0; ++ ++ return err; ++} ++#else ++static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo) ++{ ++ return 0; ++} ++#endif /* CONFIG_AUFS_EXPORT */ ++ ++/* ---------------------------------------------------------------------- */ ++ ++void dbgaufs_si_fin(struct au_sbinfo *sbinfo) ++{ ++ /* ++ * This function is a dynamic '__fin' function actually, ++ * so the tiny check for si_rwsem is unnecessary. ++ */ ++ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */ ++ ++ debugfs_remove_recursive(sbinfo->si_dbgaufs); ++ sbinfo->si_dbgaufs = NULL; ++} ++ ++int dbgaufs_si_init(struct au_sbinfo *sbinfo) ++{ ++ int err; ++ char name[SysaufsSiNameLen]; ++ ++ /* ++ * This function is a dynamic '__init' function actually, ++ * so the tiny check for si_rwsem is unnecessary. ++ */ ++ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */ ++ ++ err = -ENOENT; ++ if (!dbgaufs) { ++ AuErr1("/debug/aufs is uninitialized\n"); ++ goto out; ++ } ++ ++ err = -EIO; ++ sysaufs_name(sbinfo, name); ++ sbinfo->si_dbgaufs = debugfs_create_dir(name, dbgaufs); ++ if (unlikely(!sbinfo->si_dbgaufs)) ++ goto out; ++ ++ /* regardless plink/noplink option */ ++ sbinfo->si_dbgaufs_plink = debugfs_create_file ++ ("plink", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo, ++ &dbgaufs_plink_fop); ++ if (unlikely(!sbinfo->si_dbgaufs_plink)) ++ goto out_dir; ++ ++ /* regardless xino/noxino option */ ++ sbinfo->si_dbgaufs_xib = debugfs_create_file ++ ("xib", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo, ++ &dbgaufs_xib_fop); ++ if (unlikely(!sbinfo->si_dbgaufs_xib)) ++ goto out_dir; ++ ++ err = dbgaufs_xigen_init(sbinfo); ++ if (!err) ++ goto out; /* success */ ++ ++out_dir: ++ dbgaufs_si_fin(sbinfo); ++out: ++ if (unlikely(err)) ++ pr_err("debugfs/aufs failed\n"); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++void dbgaufs_fin(void) ++{ ++ debugfs_remove(dbgaufs); ++} ++ ++int __init dbgaufs_init(void) ++{ ++ int err; ++ ++ err = -EIO; ++ dbgaufs = debugfs_create_dir(AUFS_NAME, NULL); ++ if (dbgaufs) ++ err = 0; ++ return err; ++} +diff -Nurp linux-5.4/fs/aufs/dbgaufs.h linux-5.4-aufs/fs/aufs/dbgaufs.h +--- linux-5.4/fs/aufs/dbgaufs.h 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/dbgaufs.h 2019-11-28 01:25:59.063925618 +0200 +@@ -0,0 +1,40 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * debugfs interface ++ */ ++ ++#ifndef __DBGAUFS_H__ ++#define __DBGAUFS_H__ ++ ++#ifdef __KERNEL__ ++ ++struct super_block; ++struct au_sbinfo; ++struct au_branch; ++ ++#ifdef CONFIG_DEBUG_FS ++/* dbgaufs.c */ ++void dbgaufs_xino_del(struct au_branch *br); ++void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex); ++void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex, int topdown); ++void dbgaufs_si_fin(struct au_sbinfo *sbinfo); ++int dbgaufs_si_init(struct au_sbinfo *sbinfo); ++void dbgaufs_fin(void); ++int __init dbgaufs_init(void); ++#else ++AuStubVoid(dbgaufs_xino_del, struct au_branch *br) ++AuStubVoid(dbgaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex) ++AuStubVoid(dbgaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex, ++ int topdown) ++AuStubVoid(dbgaufs_si_fin, struct au_sbinfo *sbinfo) ++AuStubInt0(dbgaufs_si_init, struct au_sbinfo *sbinfo) ++AuStubVoid(dbgaufs_fin, void) ++AuStubInt0(__init dbgaufs_init, void) ++#endif /* CONFIG_DEBUG_FS */ ++ ++#endif /* __KERNEL__ */ ++#endif /* __DBGAUFS_H__ */ +diff -Nurp linux-5.4/fs/aufs/dcsub.c linux-5.4-aufs/fs/aufs/dcsub.c +--- linux-5.4/fs/aufs/dcsub.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/dcsub.c 2019-11-28 01:25:59.063925618 +0200 +@@ -0,0 +1,212 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * sub-routines for dentry cache ++ */ ++ ++#include "aufs.h" ++ ++static void au_dpage_free(struct au_dpage *dpage) ++{ ++ int i; ++ struct dentry **p; ++ ++ p = dpage->dentries; ++ for (i = 0; i < dpage->ndentry; i++) ++ dput(*p++); ++ free_page((unsigned long)dpage->dentries); ++} ++ ++int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp) ++{ ++ int err; ++ void *p; ++ ++ err = -ENOMEM; ++ dpages->dpages = kmalloc(sizeof(*dpages->dpages), gfp); ++ if (unlikely(!dpages->dpages)) ++ goto out; ++ ++ p = (void *)__get_free_page(gfp); ++ if (unlikely(!p)) ++ goto out_dpages; ++ ++ dpages->dpages[0].ndentry = 0; ++ dpages->dpages[0].dentries = p; ++ dpages->ndpage = 1; ++ return 0; /* success */ ++ ++out_dpages: ++ au_kfree_try_rcu(dpages->dpages); ++out: ++ return err; ++} ++ ++void au_dpages_free(struct au_dcsub_pages *dpages) ++{ ++ int i; ++ struct au_dpage *p; ++ ++ p = dpages->dpages; ++ for (i = 0; i < dpages->ndpage; i++) ++ au_dpage_free(p++); ++ au_kfree_try_rcu(dpages->dpages); ++} ++ ++static int au_dpages_append(struct au_dcsub_pages *dpages, ++ struct dentry *dentry, gfp_t gfp) ++{ ++ int err, sz; ++ struct au_dpage *dpage; ++ void *p; ++ ++ dpage = dpages->dpages + dpages->ndpage - 1; ++ sz = PAGE_SIZE / sizeof(dentry); ++ if (unlikely(dpage->ndentry >= sz)) { ++ AuLabel(new dpage); ++ err = -ENOMEM; ++ sz = dpages->ndpage * sizeof(*dpages->dpages); ++ p = au_kzrealloc(dpages->dpages, sz, ++ sz + sizeof(*dpages->dpages), gfp, ++ /*may_shrink*/0); ++ if (unlikely(!p)) ++ goto out; ++ ++ dpages->dpages = p; ++ dpage = dpages->dpages + dpages->ndpage; ++ p = (void *)__get_free_page(gfp); ++ if (unlikely(!p)) ++ goto out; ++ ++ dpage->ndentry = 0; ++ dpage->dentries = p; ++ dpages->ndpage++; ++ } ++ ++ AuDebugOn(au_dcount(dentry) <= 0); ++ dpage->dentries[dpage->ndentry++] = dget_dlock(dentry); ++ return 0; /* success */ ++ ++out: ++ return err; ++} ++ ++/* todo: BAD approach */ ++/* copied from linux/fs/dcache.c */ ++enum d_walk_ret { ++ D_WALK_CONTINUE, ++ D_WALK_QUIT, ++ D_WALK_NORETRY, ++ D_WALK_SKIP, ++}; ++ ++extern void d_walk(struct dentry *parent, void *data, ++ enum d_walk_ret (*enter)(void *, struct dentry *)); ++ ++struct ac_dpages_arg { ++ int err; ++ struct au_dcsub_pages *dpages; ++ struct super_block *sb; ++ au_dpages_test test; ++ void *arg; ++}; ++ ++static enum d_walk_ret au_call_dpages_append(void *_arg, struct dentry *dentry) ++{ ++ enum d_walk_ret ret; ++ struct ac_dpages_arg *arg = _arg; ++ ++ ret = D_WALK_CONTINUE; ++ if (dentry->d_sb == arg->sb ++ && !IS_ROOT(dentry) ++ && au_dcount(dentry) > 0 ++ && au_di(dentry) ++ && (!arg->test || arg->test(dentry, arg->arg))) { ++ arg->err = au_dpages_append(arg->dpages, dentry, GFP_ATOMIC); ++ if (unlikely(arg->err)) ++ ret = D_WALK_QUIT; ++ } ++ ++ return ret; ++} ++ ++int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root, ++ au_dpages_test test, void *arg) ++{ ++ struct ac_dpages_arg args = { ++ .err = 0, ++ .dpages = dpages, ++ .sb = root->d_sb, ++ .test = test, ++ .arg = arg ++ }; ++ ++ d_walk(root, &args, au_call_dpages_append); ++ ++ return args.err; ++} ++ ++int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry, ++ int do_include, au_dpages_test test, void *arg) ++{ ++ int err; ++ ++ err = 0; ++ write_seqlock(&rename_lock); ++ spin_lock(&dentry->d_lock); ++ if (do_include ++ && au_dcount(dentry) > 0 ++ && (!test || test(dentry, arg))) ++ err = au_dpages_append(dpages, dentry, GFP_ATOMIC); ++ spin_unlock(&dentry->d_lock); ++ if (unlikely(err)) ++ goto out; ++ ++ /* ++ * RCU for vfsmount is unnecessary since this is a traverse in a single ++ * mount ++ */ ++ while (!IS_ROOT(dentry)) { ++ dentry = dentry->d_parent; /* rename_lock is locked */ ++ spin_lock(&dentry->d_lock); ++ if (au_dcount(dentry) > 0 ++ && (!test || test(dentry, arg))) ++ err = au_dpages_append(dpages, dentry, GFP_ATOMIC); ++ spin_unlock(&dentry->d_lock); ++ if (unlikely(err)) ++ break; ++ } ++ ++out: ++ write_sequnlock(&rename_lock); ++ return err; ++} ++ ++static inline int au_dcsub_dpages_aufs(struct dentry *dentry, void *arg) ++{ ++ return au_di(dentry) && dentry->d_sb == arg; ++} ++ ++int au_dcsub_pages_rev_aufs(struct au_dcsub_pages *dpages, ++ struct dentry *dentry, int do_include) ++{ ++ return au_dcsub_pages_rev(dpages, dentry, do_include, ++ au_dcsub_dpages_aufs, dentry->d_sb); ++} ++ ++int au_test_subdir(struct dentry *d1, struct dentry *d2) ++{ ++ struct path path[2] = { ++ { ++ .dentry = d1 ++ }, ++ { ++ .dentry = d2 ++ } ++ }; ++ ++ return path_is_under(path + 0, path + 1); ++} +diff -Nurp linux-5.4/fs/aufs/dcsub.h linux-5.4-aufs/fs/aufs/dcsub.h +--- linux-5.4/fs/aufs/dcsub.h 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/dcsub.h 2019-11-28 01:25:59.063925618 +0200 +@@ -0,0 +1,124 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * sub-routines for dentry cache ++ */ ++ ++#ifndef __AUFS_DCSUB_H__ ++#define __AUFS_DCSUB_H__ ++ ++#ifdef __KERNEL__ ++ ++#include ++#include ++ ++struct au_dpage { ++ int ndentry; ++ struct dentry **dentries; ++}; ++ ++struct au_dcsub_pages { ++ int ndpage; ++ struct au_dpage *dpages; ++}; ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* dcsub.c */ ++int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp); ++void au_dpages_free(struct au_dcsub_pages *dpages); ++typedef int (*au_dpages_test)(struct dentry *dentry, void *arg); ++int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root, ++ au_dpages_test test, void *arg); ++int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry, ++ int do_include, au_dpages_test test, void *arg); ++int au_dcsub_pages_rev_aufs(struct au_dcsub_pages *dpages, ++ struct dentry *dentry, int do_include); ++int au_test_subdir(struct dentry *d1, struct dentry *d2); ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * todo: in linux-3.13, several similar (but faster) helpers are added to ++ * include/linux/dcache.h. Try them (in the future). ++ */ ++ ++static inline int au_d_hashed_positive(struct dentry *d) ++{ ++ int err; ++ struct inode *inode = d_inode(d); ++ ++ err = 0; ++ if (unlikely(d_unhashed(d) ++ || d_is_negative(d) ++ || !inode->i_nlink)) ++ err = -ENOENT; ++ return err; ++} ++ ++static inline int au_d_linkable(struct dentry *d) ++{ ++ int err; ++ struct inode *inode = d_inode(d); ++ ++ err = au_d_hashed_positive(d); ++ if (err ++ && d_is_positive(d) ++ && (inode->i_state & I_LINKABLE)) ++ err = 0; ++ return err; ++} ++ ++static inline int au_d_alive(struct dentry *d) ++{ ++ int err; ++ struct inode *inode; ++ ++ err = 0; ++ if (!IS_ROOT(d)) ++ err = au_d_hashed_positive(d); ++ else { ++ inode = d_inode(d); ++ if (unlikely(d_unlinked(d) ++ || d_is_negative(d) ++ || !inode->i_nlink)) ++ err = -ENOENT; ++ } ++ return err; ++} ++ ++static inline int au_alive_dir(struct dentry *d) ++{ ++ int err; ++ ++ err = au_d_alive(d); ++ if (unlikely(err || IS_DEADDIR(d_inode(d)))) ++ err = -ENOENT; ++ return err; ++} ++ ++static inline int au_qstreq(struct qstr *a, struct qstr *b) ++{ ++ return a->len == b->len ++ && !memcmp(a->name, b->name, a->len); ++} ++ ++/* ++ * by the commit ++ * 360f547 2015-01-25 dcache: let the dentry count go down to zero without ++ * taking d_lock ++ * the type of d_lockref.count became int, but the inlined function d_count() ++ * still returns unsigned int. ++ * I don't know why. Maybe it is for every d_count() users? ++ * Anyway au_dcount() lives on. ++ */ ++static inline int au_dcount(struct dentry *d) ++{ ++ return (int)d_count(d); ++} ++ ++#endif /* __KERNEL__ */ ++#endif /* __AUFS_DCSUB_H__ */ +diff -Nurp linux-5.4/fs/aufs/debug.c linux-5.4-aufs/fs/aufs/debug.c +--- linux-5.4/fs/aufs/debug.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/debug.c 2019-11-28 01:25:59.063925618 +0200 +@@ -0,0 +1,428 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * debug print functions ++ */ ++ ++#include ++#include "aufs.h" ++ ++/* Returns 0, or -errno. arg is in kp->arg. */ ++static int param_atomic_t_set(const char *val, const struct kernel_param *kp) ++{ ++ int err, n; ++ ++ err = kstrtoint(val, 0, &n); ++ if (!err) { ++ if (n > 0) ++ au_debug_on(); ++ else ++ au_debug_off(); ++ } ++ return err; ++} ++ ++/* Returns length written or -errno. Buffer is 4k (ie. be short!) */ ++static int param_atomic_t_get(char *buffer, const struct kernel_param *kp) ++{ ++ atomic_t *a; ++ ++ a = kp->arg; ++ return sprintf(buffer, "%d", atomic_read(a)); ++} ++ ++static struct kernel_param_ops param_ops_atomic_t = { ++ .set = param_atomic_t_set, ++ .get = param_atomic_t_get ++ /* void (*free)(void *arg) */ ++}; ++ ++atomic_t aufs_debug = ATOMIC_INIT(0); ++MODULE_PARM_DESC(debug, "debug print"); ++module_param_named(debug, aufs_debug, atomic_t, 0664); ++ ++DEFINE_MUTEX(au_dbg_mtx); /* just to serialize the dbg msgs */ ++char *au_plevel = KERN_DEBUG; ++#define dpri(fmt, ...) do { \ ++ if ((au_plevel \ ++ && strcmp(au_plevel, KERN_DEBUG)) \ ++ || au_debug_test()) \ ++ printk("%s" fmt, au_plevel, ##__VA_ARGS__); \ ++} while (0) ++ ++/* ---------------------------------------------------------------------- */ ++ ++void au_dpri_whlist(struct au_nhash *whlist) ++{ ++ unsigned long ul, n; ++ struct hlist_head *head; ++ struct au_vdir_wh *pos; ++ ++ n = whlist->nh_num; ++ head = whlist->nh_head; ++ for (ul = 0; ul < n; ul++) { ++ hlist_for_each_entry(pos, head, wh_hash) ++ dpri("b%d, %.*s, %d\n", ++ pos->wh_bindex, ++ pos->wh_str.len, pos->wh_str.name, ++ pos->wh_str.len); ++ head++; ++ } ++} ++ ++void au_dpri_vdir(struct au_vdir *vdir) ++{ ++ unsigned long ul; ++ union au_vdir_deblk_p p; ++ unsigned char *o; ++ ++ if (!vdir || IS_ERR(vdir)) { ++ dpri("err %ld\n", PTR_ERR(vdir)); ++ return; ++ } ++ ++ dpri("deblk %u, nblk %lu, deblk %p, last{%lu, %p}, ver %llu\n", ++ vdir->vd_deblk_sz, vdir->vd_nblk, vdir->vd_deblk, ++ vdir->vd_last.ul, vdir->vd_last.p.deblk, vdir->vd_version); ++ for (ul = 0; ul < vdir->vd_nblk; ul++) { ++ p.deblk = vdir->vd_deblk[ul]; ++ o = p.deblk; ++ dpri("[%lu]: %p\n", ul, o); ++ } ++} ++ ++static int do_pri_inode(aufs_bindex_t bindex, struct inode *inode, int hn, ++ struct dentry *wh) ++{ ++ char *n = NULL; ++ int l = 0; ++ ++ if (!inode || IS_ERR(inode)) { ++ dpri("i%d: err %ld\n", bindex, PTR_ERR(inode)); ++ return -1; ++ } ++ ++ /* the type of i_blocks depends upon CONFIG_LBDAF */ ++ BUILD_BUG_ON(sizeof(inode->i_blocks) != sizeof(unsigned long) ++ && sizeof(inode->i_blocks) != sizeof(u64)); ++ if (wh) { ++ n = (void *)wh->d_name.name; ++ l = wh->d_name.len; ++ } ++ ++ dpri("i%d: %p, i%lu, %s, cnt %d, nl %u, 0%o, sz %llu, blk %llu," ++ " hn %d, ct %lld, np %lu, st 0x%lx, f 0x%x, v %llu, g %x%s%.*s\n", ++ bindex, inode, ++ inode->i_ino, inode->i_sb ? au_sbtype(inode->i_sb) : "??", ++ atomic_read(&inode->i_count), inode->i_nlink, inode->i_mode, ++ i_size_read(inode), (unsigned long long)inode->i_blocks, ++ hn, (long long)timespec64_to_ns(&inode->i_ctime) & 0x0ffff, ++ inode->i_mapping ? inode->i_mapping->nrpages : 0, ++ inode->i_state, inode->i_flags, inode_peek_iversion(inode), ++ inode->i_generation, ++ l ? ", wh " : "", l, n); ++ return 0; ++} ++ ++void au_dpri_inode(struct inode *inode) ++{ ++ struct au_iinfo *iinfo; ++ struct au_hinode *hi; ++ aufs_bindex_t bindex; ++ int err, hn; ++ ++ err = do_pri_inode(-1, inode, -1, NULL); ++ if (err || !au_test_aufs(inode->i_sb) || au_is_bad_inode(inode)) ++ return; ++ ++ iinfo = au_ii(inode); ++ dpri("i-1: btop %d, bbot %d, gen %d\n", ++ iinfo->ii_btop, iinfo->ii_bbot, au_iigen(inode, NULL)); ++ if (iinfo->ii_btop < 0) ++ return; ++ hn = 0; ++ for (bindex = iinfo->ii_btop; bindex <= iinfo->ii_bbot; bindex++) { ++ hi = au_hinode(iinfo, bindex); ++ hn = !!au_hn(hi); ++ do_pri_inode(bindex, hi->hi_inode, hn, hi->hi_whdentry); ++ } ++} ++ ++void au_dpri_dalias(struct inode *inode) ++{ ++ struct dentry *d; ++ ++ spin_lock(&inode->i_lock); ++ hlist_for_each_entry(d, &inode->i_dentry, d_u.d_alias) ++ au_dpri_dentry(d); ++ spin_unlock(&inode->i_lock); ++} ++ ++static int do_pri_dentry(aufs_bindex_t bindex, struct dentry *dentry) ++{ ++ struct dentry *wh = NULL; ++ int hn; ++ struct inode *inode; ++ struct au_iinfo *iinfo; ++ struct au_hinode *hi; ++ ++ if (!dentry || IS_ERR(dentry)) { ++ dpri("d%d: err %ld\n", bindex, PTR_ERR(dentry)); ++ return -1; ++ } ++ /* do not call dget_parent() here */ ++ /* note: access d_xxx without d_lock */ ++ dpri("d%d: %p, %pd2?, %s, cnt %d, flags 0x%x, %shashed\n", ++ bindex, dentry, dentry, ++ dentry->d_sb ? au_sbtype(dentry->d_sb) : "??", ++ au_dcount(dentry), dentry->d_flags, ++ d_unhashed(dentry) ? "un" : ""); ++ hn = -1; ++ inode = NULL; ++ if (d_is_positive(dentry)) ++ inode = d_inode(dentry); ++ if (inode ++ && au_test_aufs(dentry->d_sb) ++ && bindex >= 0 ++ && !au_is_bad_inode(inode)) { ++ iinfo = au_ii(inode); ++ hi = au_hinode(iinfo, bindex); ++ hn = !!au_hn(hi); ++ wh = hi->hi_whdentry; ++ } ++ do_pri_inode(bindex, inode, hn, wh); ++ return 0; ++} ++ ++void au_dpri_dentry(struct dentry *dentry) ++{ ++ struct au_dinfo *dinfo; ++ aufs_bindex_t bindex; ++ int err; ++ ++ err = do_pri_dentry(-1, dentry); ++ if (err || !au_test_aufs(dentry->d_sb)) ++ return; ++ ++ dinfo = au_di(dentry); ++ if (!dinfo) ++ return; ++ dpri("d-1: btop %d, bbot %d, bwh %d, bdiropq %d, gen %d, tmp %d\n", ++ dinfo->di_btop, dinfo->di_bbot, ++ dinfo->di_bwh, dinfo->di_bdiropq, au_digen(dentry), ++ dinfo->di_tmpfile); ++ if (dinfo->di_btop < 0) ++ return; ++ for (bindex = dinfo->di_btop; bindex <= dinfo->di_bbot; bindex++) ++ do_pri_dentry(bindex, au_hdentry(dinfo, bindex)->hd_dentry); ++} ++ ++static int do_pri_file(aufs_bindex_t bindex, struct file *file) ++{ ++ char a[32]; ++ ++ if (!file || IS_ERR(file)) { ++ dpri("f%d: err %ld\n", bindex, PTR_ERR(file)); ++ return -1; ++ } ++ a[0] = 0; ++ if (bindex < 0 ++ && !IS_ERR_OR_NULL(file->f_path.dentry) ++ && au_test_aufs(file->f_path.dentry->d_sb) ++ && au_fi(file)) ++ snprintf(a, sizeof(a), ", gen %d, mmapped %d", ++ au_figen(file), atomic_read(&au_fi(file)->fi_mmapped)); ++ dpri("f%d: mode 0x%x, flags 0%o, cnt %ld, v %llu, pos %llu%s\n", ++ bindex, file->f_mode, file->f_flags, (long)file_count(file), ++ file->f_version, file->f_pos, a); ++ if (!IS_ERR_OR_NULL(file->f_path.dentry)) ++ do_pri_dentry(bindex, file->f_path.dentry); ++ return 0; ++} ++ ++void au_dpri_file(struct file *file) ++{ ++ struct au_finfo *finfo; ++ struct au_fidir *fidir; ++ struct au_hfile *hfile; ++ aufs_bindex_t bindex; ++ int err; ++ ++ err = do_pri_file(-1, file); ++ if (err ++ || IS_ERR_OR_NULL(file->f_path.dentry) ++ || !au_test_aufs(file->f_path.dentry->d_sb)) ++ return; ++ ++ finfo = au_fi(file); ++ if (!finfo) ++ return; ++ if (finfo->fi_btop < 0) ++ return; ++ fidir = finfo->fi_hdir; ++ if (!fidir) ++ do_pri_file(finfo->fi_btop, finfo->fi_htop.hf_file); ++ else ++ for (bindex = finfo->fi_btop; ++ bindex >= 0 && bindex <= fidir->fd_bbot; ++ bindex++) { ++ hfile = fidir->fd_hfile + bindex; ++ do_pri_file(bindex, hfile ? hfile->hf_file : NULL); ++ } ++} ++ ++static int do_pri_br(aufs_bindex_t bindex, struct au_branch *br) ++{ ++ struct vfsmount *mnt; ++ struct super_block *sb; ++ ++ if (!br || IS_ERR(br)) ++ goto out; ++ mnt = au_br_mnt(br); ++ if (!mnt || IS_ERR(mnt)) ++ goto out; ++ sb = mnt->mnt_sb; ++ if (!sb || IS_ERR(sb)) ++ goto out; ++ ++ dpri("s%d: {perm 0x%x, id %d, wbr %p}, " ++ "%s, dev 0x%02x%02x, flags 0x%lx, cnt %d, active %d, " ++ "xino %d\n", ++ bindex, br->br_perm, br->br_id, br->br_wbr, ++ au_sbtype(sb), MAJOR(sb->s_dev), MINOR(sb->s_dev), ++ sb->s_flags, sb->s_count, ++ atomic_read(&sb->s_active), ++ !!au_xino_file(br->br_xino, /*idx*/-1)); ++ return 0; ++ ++out: ++ dpri("s%d: err %ld\n", bindex, PTR_ERR(br)); ++ return -1; ++} ++ ++void au_dpri_sb(struct super_block *sb) ++{ ++ struct au_sbinfo *sbinfo; ++ aufs_bindex_t bindex; ++ int err; ++ /* to reduce stack size */ ++ struct { ++ struct vfsmount mnt; ++ struct au_branch fake; ++ } *a; ++ ++ /* this function can be called from magic sysrq */ ++ a = kzalloc(sizeof(*a), GFP_ATOMIC); ++ if (unlikely(!a)) { ++ dpri("no memory\n"); ++ return; ++ } ++ ++ a->mnt.mnt_sb = sb; ++ a->fake.br_path.mnt = &a->mnt; ++ err = do_pri_br(-1, &a->fake); ++ au_kfree_rcu(a); ++ dpri("dev 0x%x\n", sb->s_dev); ++ if (err || !au_test_aufs(sb)) ++ return; ++ ++ sbinfo = au_sbi(sb); ++ if (!sbinfo) ++ return; ++ dpri("nw %d, gen %u, kobj %d\n", ++ atomic_read(&sbinfo->si_nowait.nw_len), sbinfo->si_generation, ++ kref_read(&sbinfo->si_kobj.kref)); ++ for (bindex = 0; bindex <= sbinfo->si_bbot; bindex++) ++ do_pri_br(bindex, sbinfo->si_branch[0 + bindex]); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++void __au_dbg_verify_dinode(struct dentry *dentry, const char *func, int line) ++{ ++ struct inode *h_inode, *inode = d_inode(dentry); ++ struct dentry *h_dentry; ++ aufs_bindex_t bindex, bbot, bi; ++ ++ if (!inode /* || au_di(dentry)->di_lsc == AuLsc_DI_TMP */) ++ return; ++ ++ bbot = au_dbbot(dentry); ++ bi = au_ibbot(inode); ++ if (bi < bbot) ++ bbot = bi; ++ bindex = au_dbtop(dentry); ++ bi = au_ibtop(inode); ++ if (bi > bindex) ++ bindex = bi; ++ ++ for (; bindex <= bbot; bindex++) { ++ h_dentry = au_h_dptr(dentry, bindex); ++ if (!h_dentry) ++ continue; ++ h_inode = au_h_iptr(inode, bindex); ++ if (unlikely(h_inode != d_inode(h_dentry))) { ++ au_debug_on(); ++ AuDbg("b%d, %s:%d\n", bindex, func, line); ++ AuDbgDentry(dentry); ++ AuDbgInode(inode); ++ au_debug_off(); ++ BUG(); ++ } ++ } ++} ++ ++void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen) ++{ ++ int err, i, j; ++ struct au_dcsub_pages dpages; ++ struct au_dpage *dpage; ++ struct dentry **dentries; ++ ++ err = au_dpages_init(&dpages, GFP_NOFS); ++ AuDebugOn(err); ++ err = au_dcsub_pages_rev_aufs(&dpages, parent, /*do_include*/1); ++ AuDebugOn(err); ++ for (i = dpages.ndpage - 1; !err && i >= 0; i--) { ++ dpage = dpages.dpages + i; ++ dentries = dpage->dentries; ++ for (j = dpage->ndentry - 1; !err && j >= 0; j--) ++ AuDebugOn(au_digen_test(dentries[j], sigen)); ++ } ++ au_dpages_free(&dpages); ++} ++ ++void au_dbg_verify_kthread(void) ++{ ++ if (au_wkq_test()) { ++ au_dbg_blocked(); ++ /* ++ * It may be recursive, but udba=notify between two aufs mounts, ++ * where a single ro branch is shared, is not a problem. ++ */ ++ /* WARN_ON(1); */ ++ } ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++int __init au_debug_init(void) ++{ ++ aufs_bindex_t bindex; ++ struct au_vdir_destr destr; ++ ++ bindex = -1; ++ AuDebugOn(bindex >= 0); ++ ++ destr.len = -1; ++ AuDebugOn(destr.len < NAME_MAX); ++ ++#ifdef CONFIG_4KSTACKS ++ pr_warn("CONFIG_4KSTACKS is defined.\n"); ++#endif ++ ++ return 0; ++} +diff -Nurp linux-5.4/fs/aufs/debug.h linux-5.4-aufs/fs/aufs/debug.h +--- linux-5.4/fs/aufs/debug.h 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/debug.h 2019-11-28 01:25:59.063925618 +0200 +@@ -0,0 +1,213 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * debug print functions ++ */ ++ ++#ifndef __AUFS_DEBUG_H__ ++#define __AUFS_DEBUG_H__ ++ ++#ifdef __KERNEL__ ++ ++#include ++#include ++#include ++#include ++ ++#ifdef CONFIG_AUFS_DEBUG ++#define AuDebugOn(a) BUG_ON(a) ++ ++/* module parameter */ ++extern atomic_t aufs_debug; ++static inline void au_debug_on(void) ++{ ++ atomic_inc(&aufs_debug); ++} ++static inline void au_debug_off(void) ++{ ++ atomic_dec_if_positive(&aufs_debug); ++} ++ ++static inline int au_debug_test(void) ++{ ++ return atomic_read(&aufs_debug) > 0; ++} ++#else ++#define AuDebugOn(a) do {} while (0) ++AuStubVoid(au_debug_on, void) ++AuStubVoid(au_debug_off, void) ++AuStubInt0(au_debug_test, void) ++#endif /* CONFIG_AUFS_DEBUG */ ++ ++#define param_check_atomic_t(name, p) __param_check(name, p, atomic_t) ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* debug print */ ++ ++#define AuDbg(fmt, ...) do { \ ++ if (au_debug_test()) \ ++ pr_debug("DEBUG: " fmt, ##__VA_ARGS__); \ ++} while (0) ++#define AuLabel(l) AuDbg(#l "\n") ++#define AuIOErr(fmt, ...) pr_err("I/O Error, " fmt, ##__VA_ARGS__) ++#define AuWarn1(fmt, ...) do { \ ++ static unsigned char _c; \ ++ if (!_c++) \ ++ pr_warn(fmt, ##__VA_ARGS__); \ ++} while (0) ++ ++#define AuErr1(fmt, ...) do { \ ++ static unsigned char _c; \ ++ if (!_c++) \ ++ pr_err(fmt, ##__VA_ARGS__); \ ++} while (0) ++ ++#define AuIOErr1(fmt, ...) do { \ ++ static unsigned char _c; \ ++ if (!_c++) \ ++ AuIOErr(fmt, ##__VA_ARGS__); \ ++} while (0) ++ ++#define AuUnsupportMsg "This operation is not supported." \ ++ " Please report this application to aufs-users ML." ++#define AuUnsupport(fmt, ...) do { \ ++ pr_err(AuUnsupportMsg "\n" fmt, ##__VA_ARGS__); \ ++ dump_stack(); \ ++} while (0) ++ ++#define AuTraceErr(e) do { \ ++ if (unlikely((e) < 0)) \ ++ AuDbg("err %d\n", (int)(e)); \ ++} while (0) ++ ++#define AuTraceErrPtr(p) do { \ ++ if (IS_ERR(p)) \ ++ AuDbg("err %ld\n", PTR_ERR(p)); \ ++} while (0) ++ ++/* dirty macros for debug print, use with "%.*s" and caution */ ++#define AuLNPair(qstr) (qstr)->len, (qstr)->name ++ ++/* ---------------------------------------------------------------------- */ ++ ++struct dentry; ++#ifdef CONFIG_AUFS_DEBUG ++extern struct mutex au_dbg_mtx; ++extern char *au_plevel; ++struct au_nhash; ++void au_dpri_whlist(struct au_nhash *whlist); ++struct au_vdir; ++void au_dpri_vdir(struct au_vdir *vdir); ++struct inode; ++void au_dpri_inode(struct inode *inode); ++void au_dpri_dalias(struct inode *inode); ++void au_dpri_dentry(struct dentry *dentry); ++struct file; ++void au_dpri_file(struct file *filp); ++struct super_block; ++void au_dpri_sb(struct super_block *sb); ++ ++#define au_dbg_verify_dinode(d) __au_dbg_verify_dinode(d, __func__, __LINE__) ++void __au_dbg_verify_dinode(struct dentry *dentry, const char *func, int line); ++void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen); ++void au_dbg_verify_kthread(void); ++ ++int __init au_debug_init(void); ++ ++#define AuDbgWhlist(w) do { \ ++ mutex_lock(&au_dbg_mtx); \ ++ AuDbg(#w "\n"); \ ++ au_dpri_whlist(w); \ ++ mutex_unlock(&au_dbg_mtx); \ ++} while (0) ++ ++#define AuDbgVdir(v) do { \ ++ mutex_lock(&au_dbg_mtx); \ ++ AuDbg(#v "\n"); \ ++ au_dpri_vdir(v); \ ++ mutex_unlock(&au_dbg_mtx); \ ++} while (0) ++ ++#define AuDbgInode(i) do { \ ++ mutex_lock(&au_dbg_mtx); \ ++ AuDbg(#i "\n"); \ ++ au_dpri_inode(i); \ ++ mutex_unlock(&au_dbg_mtx); \ ++} while (0) ++ ++#define AuDbgDAlias(i) do { \ ++ mutex_lock(&au_dbg_mtx); \ ++ AuDbg(#i "\n"); \ ++ au_dpri_dalias(i); \ ++ mutex_unlock(&au_dbg_mtx); \ ++} while (0) ++ ++#define AuDbgDentry(d) do { \ ++ mutex_lock(&au_dbg_mtx); \ ++ AuDbg(#d "\n"); \ ++ au_dpri_dentry(d); \ ++ mutex_unlock(&au_dbg_mtx); \ ++} while (0) ++ ++#define AuDbgFile(f) do { \ ++ mutex_lock(&au_dbg_mtx); \ ++ AuDbg(#f "\n"); \ ++ au_dpri_file(f); \ ++ mutex_unlock(&au_dbg_mtx); \ ++} while (0) ++ ++#define AuDbgSb(sb) do { \ ++ mutex_lock(&au_dbg_mtx); \ ++ AuDbg(#sb "\n"); \ ++ au_dpri_sb(sb); \ ++ mutex_unlock(&au_dbg_mtx); \ ++} while (0) ++ ++#define AuDbgSym(addr) do { \ ++ char sym[KSYM_SYMBOL_LEN]; \ ++ sprint_symbol(sym, (unsigned long)addr); \ ++ AuDbg("%s\n", sym); \ ++} while (0) ++#else ++AuStubVoid(au_dbg_verify_dinode, struct dentry *dentry) ++AuStubVoid(au_dbg_verify_gen, struct dentry *parent, unsigned int sigen) ++AuStubVoid(au_dbg_verify_kthread, void) ++AuStubInt0(__init au_debug_init, void) ++ ++#define AuDbgWhlist(w) do {} while (0) ++#define AuDbgVdir(v) do {} while (0) ++#define AuDbgInode(i) do {} while (0) ++#define AuDbgDAlias(i) do {} while (0) ++#define AuDbgDentry(d) do {} while (0) ++#define AuDbgFile(f) do {} while (0) ++#define AuDbgSb(sb) do {} while (0) ++#define AuDbgSym(addr) do {} while (0) ++#endif /* CONFIG_AUFS_DEBUG */ ++ ++/* ---------------------------------------------------------------------- */ ++ ++#ifdef CONFIG_AUFS_MAGIC_SYSRQ ++int __init au_sysrq_init(void); ++void au_sysrq_fin(void); ++ ++#ifdef CONFIG_HW_CONSOLE ++#define au_dbg_blocked() do { \ ++ WARN_ON(1); \ ++ handle_sysrq('w'); \ ++} while (0) ++#else ++AuStubVoid(au_dbg_blocked, void) ++#endif ++ ++#else ++AuStubInt0(__init au_sysrq_init, void) ++AuStubVoid(au_sysrq_fin, void) ++AuStubVoid(au_dbg_blocked, void) ++#endif /* CONFIG_AUFS_MAGIC_SYSRQ */ ++ ++#endif /* __KERNEL__ */ ++#endif /* __AUFS_DEBUG_H__ */ +diff -Nurp linux-5.4/fs/aufs/dentry.c linux-5.4-aufs/fs/aufs/dentry.c +--- linux-5.4/fs/aufs/dentry.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/dentry.c 2019-11-28 01:25:59.063925618 +0200 +@@ -0,0 +1,1141 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * lookup and dentry operations ++ */ ++ ++#include ++#include ++#include "aufs.h" ++ ++/* ++ * returns positive/negative dentry, NULL or an error. ++ * NULL means whiteout-ed or not-found. ++ */ ++static struct dentry* ++au_do_lookup(struct dentry *h_parent, struct dentry *dentry, ++ aufs_bindex_t bindex, struct au_do_lookup_args *args) ++{ ++ struct dentry *h_dentry; ++ struct inode *h_inode; ++ struct au_branch *br; ++ int wh_found, opq; ++ unsigned char wh_able; ++ const unsigned char allow_neg = !!au_ftest_lkup(args->flags, ALLOW_NEG); ++ const unsigned char ignore_perm = !!au_ftest_lkup(args->flags, ++ IGNORE_PERM); ++ ++ wh_found = 0; ++ br = au_sbr(dentry->d_sb, bindex); ++ wh_able = !!au_br_whable(br->br_perm); ++ if (wh_able) ++ wh_found = au_wh_test(h_parent, &args->whname, ignore_perm); ++ h_dentry = ERR_PTR(wh_found); ++ if (!wh_found) ++ goto real_lookup; ++ if (unlikely(wh_found < 0)) ++ goto out; ++ ++ /* We found a whiteout */ ++ /* au_set_dbbot(dentry, bindex); */ ++ au_set_dbwh(dentry, bindex); ++ if (!allow_neg) ++ return NULL; /* success */ ++ ++real_lookup: ++ if (!ignore_perm) ++ h_dentry = vfsub_lkup_one(args->name, h_parent); ++ else ++ h_dentry = au_sio_lkup_one(args->name, h_parent); ++ if (IS_ERR(h_dentry)) { ++ if (PTR_ERR(h_dentry) == -ENAMETOOLONG ++ && !allow_neg) ++ h_dentry = NULL; ++ goto out; ++ } ++ ++ h_inode = d_inode(h_dentry); ++ if (d_is_negative(h_dentry)) { ++ if (!allow_neg) ++ goto out_neg; ++ } else if (wh_found ++ || (args->type && args->type != (h_inode->i_mode & S_IFMT))) ++ goto out_neg; ++ else if (au_ftest_lkup(args->flags, DIRREN) ++ /* && h_inode */ ++ && !au_dr_lkup_h_ino(args, bindex, h_inode->i_ino)) { ++ AuDbg("b%d %pd ignored hi%llu\n", bindex, h_dentry, ++ (unsigned long long)h_inode->i_ino); ++ goto out_neg; ++ } ++ ++ if (au_dbbot(dentry) <= bindex) ++ au_set_dbbot(dentry, bindex); ++ if (au_dbtop(dentry) < 0 || bindex < au_dbtop(dentry)) ++ au_set_dbtop(dentry, bindex); ++ au_set_h_dptr(dentry, bindex, h_dentry); ++ ++ if (!d_is_dir(h_dentry) ++ || !wh_able ++ || (d_really_is_positive(dentry) && !d_is_dir(dentry))) ++ goto out; /* success */ ++ ++ inode_lock_shared_nested(h_inode, AuLsc_I_CHILD); ++ opq = au_diropq_test(h_dentry); ++ inode_unlock_shared(h_inode); ++ if (opq > 0) ++ au_set_dbdiropq(dentry, bindex); ++ else if (unlikely(opq < 0)) { ++ au_set_h_dptr(dentry, bindex, NULL); ++ h_dentry = ERR_PTR(opq); ++ } ++ goto out; ++ ++out_neg: ++ dput(h_dentry); ++ h_dentry = NULL; ++out: ++ return h_dentry; ++} ++ ++static int au_test_shwh(struct super_block *sb, const struct qstr *name) ++{ ++ if (unlikely(!au_opt_test(au_mntflags(sb), SHWH) ++ && !strncmp(name->name, AUFS_WH_PFX, AUFS_WH_PFX_LEN))) ++ return -EPERM; ++ return 0; ++} ++ ++/* ++ * returns the number of lower positive dentries, ++ * otherwise an error. ++ * can be called at unlinking with @type is zero. ++ */ ++int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t btop, ++ unsigned int flags) ++{ ++ int npositive, err; ++ aufs_bindex_t bindex, btail, bdiropq; ++ unsigned char isdir, dirperm1, dirren; ++ struct au_do_lookup_args args = { ++ .flags = flags, ++ .name = &dentry->d_name ++ }; ++ struct dentry *parent; ++ struct super_block *sb; ++ ++ sb = dentry->d_sb; ++ err = au_test_shwh(sb, args.name); ++ if (unlikely(err)) ++ goto out; ++ ++ err = au_wh_name_alloc(&args.whname, args.name); ++ if (unlikely(err)) ++ goto out; ++ ++ isdir = !!d_is_dir(dentry); ++ dirperm1 = !!au_opt_test(au_mntflags(sb), DIRPERM1); ++ dirren = !!au_opt_test(au_mntflags(sb), DIRREN); ++ if (dirren) ++ au_fset_lkup(args.flags, DIRREN); ++ ++ npositive = 0; ++ parent = dget_parent(dentry); ++ btail = au_dbtaildir(parent); ++ for (bindex = btop; bindex <= btail; bindex++) { ++ struct dentry *h_parent, *h_dentry; ++ struct inode *h_inode, *h_dir; ++ struct au_branch *br; ++ ++ h_dentry = au_h_dptr(dentry, bindex); ++ if (h_dentry) { ++ if (d_is_positive(h_dentry)) ++ npositive++; ++ break; ++ } ++ h_parent = au_h_dptr(parent, bindex); ++ if (!h_parent || !d_is_dir(h_parent)) ++ continue; ++ ++ if (dirren) { ++ /* if the inum matches, then use the prepared name */ ++ err = au_dr_lkup_name(&args, bindex); ++ if (unlikely(err)) ++ goto out_parent; ++ } ++ ++ h_dir = d_inode(h_parent); ++ inode_lock_shared_nested(h_dir, AuLsc_I_PARENT); ++ h_dentry = au_do_lookup(h_parent, dentry, bindex, &args); ++ inode_unlock_shared(h_dir); ++ err = PTR_ERR(h_dentry); ++ if (IS_ERR(h_dentry)) ++ goto out_parent; ++ if (h_dentry) ++ au_fclr_lkup(args.flags, ALLOW_NEG); ++ if (dirperm1) ++ au_fset_lkup(args.flags, IGNORE_PERM); ++ ++ if (au_dbwh(dentry) == bindex) ++ break; ++ if (!h_dentry) ++ continue; ++ if (d_is_negative(h_dentry)) ++ continue; ++ h_inode = d_inode(h_dentry); ++ npositive++; ++ if (!args.type) ++ args.type = h_inode->i_mode & S_IFMT; ++ if (args.type != S_IFDIR) ++ break; ++ else if (isdir) { ++ /* the type of lower may be different */ ++ bdiropq = au_dbdiropq(dentry); ++ if (bdiropq >= 0 && bdiropq <= bindex) ++ break; ++ } ++ br = au_sbr(sb, bindex); ++ if (dirren ++ && au_dr_hino_test_add(&br->br_dirren, h_inode->i_ino, ++ /*add_ent*/NULL)) { ++ /* prepare next name to lookup */ ++ err = au_dr_lkup(&args, dentry, bindex); ++ if (unlikely(err)) ++ goto out_parent; ++ } ++ } ++ ++ if (npositive) { ++ AuLabel(positive); ++ au_update_dbtop(dentry); ++ } ++ err = npositive; ++ if (unlikely(!au_opt_test(au_mntflags(sb), UDBA_NONE) ++ && au_dbtop(dentry) < 0)) { ++ err = -EIO; ++ AuIOErr("both of real entry and whiteout found, %pd, err %d\n", ++ dentry, err); ++ } ++ ++out_parent: ++ dput(parent); ++ au_kfree_try_rcu(args.whname.name); ++ if (dirren) ++ au_dr_lkup_fin(&args); ++out: ++ return err; ++} ++ ++struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent) ++{ ++ struct dentry *dentry; ++ int wkq_err; ++ ++ if (!au_test_h_perm_sio(d_inode(parent), MAY_EXEC)) ++ dentry = vfsub_lkup_one(name, parent); ++ else { ++ struct vfsub_lkup_one_args args = { ++ .errp = &dentry, ++ .name = name, ++ .parent = parent ++ }; ++ ++ wkq_err = au_wkq_wait(vfsub_call_lkup_one, &args); ++ if (unlikely(wkq_err)) ++ dentry = ERR_PTR(wkq_err); ++ } ++ ++ return dentry; ++} ++ ++/* ++ * lookup @dentry on @bindex which should be negative. ++ */ ++int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex, int wh) ++{ ++ int err; ++ struct dentry *parent, *h_parent, *h_dentry; ++ struct au_branch *br; ++ ++ parent = dget_parent(dentry); ++ h_parent = au_h_dptr(parent, bindex); ++ br = au_sbr(dentry->d_sb, bindex); ++ if (wh) ++ h_dentry = au_whtmp_lkup(h_parent, br, &dentry->d_name); ++ else ++ h_dentry = au_sio_lkup_one(&dentry->d_name, h_parent); ++ err = PTR_ERR(h_dentry); ++ if (IS_ERR(h_dentry)) ++ goto out; ++ if (unlikely(d_is_positive(h_dentry))) { ++ err = -EIO; ++ AuIOErr("%pd should be negative on b%d.\n", h_dentry, bindex); ++ dput(h_dentry); ++ goto out; ++ } ++ ++ err = 0; ++ if (bindex < au_dbtop(dentry)) ++ au_set_dbtop(dentry, bindex); ++ if (au_dbbot(dentry) < bindex) ++ au_set_dbbot(dentry, bindex); ++ au_set_h_dptr(dentry, bindex, h_dentry); ++ ++out: ++ dput(parent); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* subset of struct inode */ ++struct au_iattr { ++ unsigned long i_ino; ++ /* unsigned int i_nlink; */ ++ kuid_t i_uid; ++ kgid_t i_gid; ++ u64 i_version; ++/* ++ loff_t i_size; ++ blkcnt_t i_blocks; ++*/ ++ umode_t i_mode; ++}; ++ ++static void au_iattr_save(struct au_iattr *ia, struct inode *h_inode) ++{ ++ ia->i_ino = h_inode->i_ino; ++ /* ia->i_nlink = h_inode->i_nlink; */ ++ ia->i_uid = h_inode->i_uid; ++ ia->i_gid = h_inode->i_gid; ++ ia->i_version = inode_query_iversion(h_inode); ++/* ++ ia->i_size = h_inode->i_size; ++ ia->i_blocks = h_inode->i_blocks; ++*/ ++ ia->i_mode = (h_inode->i_mode & S_IFMT); ++} ++ ++static int au_iattr_test(struct au_iattr *ia, struct inode *h_inode) ++{ ++ return ia->i_ino != h_inode->i_ino ++ /* || ia->i_nlink != h_inode->i_nlink */ ++ || !uid_eq(ia->i_uid, h_inode->i_uid) ++ || !gid_eq(ia->i_gid, h_inode->i_gid) ++ || !inode_eq_iversion(h_inode, ia->i_version) ++/* ++ || ia->i_size != h_inode->i_size ++ || ia->i_blocks != h_inode->i_blocks ++*/ ++ || ia->i_mode != (h_inode->i_mode & S_IFMT); ++} ++ ++static int au_h_verify_dentry(struct dentry *h_dentry, struct dentry *h_parent, ++ struct au_branch *br) ++{ ++ int err; ++ struct au_iattr ia; ++ struct inode *h_inode; ++ struct dentry *h_d; ++ struct super_block *h_sb; ++ ++ err = 0; ++ memset(&ia, -1, sizeof(ia)); ++ h_sb = h_dentry->d_sb; ++ h_inode = NULL; ++ if (d_is_positive(h_dentry)) { ++ h_inode = d_inode(h_dentry); ++ au_iattr_save(&ia, h_inode); ++ } else if (au_test_nfs(h_sb) || au_test_fuse(h_sb)) ++ /* nfs d_revalidate may return 0 for negative dentry */ ++ /* fuse d_revalidate always return 0 for negative dentry */ ++ goto out; ++ ++ /* main purpose is namei.c:cached_lookup() and d_revalidate */ ++ h_d = vfsub_lkup_one(&h_dentry->d_name, h_parent); ++ err = PTR_ERR(h_d); ++ if (IS_ERR(h_d)) ++ goto out; ++ ++ err = 0; ++ if (unlikely(h_d != h_dentry ++ || d_inode(h_d) != h_inode ++ || (h_inode && au_iattr_test(&ia, h_inode)))) ++ err = au_busy_or_stale(); ++ dput(h_d); ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir, ++ struct dentry *h_parent, struct au_branch *br) ++{ ++ int err; ++ ++ err = 0; ++ if (udba == AuOpt_UDBA_REVAL ++ && !au_test_fs_remote(h_dentry->d_sb)) { ++ IMustLock(h_dir); ++ err = (d_inode(h_dentry->d_parent) != h_dir); ++ } else if (udba != AuOpt_UDBA_NONE) ++ err = au_h_verify_dentry(h_dentry, h_parent, br); ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int au_do_refresh_hdentry(struct dentry *dentry, struct dentry *parent) ++{ ++ int err; ++ aufs_bindex_t new_bindex, bindex, bbot, bwh, bdiropq; ++ struct au_hdentry tmp, *p, *q; ++ struct au_dinfo *dinfo; ++ struct super_block *sb; ++ ++ DiMustWriteLock(dentry); ++ ++ sb = dentry->d_sb; ++ dinfo = au_di(dentry); ++ bbot = dinfo->di_bbot; ++ bwh = dinfo->di_bwh; ++ bdiropq = dinfo->di_bdiropq; ++ bindex = dinfo->di_btop; ++ p = au_hdentry(dinfo, bindex); ++ for (; bindex <= bbot; bindex++, p++) { ++ if (!p->hd_dentry) ++ continue; ++ ++ new_bindex = au_br_index(sb, p->hd_id); ++ if (new_bindex == bindex) ++ continue; ++ ++ if (dinfo->di_bwh == bindex) ++ bwh = new_bindex; ++ if (dinfo->di_bdiropq == bindex) ++ bdiropq = new_bindex; ++ if (new_bindex < 0) { ++ au_hdput(p); ++ p->hd_dentry = NULL; ++ continue; ++ } ++ ++ /* swap two lower dentries, and loop again */ ++ q = au_hdentry(dinfo, new_bindex); ++ tmp = *q; ++ *q = *p; ++ *p = tmp; ++ if (tmp.hd_dentry) { ++ bindex--; ++ p--; ++ } ++ } ++ ++ dinfo->di_bwh = -1; ++ if (bwh >= 0 && bwh <= au_sbbot(sb) && au_sbr_whable(sb, bwh)) ++ dinfo->di_bwh = bwh; ++ ++ dinfo->di_bdiropq = -1; ++ if (bdiropq >= 0 ++ && bdiropq <= au_sbbot(sb) ++ && au_sbr_whable(sb, bdiropq)) ++ dinfo->di_bdiropq = bdiropq; ++ ++ err = -EIO; ++ dinfo->di_btop = -1; ++ dinfo->di_bbot = -1; ++ bbot = au_dbbot(parent); ++ bindex = 0; ++ p = au_hdentry(dinfo, bindex); ++ for (; bindex <= bbot; bindex++, p++) ++ if (p->hd_dentry) { ++ dinfo->di_btop = bindex; ++ break; ++ } ++ ++ if (dinfo->di_btop >= 0) { ++ bindex = bbot; ++ p = au_hdentry(dinfo, bindex); ++ for (; bindex >= 0; bindex--, p--) ++ if (p->hd_dentry) { ++ dinfo->di_bbot = bindex; ++ err = 0; ++ break; ++ } ++ } ++ ++ return err; ++} ++ ++static void au_do_hide(struct dentry *dentry) ++{ ++ struct inode *inode; ++ ++ if (d_really_is_positive(dentry)) { ++ inode = d_inode(dentry); ++ if (!d_is_dir(dentry)) { ++ if (inode->i_nlink && !d_unhashed(dentry)) ++ drop_nlink(inode); ++ } else { ++ clear_nlink(inode); ++ /* stop next lookup */ ++ inode->i_flags |= S_DEAD; ++ } ++ smp_mb(); /* necessary? */ ++ } ++ d_drop(dentry); ++} ++ ++static int au_hide_children(struct dentry *parent) ++{ ++ int err, i, j, ndentry; ++ struct au_dcsub_pages dpages; ++ struct au_dpage *dpage; ++ struct dentry *dentry; ++ ++ err = au_dpages_init(&dpages, GFP_NOFS); ++ if (unlikely(err)) ++ goto out; ++ err = au_dcsub_pages(&dpages, parent, NULL, NULL); ++ if (unlikely(err)) ++ goto out_dpages; ++ ++ /* in reverse order */ ++ for (i = dpages.ndpage - 1; i >= 0; i--) { ++ dpage = dpages.dpages + i; ++ ndentry = dpage->ndentry; ++ for (j = ndentry - 1; j >= 0; j--) { ++ dentry = dpage->dentries[j]; ++ if (dentry != parent) ++ au_do_hide(dentry); ++ } ++ } ++ ++out_dpages: ++ au_dpages_free(&dpages); ++out: ++ return err; ++} ++ ++static void au_hide(struct dentry *dentry) ++{ ++ int err; ++ ++ AuDbgDentry(dentry); ++ if (d_is_dir(dentry)) { ++ /* shrink_dcache_parent(dentry); */ ++ err = au_hide_children(dentry); ++ if (unlikely(err)) ++ AuIOErr("%pd, failed hiding children, ignored %d\n", ++ dentry, err); ++ } ++ au_do_hide(dentry); ++} ++ ++/* ++ * By adding a dirty branch, a cached dentry may be affected in various ways. ++ * ++ * a dirty branch is added ++ * - on the top of layers ++ * - in the middle of layers ++ * - to the bottom of layers ++ * ++ * on the added branch there exists ++ * - a whiteout ++ * - a diropq ++ * - a same named entry ++ * + exist ++ * * negative --> positive ++ * * positive --> positive ++ * - type is unchanged ++ * - type is changed ++ * + doesn't exist ++ * * negative --> negative ++ * * positive --> negative (rejected by au_br_del() for non-dir case) ++ * - none ++ */ ++static int au_refresh_by_dinfo(struct dentry *dentry, struct au_dinfo *dinfo, ++ struct au_dinfo *tmp) ++{ ++ int err; ++ aufs_bindex_t bindex, bbot; ++ struct { ++ struct dentry *dentry; ++ struct inode *inode; ++ mode_t mode; ++ } orig_h, tmp_h = { ++ .dentry = NULL ++ }; ++ struct au_hdentry *hd; ++ struct inode *inode, *h_inode; ++ struct dentry *h_dentry; ++ ++ err = 0; ++ AuDebugOn(dinfo->di_btop < 0); ++ orig_h.mode = 0; ++ orig_h.dentry = au_hdentry(dinfo, dinfo->di_btop)->hd_dentry; ++ orig_h.inode = NULL; ++ if (d_is_positive(orig_h.dentry)) { ++ orig_h.inode = d_inode(orig_h.dentry); ++ orig_h.mode = orig_h.inode->i_mode & S_IFMT; ++ } ++ if (tmp->di_btop >= 0) { ++ tmp_h.dentry = au_hdentry(tmp, tmp->di_btop)->hd_dentry; ++ if (d_is_positive(tmp_h.dentry)) { ++ tmp_h.inode = d_inode(tmp_h.dentry); ++ tmp_h.mode = tmp_h.inode->i_mode & S_IFMT; ++ } ++ } ++ ++ inode = NULL; ++ if (d_really_is_positive(dentry)) ++ inode = d_inode(dentry); ++ if (!orig_h.inode) { ++ AuDbg("negative originally\n"); ++ if (inode) { ++ au_hide(dentry); ++ goto out; ++ } ++ AuDebugOn(inode); ++ AuDebugOn(dinfo->di_btop != dinfo->di_bbot); ++ AuDebugOn(dinfo->di_bdiropq != -1); ++ ++ if (!tmp_h.inode) { ++ AuDbg("negative --> negative\n"); ++ /* should have only one negative lower */ ++ if (tmp->di_btop >= 0 ++ && tmp->di_btop < dinfo->di_btop) { ++ AuDebugOn(tmp->di_btop != tmp->di_bbot); ++ AuDebugOn(dinfo->di_btop != dinfo->di_bbot); ++ au_set_h_dptr(dentry, dinfo->di_btop, NULL); ++ au_di_cp(dinfo, tmp); ++ hd = au_hdentry(tmp, tmp->di_btop); ++ au_set_h_dptr(dentry, tmp->di_btop, ++ dget(hd->hd_dentry)); ++ } ++ au_dbg_verify_dinode(dentry); ++ } else { ++ AuDbg("negative --> positive\n"); ++ /* ++ * similar to the behaviour of creating with bypassing ++ * aufs. ++ * unhash it in order to force an error in the ++ * succeeding create operation. ++ * we should not set S_DEAD here. ++ */ ++ d_drop(dentry); ++ /* au_di_swap(tmp, dinfo); */ ++ au_dbg_verify_dinode(dentry); ++ } ++ } else { ++ AuDbg("positive originally\n"); ++ /* inode may be NULL */ ++ AuDebugOn(inode && (inode->i_mode & S_IFMT) != orig_h.mode); ++ if (!tmp_h.inode) { ++ AuDbg("positive --> negative\n"); ++ /* or bypassing aufs */ ++ au_hide(dentry); ++ if (tmp->di_bwh >= 0 && tmp->di_bwh <= dinfo->di_btop) ++ dinfo->di_bwh = tmp->di_bwh; ++ if (inode) ++ err = au_refresh_hinode_self(inode); ++ au_dbg_verify_dinode(dentry); ++ } else if (orig_h.mode == tmp_h.mode) { ++ AuDbg("positive --> positive, same type\n"); ++ if (!S_ISDIR(orig_h.mode) ++ && dinfo->di_btop > tmp->di_btop) { ++ /* ++ * similar to the behaviour of removing and ++ * creating. ++ */ ++ au_hide(dentry); ++ if (inode) ++ err = au_refresh_hinode_self(inode); ++ au_dbg_verify_dinode(dentry); ++ } else { ++ /* fill empty slots */ ++ if (dinfo->di_btop > tmp->di_btop) ++ dinfo->di_btop = tmp->di_btop; ++ if (dinfo->di_bbot < tmp->di_bbot) ++ dinfo->di_bbot = tmp->di_bbot; ++ dinfo->di_bwh = tmp->di_bwh; ++ dinfo->di_bdiropq = tmp->di_bdiropq; ++ bbot = dinfo->di_bbot; ++ bindex = tmp->di_btop; ++ hd = au_hdentry(tmp, bindex); ++ for (; bindex <= bbot; bindex++, hd++) { ++ if (au_h_dptr(dentry, bindex)) ++ continue; ++ h_dentry = hd->hd_dentry; ++ if (!h_dentry) ++ continue; ++ AuDebugOn(d_is_negative(h_dentry)); ++ h_inode = d_inode(h_dentry); ++ AuDebugOn(orig_h.mode ++ != (h_inode->i_mode ++ & S_IFMT)); ++ au_set_h_dptr(dentry, bindex, ++ dget(h_dentry)); ++ } ++ if (inode) ++ err = au_refresh_hinode(inode, dentry); ++ au_dbg_verify_dinode(dentry); ++ } ++ } else { ++ AuDbg("positive --> positive, different type\n"); ++ /* similar to the behaviour of removing and creating */ ++ au_hide(dentry); ++ if (inode) ++ err = au_refresh_hinode_self(inode); ++ au_dbg_verify_dinode(dentry); ++ } ++ } ++ ++out: ++ return err; ++} ++ ++void au_refresh_dop(struct dentry *dentry, int force_reval) ++{ ++ const struct dentry_operations *dop ++ = force_reval ? &aufs_dop : dentry->d_sb->s_d_op; ++ static const unsigned int mask ++ = DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE; ++ ++ BUILD_BUG_ON(sizeof(mask) != sizeof(dentry->d_flags)); ++ ++ if (dentry->d_op == dop) ++ return; ++ ++ AuDbg("%pd\n", dentry); ++ spin_lock(&dentry->d_lock); ++ if (dop == &aufs_dop) ++ dentry->d_flags |= mask; ++ else ++ dentry->d_flags &= ~mask; ++ dentry->d_op = dop; ++ spin_unlock(&dentry->d_lock); ++} ++ ++int au_refresh_dentry(struct dentry *dentry, struct dentry *parent) ++{ ++ int err, ebrange, nbr; ++ unsigned int sigen; ++ struct au_dinfo *dinfo, *tmp; ++ struct super_block *sb; ++ struct inode *inode; ++ ++ DiMustWriteLock(dentry); ++ AuDebugOn(IS_ROOT(dentry)); ++ AuDebugOn(d_really_is_negative(parent)); ++ ++ sb = dentry->d_sb; ++ sigen = au_sigen(sb); ++ err = au_digen_test(parent, sigen); ++ if (unlikely(err)) ++ goto out; ++ ++ nbr = au_sbbot(sb) + 1; ++ dinfo = au_di(dentry); ++ err = au_di_realloc(dinfo, nbr, /*may_shrink*/0); ++ if (unlikely(err)) ++ goto out; ++ ebrange = au_dbrange_test(dentry); ++ if (!ebrange) ++ ebrange = au_do_refresh_hdentry(dentry, parent); ++ ++ if (d_unhashed(dentry) || ebrange /* || dinfo->di_tmpfile */) { ++ AuDebugOn(au_dbtop(dentry) < 0 && au_dbbot(dentry) >= 0); ++ if (d_really_is_positive(dentry)) { ++ inode = d_inode(dentry); ++ err = au_refresh_hinode_self(inode); ++ } ++ au_dbg_verify_dinode(dentry); ++ if (!err) ++ goto out_dgen; /* success */ ++ goto out; ++ } ++ ++ /* temporary dinfo */ ++ AuDbgDentry(dentry); ++ err = -ENOMEM; ++ tmp = au_di_alloc(sb, AuLsc_DI_TMP); ++ if (unlikely(!tmp)) ++ goto out; ++ au_di_swap(tmp, dinfo); ++ /* returns the number of positive dentries */ ++ /* ++ * if current working dir is removed, it returns an error. ++ * but the dentry is legal. ++ */ ++ err = au_lkup_dentry(dentry, /*btop*/0, AuLkup_ALLOW_NEG); ++ AuDbgDentry(dentry); ++ au_di_swap(tmp, dinfo); ++ if (err == -ENOENT) ++ err = 0; ++ if (err >= 0) { ++ /* compare/refresh by dinfo */ ++ AuDbgDentry(dentry); ++ err = au_refresh_by_dinfo(dentry, dinfo, tmp); ++ au_dbg_verify_dinode(dentry); ++ AuTraceErr(err); ++ } ++ au_di_realloc(dinfo, nbr, /*may_shrink*/1); /* harmless if err */ ++ au_rw_write_unlock(&tmp->di_rwsem); ++ au_di_free(tmp); ++ if (unlikely(err)) ++ goto out; ++ ++out_dgen: ++ au_update_digen(dentry); ++out: ++ if (unlikely(err && !(dentry->d_flags & DCACHE_NFSFS_RENAMED))) { ++ AuIOErr("failed refreshing %pd, %d\n", dentry, err); ++ AuDbgDentry(dentry); ++ } ++ AuTraceErr(err); ++ return err; ++} ++ ++static int au_do_h_d_reval(struct dentry *h_dentry, unsigned int flags, ++ struct dentry *dentry, aufs_bindex_t bindex) ++{ ++ int err, valid; ++ ++ err = 0; ++ if (!(h_dentry->d_flags & DCACHE_OP_REVALIDATE)) ++ goto out; ++ ++ AuDbg("b%d\n", bindex); ++ /* ++ * gave up supporting LOOKUP_CREATE/OPEN for lower fs, ++ * due to whiteout and branch permission. ++ */ ++ flags &= ~(/*LOOKUP_PARENT |*/ LOOKUP_OPEN | LOOKUP_CREATE ++ | LOOKUP_FOLLOW | LOOKUP_EXCL); ++ /* it may return tri-state */ ++ valid = h_dentry->d_op->d_revalidate(h_dentry, flags); ++ ++ if (unlikely(valid < 0)) ++ err = valid; ++ else if (!valid) ++ err = -EINVAL; ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++/* todo: remove this */ ++static int h_d_revalidate(struct dentry *dentry, struct inode *inode, ++ unsigned int flags, int do_udba, int dirren) ++{ ++ int err; ++ umode_t mode, h_mode; ++ aufs_bindex_t bindex, btail, btop, ibs, ibe; ++ unsigned char plus, unhashed, is_root, h_plus, h_nfs, tmpfile; ++ struct inode *h_inode, *h_cached_inode; ++ struct dentry *h_dentry; ++ struct qstr *name, *h_name; ++ ++ err = 0; ++ plus = 0; ++ mode = 0; ++ ibs = -1; ++ ibe = -1; ++ unhashed = !!d_unhashed(dentry); ++ is_root = !!IS_ROOT(dentry); ++ name = &dentry->d_name; ++ tmpfile = au_di(dentry)->di_tmpfile; ++ ++ /* ++ * Theoretically, REVAL test should be unnecessary in case of ++ * {FS,I}NOTIFY. ++ * But {fs,i}notify doesn't fire some necessary events, ++ * IN_ATTRIB for atime/nlink/pageio ++ * Let's do REVAL test too. ++ */ ++ if (do_udba && inode) { ++ mode = (inode->i_mode & S_IFMT); ++ plus = (inode->i_nlink > 0); ++ ibs = au_ibtop(inode); ++ ibe = au_ibbot(inode); ++ } ++ ++ btop = au_dbtop(dentry); ++ btail = btop; ++ if (inode && S_ISDIR(inode->i_mode)) ++ btail = au_dbtaildir(dentry); ++ for (bindex = btop; bindex <= btail; bindex++) { ++ h_dentry = au_h_dptr(dentry, bindex); ++ if (!h_dentry) ++ continue; ++ ++ AuDbg("b%d, %pd\n", bindex, h_dentry); ++ h_nfs = !!au_test_nfs(h_dentry->d_sb); ++ spin_lock(&h_dentry->d_lock); ++ h_name = &h_dentry->d_name; ++ if (unlikely(do_udba ++ && !is_root ++ && ((!h_nfs ++ && (unhashed != !!d_unhashed(h_dentry) ++ || (!tmpfile && !dirren ++ && !au_qstreq(name, h_name)) ++ )) ++ || (h_nfs ++ && !(flags & LOOKUP_OPEN) ++ && (h_dentry->d_flags ++ & DCACHE_NFSFS_RENAMED))) ++ )) { ++ int h_unhashed; ++ ++ h_unhashed = d_unhashed(h_dentry); ++ spin_unlock(&h_dentry->d_lock); ++ AuDbg("unhash 0x%x 0x%x, %pd %pd\n", ++ unhashed, h_unhashed, dentry, h_dentry); ++ goto err; ++ } ++ spin_unlock(&h_dentry->d_lock); ++ ++ err = au_do_h_d_reval(h_dentry, flags, dentry, bindex); ++ if (unlikely(err)) ++ /* do not goto err, to keep the errno */ ++ break; ++ ++ /* todo: plink too? */ ++ if (!do_udba) ++ continue; ++ ++ /* UDBA tests */ ++ if (unlikely(!!inode != d_is_positive(h_dentry))) ++ goto err; ++ ++ h_inode = NULL; ++ if (d_is_positive(h_dentry)) ++ h_inode = d_inode(h_dentry); ++ h_plus = plus; ++ h_mode = mode; ++ h_cached_inode = h_inode; ++ if (h_inode) { ++ h_mode = (h_inode->i_mode & S_IFMT); ++ h_plus = (h_inode->i_nlink > 0); ++ } ++ if (inode && ibs <= bindex && bindex <= ibe) ++ h_cached_inode = au_h_iptr(inode, bindex); ++ ++ if (!h_nfs) { ++ if (unlikely(plus != h_plus && !tmpfile)) ++ goto err; ++ } else { ++ if (unlikely(!(h_dentry->d_flags & DCACHE_NFSFS_RENAMED) ++ && !is_root ++ && !IS_ROOT(h_dentry) ++ && unhashed != d_unhashed(h_dentry))) ++ goto err; ++ } ++ if (unlikely(mode != h_mode ++ || h_cached_inode != h_inode)) ++ goto err; ++ continue; ++ ++err: ++ err = -EINVAL; ++ break; ++ } ++ ++ AuTraceErr(err); ++ return err; ++} ++ ++/* todo: consolidate with do_refresh() and au_reval_for_attr() */ ++static int simple_reval_dpath(struct dentry *dentry, unsigned int sigen) ++{ ++ int err; ++ struct dentry *parent; ++ ++ if (!au_digen_test(dentry, sigen)) ++ return 0; ++ ++ parent = dget_parent(dentry); ++ di_read_lock_parent(parent, AuLock_IR); ++ AuDebugOn(au_digen_test(parent, sigen)); ++ au_dbg_verify_gen(parent, sigen); ++ err = au_refresh_dentry(dentry, parent); ++ di_read_unlock(parent, AuLock_IR); ++ dput(parent); ++ AuTraceErr(err); ++ return err; ++} ++ ++int au_reval_dpath(struct dentry *dentry, unsigned int sigen) ++{ ++ int err; ++ struct dentry *d, *parent; ++ ++ if (!au_ftest_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIR)) ++ return simple_reval_dpath(dentry, sigen); ++ ++ /* slow loop, keep it simple and stupid */ ++ /* cf: au_cpup_dirs() */ ++ err = 0; ++ parent = NULL; ++ while (au_digen_test(dentry, sigen)) { ++ d = dentry; ++ while (1) { ++ dput(parent); ++ parent = dget_parent(d); ++ if (!au_digen_test(parent, sigen)) ++ break; ++ d = parent; ++ } ++ ++ if (d != dentry) ++ di_write_lock_child2(d); ++ ++ /* someone might update our dentry while we were sleeping */ ++ if (au_digen_test(d, sigen)) { ++ /* ++ * todo: consolidate with simple_reval_dpath(), ++ * do_refresh() and au_reval_for_attr(). ++ */ ++ di_read_lock_parent(parent, AuLock_IR); ++ err = au_refresh_dentry(d, parent); ++ di_read_unlock(parent, AuLock_IR); ++ } ++ ++ if (d != dentry) ++ di_write_unlock(d); ++ dput(parent); ++ if (unlikely(err)) ++ break; ++ } ++ ++ return err; ++} ++ ++/* ++ * if valid returns 1, otherwise 0. ++ */ ++static int aufs_d_revalidate(struct dentry *dentry, unsigned int flags) ++{ ++ int valid, err; ++ unsigned int sigen; ++ unsigned char do_udba, dirren; ++ struct super_block *sb; ++ struct inode *inode; ++ ++ /* todo: support rcu-walk? */ ++ if (flags & LOOKUP_RCU) ++ return -ECHILD; ++ ++ valid = 0; ++ if (unlikely(!au_di(dentry))) ++ goto out; ++ ++ valid = 1; ++ sb = dentry->d_sb; ++ /* ++ * todo: very ugly ++ * i_mutex of parent dir may be held, ++ * but we should not return 'invalid' due to busy. ++ */ ++ err = aufs_read_lock(dentry, AuLock_FLUSH | AuLock_DW | AuLock_NOPLM); ++ if (unlikely(err)) { ++ valid = err; ++ AuTraceErr(err); ++ goto out; ++ } ++ inode = NULL; ++ if (d_really_is_positive(dentry)) ++ inode = d_inode(dentry); ++ if (unlikely(inode && au_is_bad_inode(inode))) { ++ err = -EINVAL; ++ AuTraceErr(err); ++ goto out_dgrade; ++ } ++ if (unlikely(au_dbrange_test(dentry))) { ++ err = -EINVAL; ++ AuTraceErr(err); ++ goto out_dgrade; ++ } ++ ++ sigen = au_sigen(sb); ++ if (au_digen_test(dentry, sigen)) { ++ AuDebugOn(IS_ROOT(dentry)); ++ err = au_reval_dpath(dentry, sigen); ++ if (unlikely(err)) { ++ AuTraceErr(err); ++ goto out_dgrade; ++ } ++ } ++ di_downgrade_lock(dentry, AuLock_IR); ++ ++ err = -EINVAL; ++ if (!(flags & (LOOKUP_OPEN | LOOKUP_EMPTY)) ++ && inode ++ && !(inode->i_state && I_LINKABLE) ++ && (IS_DEADDIR(inode) || !inode->i_nlink)) { ++ AuTraceErr(err); ++ goto out_inval; ++ } ++ ++ do_udba = !au_opt_test(au_mntflags(sb), UDBA_NONE); ++ if (do_udba && inode) { ++ aufs_bindex_t btop = au_ibtop(inode); ++ struct inode *h_inode; ++ ++ if (btop >= 0) { ++ h_inode = au_h_iptr(inode, btop); ++ if (h_inode && au_test_higen(inode, h_inode)) { ++ AuTraceErr(err); ++ goto out_inval; ++ } ++ } ++ } ++ ++ dirren = !!au_opt_test(au_mntflags(sb), DIRREN); ++ err = h_d_revalidate(dentry, inode, flags, do_udba, dirren); ++ if (unlikely(!err && do_udba && au_dbtop(dentry) < 0)) { ++ err = -EIO; ++ AuDbg("both of real entry and whiteout found, %p, err %d\n", ++ dentry, err); ++ } ++ goto out_inval; ++ ++out_dgrade: ++ di_downgrade_lock(dentry, AuLock_IR); ++out_inval: ++ aufs_read_unlock(dentry, AuLock_IR); ++ AuTraceErr(err); ++ valid = !err; ++out: ++ if (!valid) { ++ AuDbg("%pd invalid, %d\n", dentry, valid); ++ d_drop(dentry); ++ } ++ return valid; ++} ++ ++static void aufs_d_release(struct dentry *dentry) ++{ ++ if (au_di(dentry)) { ++ au_di_fin(dentry); ++ au_hn_di_reinit(dentry); ++ } ++} ++ ++const struct dentry_operations aufs_dop = { ++ .d_revalidate = aufs_d_revalidate, ++ .d_weak_revalidate = aufs_d_revalidate, ++ .d_release = aufs_d_release ++}; ++ ++/* aufs_dop without d_revalidate */ ++const struct dentry_operations aufs_dop_noreval = { ++ .d_release = aufs_d_release ++}; +diff -Nurp linux-5.4/fs/aufs/dentry.h linux-5.4-aufs/fs/aufs/dentry.h +--- linux-5.4/fs/aufs/dentry.h 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/dentry.h 2019-11-28 01:25:59.063925618 +0200 +@@ -0,0 +1,255 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * lookup and dentry operations ++ */ ++ ++#ifndef __AUFS_DENTRY_H__ ++#define __AUFS_DENTRY_H__ ++ ++#ifdef __KERNEL__ ++ ++#include ++#include "dirren.h" ++#include "rwsem.h" ++ ++struct au_hdentry { ++ struct dentry *hd_dentry; ++ aufs_bindex_t hd_id; ++}; ++ ++struct au_dinfo { ++ atomic_t di_generation; ++ ++ struct au_rwsem di_rwsem; ++ aufs_bindex_t di_btop, di_bbot, di_bwh, di_bdiropq; ++ unsigned char di_tmpfile; /* to allow the different name */ ++ struct au_hdentry *di_hdentry; ++ struct rcu_head rcu; ++} ____cacheline_aligned_in_smp; ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* flags for au_lkup_dentry() */ ++#define AuLkup_ALLOW_NEG 1 ++#define AuLkup_IGNORE_PERM (1 << 1) ++#define AuLkup_DIRREN (1 << 2) ++#define au_ftest_lkup(flags, name) ((flags) & AuLkup_##name) ++#define au_fset_lkup(flags, name) \ ++ do { (flags) |= AuLkup_##name; } while (0) ++#define au_fclr_lkup(flags, name) \ ++ do { (flags) &= ~AuLkup_##name; } while (0) ++ ++#ifndef CONFIG_AUFS_DIRREN ++#undef AuLkup_DIRREN ++#define AuLkup_DIRREN 0 ++#endif ++ ++struct au_do_lookup_args { ++ unsigned int flags; ++ mode_t type; ++ struct qstr whname, *name; ++ struct au_dr_lookup dirren; ++}; ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* dentry.c */ ++extern const struct dentry_operations aufs_dop, aufs_dop_noreval; ++struct au_branch; ++struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent); ++int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir, ++ struct dentry *h_parent, struct au_branch *br); ++ ++int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t btop, ++ unsigned int flags); ++int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex, int wh); ++int au_refresh_dentry(struct dentry *dentry, struct dentry *parent); ++int au_reval_dpath(struct dentry *dentry, unsigned int sigen); ++void au_refresh_dop(struct dentry *dentry, int force_reval); ++ ++/* dinfo.c */ ++void au_di_init_once(void *_di); ++struct au_dinfo *au_di_alloc(struct super_block *sb, unsigned int lsc); ++void au_di_free(struct au_dinfo *dinfo); ++void au_di_swap(struct au_dinfo *a, struct au_dinfo *b); ++void au_di_cp(struct au_dinfo *dst, struct au_dinfo *src); ++int au_di_init(struct dentry *dentry); ++void au_di_fin(struct dentry *dentry); ++int au_di_realloc(struct au_dinfo *dinfo, int nbr, int may_shrink); ++ ++void di_read_lock(struct dentry *d, int flags, unsigned int lsc); ++void di_read_unlock(struct dentry *d, int flags); ++void di_downgrade_lock(struct dentry *d, int flags); ++void di_write_lock(struct dentry *d, unsigned int lsc); ++void di_write_unlock(struct dentry *d); ++void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir); ++void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir); ++void di_write_unlock2(struct dentry *d1, struct dentry *d2); ++ ++struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex); ++struct dentry *au_h_d_alias(struct dentry *dentry, aufs_bindex_t bindex); ++aufs_bindex_t au_dbtail(struct dentry *dentry); ++aufs_bindex_t au_dbtaildir(struct dentry *dentry); ++ ++void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex, ++ struct dentry *h_dentry); ++int au_digen_test(struct dentry *dentry, unsigned int sigen); ++int au_dbrange_test(struct dentry *dentry); ++void au_update_digen(struct dentry *dentry); ++void au_update_dbrange(struct dentry *dentry, int do_put_zero); ++void au_update_dbtop(struct dentry *dentry); ++void au_update_dbbot(struct dentry *dentry); ++int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry); ++ ++/* ---------------------------------------------------------------------- */ ++ ++static inline struct au_dinfo *au_di(struct dentry *dentry) ++{ ++ return dentry->d_fsdata; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* lock subclass for dinfo */ ++enum { ++ AuLsc_DI_CHILD, /* child first */ ++ AuLsc_DI_CHILD2, /* rename(2), link(2), and cpup at hnotify */ ++ AuLsc_DI_CHILD3, /* copyup dirs */ ++ AuLsc_DI_PARENT, ++ AuLsc_DI_PARENT2, ++ AuLsc_DI_PARENT3, ++ AuLsc_DI_TMP /* temp for replacing dinfo */ ++}; ++ ++/* ++ * di_read_lock_child, di_write_lock_child, ++ * di_read_lock_child2, di_write_lock_child2, ++ * di_read_lock_child3, di_write_lock_child3, ++ * di_read_lock_parent, di_write_lock_parent, ++ * di_read_lock_parent2, di_write_lock_parent2, ++ * di_read_lock_parent3, di_write_lock_parent3, ++ */ ++#define AuReadLockFunc(name, lsc) \ ++static inline void di_read_lock_##name(struct dentry *d, int flags) \ ++{ di_read_lock(d, flags, AuLsc_DI_##lsc); } ++ ++#define AuWriteLockFunc(name, lsc) \ ++static inline void di_write_lock_##name(struct dentry *d) \ ++{ di_write_lock(d, AuLsc_DI_##lsc); } ++ ++#define AuRWLockFuncs(name, lsc) \ ++ AuReadLockFunc(name, lsc) \ ++ AuWriteLockFunc(name, lsc) ++ ++AuRWLockFuncs(child, CHILD); ++AuRWLockFuncs(child2, CHILD2); ++AuRWLockFuncs(child3, CHILD3); ++AuRWLockFuncs(parent, PARENT); ++AuRWLockFuncs(parent2, PARENT2); ++AuRWLockFuncs(parent3, PARENT3); ++ ++#undef AuReadLockFunc ++#undef AuWriteLockFunc ++#undef AuRWLockFuncs ++ ++#define DiMustNoWaiters(d) AuRwMustNoWaiters(&au_di(d)->di_rwsem) ++#define DiMustAnyLock(d) AuRwMustAnyLock(&au_di(d)->di_rwsem) ++#define DiMustWriteLock(d) AuRwMustWriteLock(&au_di(d)->di_rwsem) ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* todo: memory barrier? */ ++static inline unsigned int au_digen(struct dentry *d) ++{ ++ return atomic_read(&au_di(d)->di_generation); ++} ++ ++static inline void au_h_dentry_init(struct au_hdentry *hdentry) ++{ ++ hdentry->hd_dentry = NULL; ++} ++ ++static inline struct au_hdentry *au_hdentry(struct au_dinfo *di, ++ aufs_bindex_t bindex) ++{ ++ return di->di_hdentry + bindex; ++} ++ ++static inline void au_hdput(struct au_hdentry *hd) ++{ ++ if (hd) ++ dput(hd->hd_dentry); ++} ++ ++static inline aufs_bindex_t au_dbtop(struct dentry *dentry) ++{ ++ DiMustAnyLock(dentry); ++ return au_di(dentry)->di_btop; ++} ++ ++static inline aufs_bindex_t au_dbbot(struct dentry *dentry) ++{ ++ DiMustAnyLock(dentry); ++ return au_di(dentry)->di_bbot; ++} ++ ++static inline aufs_bindex_t au_dbwh(struct dentry *dentry) ++{ ++ DiMustAnyLock(dentry); ++ return au_di(dentry)->di_bwh; ++} ++ ++static inline aufs_bindex_t au_dbdiropq(struct dentry *dentry) ++{ ++ DiMustAnyLock(dentry); ++ return au_di(dentry)->di_bdiropq; ++} ++ ++/* todo: hard/soft set? */ ++static inline void au_set_dbtop(struct dentry *dentry, aufs_bindex_t bindex) ++{ ++ DiMustWriteLock(dentry); ++ au_di(dentry)->di_btop = bindex; ++} ++ ++static inline void au_set_dbbot(struct dentry *dentry, aufs_bindex_t bindex) ++{ ++ DiMustWriteLock(dentry); ++ au_di(dentry)->di_bbot = bindex; ++} ++ ++static inline void au_set_dbwh(struct dentry *dentry, aufs_bindex_t bindex) ++{ ++ DiMustWriteLock(dentry); ++ /* dbwh can be outside of btop - bbot range */ ++ au_di(dentry)->di_bwh = bindex; ++} ++ ++static inline void au_set_dbdiropq(struct dentry *dentry, aufs_bindex_t bindex) ++{ ++ DiMustWriteLock(dentry); ++ au_di(dentry)->di_bdiropq = bindex; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++#ifdef CONFIG_AUFS_HNOTIFY ++static inline void au_digen_dec(struct dentry *d) ++{ ++ atomic_dec(&au_di(d)->di_generation); ++} ++ ++static inline void au_hn_di_reinit(struct dentry *dentry) ++{ ++ dentry->d_fsdata = NULL; ++} ++#else ++AuStubVoid(au_hn_di_reinit, struct dentry *dentry __maybe_unused) ++#endif /* CONFIG_AUFS_HNOTIFY */ ++ ++#endif /* __KERNEL__ */ ++#endif /* __AUFS_DENTRY_H__ */ +diff -Nurp linux-5.4/fs/aufs/dinfo.c linux-5.4-aufs/fs/aufs/dinfo.c +--- linux-5.4/fs/aufs/dinfo.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/dinfo.c 2019-11-28 01:25:59.063925618 +0200 +@@ -0,0 +1,541 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * dentry private data ++ */ ++ ++#include "aufs.h" ++ ++void au_di_init_once(void *_dinfo) ++{ ++ struct au_dinfo *dinfo = _dinfo; ++ ++ au_rw_init(&dinfo->di_rwsem); ++} ++ ++struct au_dinfo *au_di_alloc(struct super_block *sb, unsigned int lsc) ++{ ++ struct au_dinfo *dinfo; ++ int nbr, i; ++ ++ dinfo = au_cache_alloc_dinfo(); ++ if (unlikely(!dinfo)) ++ goto out; ++ ++ nbr = au_sbbot(sb) + 1; ++ if (nbr <= 0) ++ nbr = 1; ++ dinfo->di_hdentry = kcalloc(nbr, sizeof(*dinfo->di_hdentry), GFP_NOFS); ++ if (dinfo->di_hdentry) { ++ au_rw_write_lock_nested(&dinfo->di_rwsem, lsc); ++ dinfo->di_btop = -1; ++ dinfo->di_bbot = -1; ++ dinfo->di_bwh = -1; ++ dinfo->di_bdiropq = -1; ++ dinfo->di_tmpfile = 0; ++ for (i = 0; i < nbr; i++) ++ dinfo->di_hdentry[i].hd_id = -1; ++ goto out; ++ } ++ ++ au_cache_free_dinfo(dinfo); ++ dinfo = NULL; ++ ++out: ++ return dinfo; ++} ++ ++void au_di_free(struct au_dinfo *dinfo) ++{ ++ struct au_hdentry *p; ++ aufs_bindex_t bbot, bindex; ++ ++ /* dentry may not be revalidated */ ++ bindex = dinfo->di_btop; ++ if (bindex >= 0) { ++ bbot = dinfo->di_bbot; ++ p = au_hdentry(dinfo, bindex); ++ while (bindex++ <= bbot) ++ au_hdput(p++); ++ } ++ au_kfree_try_rcu(dinfo->di_hdentry); ++ au_cache_free_dinfo(dinfo); ++} ++ ++void au_di_swap(struct au_dinfo *a, struct au_dinfo *b) ++{ ++ struct au_hdentry *p; ++ aufs_bindex_t bi; ++ ++ AuRwMustWriteLock(&a->di_rwsem); ++ AuRwMustWriteLock(&b->di_rwsem); ++ ++#define DiSwap(v, name) \ ++ do { \ ++ v = a->di_##name; \ ++ a->di_##name = b->di_##name; \ ++ b->di_##name = v; \ ++ } while (0) ++ ++ DiSwap(p, hdentry); ++ DiSwap(bi, btop); ++ DiSwap(bi, bbot); ++ DiSwap(bi, bwh); ++ DiSwap(bi, bdiropq); ++ /* smp_mb(); */ ++ ++#undef DiSwap ++} ++ ++void au_di_cp(struct au_dinfo *dst, struct au_dinfo *src) ++{ ++ AuRwMustWriteLock(&dst->di_rwsem); ++ AuRwMustWriteLock(&src->di_rwsem); ++ ++ dst->di_btop = src->di_btop; ++ dst->di_bbot = src->di_bbot; ++ dst->di_bwh = src->di_bwh; ++ dst->di_bdiropq = src->di_bdiropq; ++ /* smp_mb(); */ ++} ++ ++int au_di_init(struct dentry *dentry) ++{ ++ int err; ++ struct super_block *sb; ++ struct au_dinfo *dinfo; ++ ++ err = 0; ++ sb = dentry->d_sb; ++ dinfo = au_di_alloc(sb, AuLsc_DI_CHILD); ++ if (dinfo) { ++ atomic_set(&dinfo->di_generation, au_sigen(sb)); ++ /* smp_mb(); */ /* atomic_set */ ++ dentry->d_fsdata = dinfo; ++ } else ++ err = -ENOMEM; ++ ++ return err; ++} ++ ++void au_di_fin(struct dentry *dentry) ++{ ++ struct au_dinfo *dinfo; ++ ++ dinfo = au_di(dentry); ++ AuRwDestroy(&dinfo->di_rwsem); ++ au_di_free(dinfo); ++} ++ ++int au_di_realloc(struct au_dinfo *dinfo, int nbr, int may_shrink) ++{ ++ int err, sz; ++ struct au_hdentry *hdp; ++ ++ AuRwMustWriteLock(&dinfo->di_rwsem); ++ ++ err = -ENOMEM; ++ sz = sizeof(*hdp) * (dinfo->di_bbot + 1); ++ if (!sz) ++ sz = sizeof(*hdp); ++ hdp = au_kzrealloc(dinfo->di_hdentry, sz, sizeof(*hdp) * nbr, GFP_NOFS, ++ may_shrink); ++ if (hdp) { ++ dinfo->di_hdentry = hdp; ++ err = 0; ++ } ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static void do_ii_write_lock(struct inode *inode, unsigned int lsc) ++{ ++ switch (lsc) { ++ case AuLsc_DI_CHILD: ++ ii_write_lock_child(inode); ++ break; ++ case AuLsc_DI_CHILD2: ++ ii_write_lock_child2(inode); ++ break; ++ case AuLsc_DI_CHILD3: ++ ii_write_lock_child3(inode); ++ break; ++ case AuLsc_DI_PARENT: ++ ii_write_lock_parent(inode); ++ break; ++ case AuLsc_DI_PARENT2: ++ ii_write_lock_parent2(inode); ++ break; ++ case AuLsc_DI_PARENT3: ++ ii_write_lock_parent3(inode); ++ break; ++ default: ++ BUG(); ++ } ++} ++ ++static void do_ii_read_lock(struct inode *inode, unsigned int lsc) ++{ ++ switch (lsc) { ++ case AuLsc_DI_CHILD: ++ ii_read_lock_child(inode); ++ break; ++ case AuLsc_DI_CHILD2: ++ ii_read_lock_child2(inode); ++ break; ++ case AuLsc_DI_CHILD3: ++ ii_read_lock_child3(inode); ++ break; ++ case AuLsc_DI_PARENT: ++ ii_read_lock_parent(inode); ++ break; ++ case AuLsc_DI_PARENT2: ++ ii_read_lock_parent2(inode); ++ break; ++ case AuLsc_DI_PARENT3: ++ ii_read_lock_parent3(inode); ++ break; ++ default: ++ BUG(); ++ } ++} ++ ++void di_read_lock(struct dentry *d, int flags, unsigned int lsc) ++{ ++ struct inode *inode; ++ ++ au_rw_read_lock_nested(&au_di(d)->di_rwsem, lsc); ++ if (d_really_is_positive(d)) { ++ inode = d_inode(d); ++ if (au_ftest_lock(flags, IW)) ++ do_ii_write_lock(inode, lsc); ++ else if (au_ftest_lock(flags, IR)) ++ do_ii_read_lock(inode, lsc); ++ } ++} ++ ++void di_read_unlock(struct dentry *d, int flags) ++{ ++ struct inode *inode; ++ ++ if (d_really_is_positive(d)) { ++ inode = d_inode(d); ++ if (au_ftest_lock(flags, IW)) { ++ au_dbg_verify_dinode(d); ++ ii_write_unlock(inode); ++ } else if (au_ftest_lock(flags, IR)) { ++ au_dbg_verify_dinode(d); ++ ii_read_unlock(inode); ++ } ++ } ++ au_rw_read_unlock(&au_di(d)->di_rwsem); ++} ++ ++void di_downgrade_lock(struct dentry *d, int flags) ++{ ++ if (d_really_is_positive(d) && au_ftest_lock(flags, IR)) ++ ii_downgrade_lock(d_inode(d)); ++ au_rw_dgrade_lock(&au_di(d)->di_rwsem); ++} ++ ++void di_write_lock(struct dentry *d, unsigned int lsc) ++{ ++ au_rw_write_lock_nested(&au_di(d)->di_rwsem, lsc); ++ if (d_really_is_positive(d)) ++ do_ii_write_lock(d_inode(d), lsc); ++} ++ ++void di_write_unlock(struct dentry *d) ++{ ++ au_dbg_verify_dinode(d); ++ if (d_really_is_positive(d)) ++ ii_write_unlock(d_inode(d)); ++ au_rw_write_unlock(&au_di(d)->di_rwsem); ++} ++ ++void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir) ++{ ++ AuDebugOn(d1 == d2 ++ || d_inode(d1) == d_inode(d2) ++ || d1->d_sb != d2->d_sb); ++ ++ if ((isdir && au_test_subdir(d1, d2)) ++ || d1 < d2) { ++ di_write_lock_child(d1); ++ di_write_lock_child2(d2); ++ } else { ++ di_write_lock_child(d2); ++ di_write_lock_child2(d1); ++ } ++} ++ ++void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir) ++{ ++ AuDebugOn(d1 == d2 ++ || d_inode(d1) == d_inode(d2) ++ || d1->d_sb != d2->d_sb); ++ ++ if ((isdir && au_test_subdir(d1, d2)) ++ || d1 < d2) { ++ di_write_lock_parent(d1); ++ di_write_lock_parent2(d2); ++ } else { ++ di_write_lock_parent(d2); ++ di_write_lock_parent2(d1); ++ } ++} ++ ++void di_write_unlock2(struct dentry *d1, struct dentry *d2) ++{ ++ di_write_unlock(d1); ++ if (d_inode(d1) == d_inode(d2)) ++ au_rw_write_unlock(&au_di(d2)->di_rwsem); ++ else ++ di_write_unlock(d2); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex) ++{ ++ struct dentry *d; ++ ++ DiMustAnyLock(dentry); ++ ++ if (au_dbtop(dentry) < 0 || bindex < au_dbtop(dentry)) ++ return NULL; ++ AuDebugOn(bindex < 0); ++ d = au_hdentry(au_di(dentry), bindex)->hd_dentry; ++ AuDebugOn(d && au_dcount(d) <= 0); ++ return d; ++} ++ ++/* ++ * extended version of au_h_dptr(). ++ * returns a hashed and positive (or linkable) h_dentry in bindex, NULL, or ++ * error. ++ */ ++struct dentry *au_h_d_alias(struct dentry *dentry, aufs_bindex_t bindex) ++{ ++ struct dentry *h_dentry; ++ struct inode *inode, *h_inode; ++ ++ AuDebugOn(d_really_is_negative(dentry)); ++ ++ h_dentry = NULL; ++ if (au_dbtop(dentry) <= bindex ++ && bindex <= au_dbbot(dentry)) ++ h_dentry = au_h_dptr(dentry, bindex); ++ if (h_dentry && !au_d_linkable(h_dentry)) { ++ dget(h_dentry); ++ goto out; /* success */ ++ } ++ ++ inode = d_inode(dentry); ++ AuDebugOn(bindex < au_ibtop(inode)); ++ AuDebugOn(au_ibbot(inode) < bindex); ++ h_inode = au_h_iptr(inode, bindex); ++ h_dentry = d_find_alias(h_inode); ++ if (h_dentry) { ++ if (!IS_ERR(h_dentry)) { ++ if (!au_d_linkable(h_dentry)) ++ goto out; /* success */ ++ dput(h_dentry); ++ } else ++ goto out; ++ } ++ ++ if (au_opt_test(au_mntflags(dentry->d_sb), PLINK)) { ++ h_dentry = au_plink_lkup(inode, bindex); ++ AuDebugOn(!h_dentry); ++ if (!IS_ERR(h_dentry)) { ++ if (!au_d_hashed_positive(h_dentry)) ++ goto out; /* success */ ++ dput(h_dentry); ++ h_dentry = NULL; ++ } ++ } ++ ++out: ++ AuDbgDentry(h_dentry); ++ return h_dentry; ++} ++ ++aufs_bindex_t au_dbtail(struct dentry *dentry) ++{ ++ aufs_bindex_t bbot, bwh; ++ ++ bbot = au_dbbot(dentry); ++ if (0 <= bbot) { ++ bwh = au_dbwh(dentry); ++ if (!bwh) ++ return bwh; ++ if (0 < bwh && bwh < bbot) ++ return bwh - 1; ++ } ++ return bbot; ++} ++ ++aufs_bindex_t au_dbtaildir(struct dentry *dentry) ++{ ++ aufs_bindex_t bbot, bopq; ++ ++ bbot = au_dbtail(dentry); ++ if (0 <= bbot) { ++ bopq = au_dbdiropq(dentry); ++ if (0 <= bopq && bopq < bbot) ++ bbot = bopq; ++ } ++ return bbot; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex, ++ struct dentry *h_dentry) ++{ ++ struct au_dinfo *dinfo; ++ struct au_hdentry *hd; ++ struct au_branch *br; ++ ++ DiMustWriteLock(dentry); ++ ++ dinfo = au_di(dentry); ++ hd = au_hdentry(dinfo, bindex); ++ au_hdput(hd); ++ hd->hd_dentry = h_dentry; ++ if (h_dentry) { ++ br = au_sbr(dentry->d_sb, bindex); ++ hd->hd_id = br->br_id; ++ } ++} ++ ++int au_dbrange_test(struct dentry *dentry) ++{ ++ int err; ++ aufs_bindex_t btop, bbot; ++ ++ err = 0; ++ btop = au_dbtop(dentry); ++ bbot = au_dbbot(dentry); ++ if (btop >= 0) ++ AuDebugOn(bbot < 0 && btop > bbot); ++ else { ++ err = -EIO; ++ AuDebugOn(bbot >= 0); ++ } ++ ++ return err; ++} ++ ++int au_digen_test(struct dentry *dentry, unsigned int sigen) ++{ ++ int err; ++ ++ err = 0; ++ if (unlikely(au_digen(dentry) != sigen ++ || au_iigen_test(d_inode(dentry), sigen))) ++ err = -EIO; ++ ++ return err; ++} ++ ++void au_update_digen(struct dentry *dentry) ++{ ++ atomic_set(&au_di(dentry)->di_generation, au_sigen(dentry->d_sb)); ++ /* smp_mb(); */ /* atomic_set */ ++} ++ ++void au_update_dbrange(struct dentry *dentry, int do_put_zero) ++{ ++ struct au_dinfo *dinfo; ++ struct dentry *h_d; ++ struct au_hdentry *hdp; ++ aufs_bindex_t bindex, bbot; ++ ++ DiMustWriteLock(dentry); ++ ++ dinfo = au_di(dentry); ++ if (!dinfo || dinfo->di_btop < 0) ++ return; ++ ++ if (do_put_zero) { ++ bbot = dinfo->di_bbot; ++ bindex = dinfo->di_btop; ++ hdp = au_hdentry(dinfo, bindex); ++ for (; bindex <= bbot; bindex++, hdp++) { ++ h_d = hdp->hd_dentry; ++ if (h_d && d_is_negative(h_d)) ++ au_set_h_dptr(dentry, bindex, NULL); ++ } ++ } ++ ++ dinfo->di_btop = 0; ++ hdp = au_hdentry(dinfo, dinfo->di_btop); ++ for (; dinfo->di_btop <= dinfo->di_bbot; dinfo->di_btop++, hdp++) ++ if (hdp->hd_dentry) ++ break; ++ if (dinfo->di_btop > dinfo->di_bbot) { ++ dinfo->di_btop = -1; ++ dinfo->di_bbot = -1; ++ return; ++ } ++ ++ hdp = au_hdentry(dinfo, dinfo->di_bbot); ++ for (; dinfo->di_bbot >= 0; dinfo->di_bbot--, hdp--) ++ if (hdp->hd_dentry) ++ break; ++ AuDebugOn(dinfo->di_btop > dinfo->di_bbot || dinfo->di_bbot < 0); ++} ++ ++void au_update_dbtop(struct dentry *dentry) ++{ ++ aufs_bindex_t bindex, bbot; ++ struct dentry *h_dentry; ++ ++ bbot = au_dbbot(dentry); ++ for (bindex = au_dbtop(dentry); bindex <= bbot; bindex++) { ++ h_dentry = au_h_dptr(dentry, bindex); ++ if (!h_dentry) ++ continue; ++ if (d_is_positive(h_dentry)) { ++ au_set_dbtop(dentry, bindex); ++ return; ++ } ++ au_set_h_dptr(dentry, bindex, NULL); ++ } ++} ++ ++void au_update_dbbot(struct dentry *dentry) ++{ ++ aufs_bindex_t bindex, btop; ++ struct dentry *h_dentry; ++ ++ btop = au_dbtop(dentry); ++ for (bindex = au_dbbot(dentry); bindex >= btop; bindex--) { ++ h_dentry = au_h_dptr(dentry, bindex); ++ if (!h_dentry) ++ continue; ++ if (d_is_positive(h_dentry)) { ++ au_set_dbbot(dentry, bindex); ++ return; ++ } ++ au_set_h_dptr(dentry, bindex, NULL); ++ } ++} ++ ++int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry) ++{ ++ aufs_bindex_t bindex, bbot; ++ ++ bbot = au_dbbot(dentry); ++ for (bindex = au_dbtop(dentry); bindex <= bbot; bindex++) ++ if (au_h_dptr(dentry, bindex) == h_dentry) ++ return bindex; ++ return -1; ++} +diff -Nurp linux-5.4/fs/aufs/dir.c linux-5.4-aufs/fs/aufs/dir.c +--- linux-5.4/fs/aufs/dir.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/dir.c 2019-11-28 01:25:59.064925618 +0200 +@@ -0,0 +1,750 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * directory operations ++ */ ++ ++#include ++#include ++#include "aufs.h" ++ ++void au_add_nlink(struct inode *dir, struct inode *h_dir) ++{ ++ unsigned int nlink; ++ ++ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode)); ++ ++ nlink = dir->i_nlink; ++ nlink += h_dir->i_nlink - 2; ++ if (h_dir->i_nlink < 2) ++ nlink += 2; ++ smp_mb(); /* for i_nlink */ ++ /* 0 can happen in revaliding */ ++ set_nlink(dir, nlink); ++} ++ ++void au_sub_nlink(struct inode *dir, struct inode *h_dir) ++{ ++ unsigned int nlink; ++ ++ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode)); ++ ++ nlink = dir->i_nlink; ++ nlink -= h_dir->i_nlink - 2; ++ if (h_dir->i_nlink < 2) ++ nlink -= 2; ++ smp_mb(); /* for i_nlink */ ++ /* nlink == 0 means the branch-fs is broken */ ++ set_nlink(dir, nlink); ++} ++ ++loff_t au_dir_size(struct file *file, struct dentry *dentry) ++{ ++ loff_t sz; ++ aufs_bindex_t bindex, bbot; ++ struct file *h_file; ++ struct dentry *h_dentry; ++ ++ sz = 0; ++ if (file) { ++ AuDebugOn(!d_is_dir(file->f_path.dentry)); ++ ++ bbot = au_fbbot_dir(file); ++ for (bindex = au_fbtop(file); ++ bindex <= bbot && sz < KMALLOC_MAX_SIZE; ++ bindex++) { ++ h_file = au_hf_dir(file, bindex); ++ if (h_file && file_inode(h_file)) ++ sz += vfsub_f_size_read(h_file); ++ } ++ } else { ++ AuDebugOn(!dentry); ++ AuDebugOn(!d_is_dir(dentry)); ++ ++ bbot = au_dbtaildir(dentry); ++ for (bindex = au_dbtop(dentry); ++ bindex <= bbot && sz < KMALLOC_MAX_SIZE; ++ bindex++) { ++ h_dentry = au_h_dptr(dentry, bindex); ++ if (h_dentry && d_is_positive(h_dentry)) ++ sz += i_size_read(d_inode(h_dentry)); ++ } ++ } ++ if (sz < KMALLOC_MAX_SIZE) ++ sz = roundup_pow_of_two(sz); ++ if (sz > KMALLOC_MAX_SIZE) ++ sz = KMALLOC_MAX_SIZE; ++ else if (sz < NAME_MAX) { ++ BUILD_BUG_ON(AUFS_RDBLK_DEF < NAME_MAX); ++ sz = AUFS_RDBLK_DEF; ++ } ++ return sz; ++} ++ ++struct au_dir_ts_arg { ++ struct dentry *dentry; ++ aufs_bindex_t brid; ++}; ++ ++static void au_do_dir_ts(void *arg) ++{ ++ struct au_dir_ts_arg *a = arg; ++ struct au_dtime dt; ++ struct path h_path; ++ struct inode *dir, *h_dir; ++ struct super_block *sb; ++ struct au_branch *br; ++ struct au_hinode *hdir; ++ int err; ++ aufs_bindex_t btop, bindex; ++ ++ sb = a->dentry->d_sb; ++ if (d_really_is_negative(a->dentry)) ++ goto out; ++ /* no dir->i_mutex lock */ ++ aufs_read_lock(a->dentry, AuLock_DW); /* noflush */ ++ ++ dir = d_inode(a->dentry); ++ btop = au_ibtop(dir); ++ bindex = au_br_index(sb, a->brid); ++ if (bindex < btop) ++ goto out_unlock; ++ ++ br = au_sbr(sb, bindex); ++ h_path.dentry = au_h_dptr(a->dentry, bindex); ++ if (!h_path.dentry) ++ goto out_unlock; ++ h_path.mnt = au_br_mnt(br); ++ au_dtime_store(&dt, a->dentry, &h_path); ++ ++ br = au_sbr(sb, btop); ++ if (!au_br_writable(br->br_perm)) ++ goto out_unlock; ++ h_path.dentry = au_h_dptr(a->dentry, btop); ++ h_path.mnt = au_br_mnt(br); ++ err = vfsub_mnt_want_write(h_path.mnt); ++ if (err) ++ goto out_unlock; ++ hdir = au_hi(dir, btop); ++ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT); ++ h_dir = au_h_iptr(dir, btop); ++ if (h_dir->i_nlink ++ && timespec64_compare(&h_dir->i_mtime, &dt.dt_mtime) < 0) { ++ dt.dt_h_path = h_path; ++ au_dtime_revert(&dt); ++ } ++ au_hn_inode_unlock(hdir); ++ vfsub_mnt_drop_write(h_path.mnt); ++ au_cpup_attr_timesizes(dir); ++ ++out_unlock: ++ aufs_read_unlock(a->dentry, AuLock_DW); ++out: ++ dput(a->dentry); ++ au_nwt_done(&au_sbi(sb)->si_nowait); ++ au_kfree_try_rcu(arg); ++} ++ ++void au_dir_ts(struct inode *dir, aufs_bindex_t bindex) ++{ ++ int perm, wkq_err; ++ aufs_bindex_t btop; ++ struct au_dir_ts_arg *arg; ++ struct dentry *dentry; ++ struct super_block *sb; ++ ++ IMustLock(dir); ++ ++ dentry = d_find_any_alias(dir); ++ AuDebugOn(!dentry); ++ sb = dentry->d_sb; ++ btop = au_ibtop(dir); ++ if (btop == bindex) { ++ au_cpup_attr_timesizes(dir); ++ goto out; ++ } ++ ++ perm = au_sbr_perm(sb, btop); ++ if (!au_br_writable(perm)) ++ goto out; ++ ++ arg = kmalloc(sizeof(*arg), GFP_NOFS); ++ if (!arg) ++ goto out; ++ ++ arg->dentry = dget(dentry); /* will be dput-ted by au_do_dir_ts() */ ++ arg->brid = au_sbr_id(sb, bindex); ++ wkq_err = au_wkq_nowait(au_do_dir_ts, arg, sb, /*flags*/0); ++ if (unlikely(wkq_err)) { ++ pr_err("wkq %d\n", wkq_err); ++ dput(dentry); ++ au_kfree_try_rcu(arg); ++ } ++ ++out: ++ dput(dentry); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int reopen_dir(struct file *file) ++{ ++ int err; ++ unsigned int flags; ++ aufs_bindex_t bindex, btail, btop; ++ struct dentry *dentry, *h_dentry; ++ struct file *h_file; ++ ++ /* open all lower dirs */ ++ dentry = file->f_path.dentry; ++ btop = au_dbtop(dentry); ++ for (bindex = au_fbtop(file); bindex < btop; bindex++) ++ au_set_h_fptr(file, bindex, NULL); ++ au_set_fbtop(file, btop); ++ ++ btail = au_dbtaildir(dentry); ++ for (bindex = au_fbbot_dir(file); btail < bindex; bindex--) ++ au_set_h_fptr(file, bindex, NULL); ++ au_set_fbbot_dir(file, btail); ++ ++ flags = vfsub_file_flags(file); ++ for (bindex = btop; bindex <= btail; bindex++) { ++ h_dentry = au_h_dptr(dentry, bindex); ++ if (!h_dentry) ++ continue; ++ h_file = au_hf_dir(file, bindex); ++ if (h_file) ++ continue; ++ ++ h_file = au_h_open(dentry, bindex, flags, file, /*force_wr*/0); ++ err = PTR_ERR(h_file); ++ if (IS_ERR(h_file)) ++ goto out; /* close all? */ ++ au_set_h_fptr(file, bindex, h_file); ++ } ++ au_update_figen(file); ++ /* todo: necessary? */ ++ /* file->f_ra = h_file->f_ra; */ ++ err = 0; ++ ++out: ++ return err; ++} ++ ++static int do_open_dir(struct file *file, int flags, struct file *h_file) ++{ ++ int err; ++ aufs_bindex_t bindex, btail; ++ struct dentry *dentry, *h_dentry; ++ struct vfsmount *mnt; ++ ++ FiMustWriteLock(file); ++ AuDebugOn(h_file); ++ ++ err = 0; ++ mnt = file->f_path.mnt; ++ dentry = file->f_path.dentry; ++ file->f_version = inode_query_iversion(d_inode(dentry)); ++ bindex = au_dbtop(dentry); ++ au_set_fbtop(file, bindex); ++ btail = au_dbtaildir(dentry); ++ au_set_fbbot_dir(file, btail); ++ for (; !err && bindex <= btail; bindex++) { ++ h_dentry = au_h_dptr(dentry, bindex); ++ if (!h_dentry) ++ continue; ++ ++ err = vfsub_test_mntns(mnt, h_dentry->d_sb); ++ if (unlikely(err)) ++ break; ++ h_file = au_h_open(dentry, bindex, flags, file, /*force_wr*/0); ++ if (IS_ERR(h_file)) { ++ err = PTR_ERR(h_file); ++ break; ++ } ++ au_set_h_fptr(file, bindex, h_file); ++ } ++ au_update_figen(file); ++ /* todo: necessary? */ ++ /* file->f_ra = h_file->f_ra; */ ++ if (!err) ++ return 0; /* success */ ++ ++ /* close all */ ++ for (bindex = au_fbtop(file); bindex <= btail; bindex++) ++ au_set_h_fptr(file, bindex, NULL); ++ au_set_fbtop(file, -1); ++ au_set_fbbot_dir(file, -1); ++ ++ return err; ++} ++ ++static int aufs_open_dir(struct inode *inode __maybe_unused, ++ struct file *file) ++{ ++ int err; ++ struct super_block *sb; ++ struct au_fidir *fidir; ++ ++ err = -ENOMEM; ++ sb = file->f_path.dentry->d_sb; ++ si_read_lock(sb, AuLock_FLUSH); ++ fidir = au_fidir_alloc(sb); ++ if (fidir) { ++ struct au_do_open_args args = { ++ .open = do_open_dir, ++ .fidir = fidir ++ }; ++ err = au_do_open(file, &args); ++ if (unlikely(err)) ++ au_kfree_rcu(fidir); ++ } ++ si_read_unlock(sb); ++ return err; ++} ++ ++static int aufs_release_dir(struct inode *inode __maybe_unused, ++ struct file *file) ++{ ++ struct au_vdir *vdir_cache; ++ struct au_finfo *finfo; ++ struct au_fidir *fidir; ++ struct au_hfile *hf; ++ aufs_bindex_t bindex, bbot; ++ ++ finfo = au_fi(file); ++ fidir = finfo->fi_hdir; ++ if (fidir) { ++ au_hbl_del(&finfo->fi_hlist, ++ &au_sbi(file->f_path.dentry->d_sb)->si_files); ++ vdir_cache = fidir->fd_vdir_cache; /* lock-free */ ++ if (vdir_cache) ++ au_vdir_free(vdir_cache); ++ ++ bindex = finfo->fi_btop; ++ if (bindex >= 0) { ++ hf = fidir->fd_hfile + bindex; ++ /* ++ * calls fput() instead of filp_close(), ++ * since no dnotify or lock for the lower file. ++ */ ++ bbot = fidir->fd_bbot; ++ for (; bindex <= bbot; bindex++, hf++) ++ if (hf->hf_file) ++ au_hfput(hf, /*execed*/0); ++ } ++ au_kfree_rcu(fidir); ++ finfo->fi_hdir = NULL; ++ } ++ au_finfo_fin(file); ++ return 0; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int au_do_flush_dir(struct file *file, fl_owner_t id) ++{ ++ int err; ++ aufs_bindex_t bindex, bbot; ++ struct file *h_file; ++ ++ err = 0; ++ bbot = au_fbbot_dir(file); ++ for (bindex = au_fbtop(file); !err && bindex <= bbot; bindex++) { ++ h_file = au_hf_dir(file, bindex); ++ if (h_file) ++ err = vfsub_flush(h_file, id); ++ } ++ return err; ++} ++ ++static int aufs_flush_dir(struct file *file, fl_owner_t id) ++{ ++ return au_do_flush(file, id, au_do_flush_dir); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int au_do_fsync_dir_no_file(struct dentry *dentry, int datasync) ++{ ++ int err; ++ aufs_bindex_t bbot, bindex; ++ struct inode *inode; ++ struct super_block *sb; ++ ++ err = 0; ++ sb = dentry->d_sb; ++ inode = d_inode(dentry); ++ IMustLock(inode); ++ bbot = au_dbbot(dentry); ++ for (bindex = au_dbtop(dentry); !err && bindex <= bbot; bindex++) { ++ struct path h_path; ++ ++ if (au_test_ro(sb, bindex, inode)) ++ continue; ++ h_path.dentry = au_h_dptr(dentry, bindex); ++ if (!h_path.dentry) ++ continue; ++ ++ h_path.mnt = au_sbr_mnt(sb, bindex); ++ err = vfsub_fsync(NULL, &h_path, datasync); ++ } ++ ++ return err; ++} ++ ++static int au_do_fsync_dir(struct file *file, int datasync) ++{ ++ int err; ++ aufs_bindex_t bbot, bindex; ++ struct file *h_file; ++ struct super_block *sb; ++ struct inode *inode; ++ ++ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1, /*fi_lsc*/0); ++ if (unlikely(err)) ++ goto out; ++ ++ inode = file_inode(file); ++ sb = inode->i_sb; ++ bbot = au_fbbot_dir(file); ++ for (bindex = au_fbtop(file); !err && bindex <= bbot; bindex++) { ++ h_file = au_hf_dir(file, bindex); ++ if (!h_file || au_test_ro(sb, bindex, inode)) ++ continue; ++ ++ err = vfsub_fsync(h_file, &h_file->f_path, datasync); ++ } ++ ++out: ++ return err; ++} ++ ++/* ++ * @file may be NULL ++ */ ++static int aufs_fsync_dir(struct file *file, loff_t start, loff_t end, ++ int datasync) ++{ ++ int err; ++ struct dentry *dentry; ++ struct inode *inode; ++ struct super_block *sb; ++ ++ err = 0; ++ dentry = file->f_path.dentry; ++ inode = d_inode(dentry); ++ inode_lock(inode); ++ sb = dentry->d_sb; ++ si_noflush_read_lock(sb); ++ if (file) ++ err = au_do_fsync_dir(file, datasync); ++ else { ++ di_write_lock_child(dentry); ++ err = au_do_fsync_dir_no_file(dentry, datasync); ++ } ++ au_cpup_attr_timesizes(inode); ++ di_write_unlock(dentry); ++ if (file) ++ fi_write_unlock(file); ++ ++ si_read_unlock(sb); ++ inode_unlock(inode); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int aufs_iterate_shared(struct file *file, struct dir_context *ctx) ++{ ++ int err; ++ struct dentry *dentry; ++ struct inode *inode, *h_inode; ++ struct super_block *sb; ++ ++ AuDbg("%pD, ctx{%ps, %llu}\n", file, ctx->actor, ctx->pos); ++ ++ dentry = file->f_path.dentry; ++ inode = d_inode(dentry); ++ IMustLock(inode); ++ ++ sb = dentry->d_sb; ++ si_read_lock(sb, AuLock_FLUSH); ++ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1, /*fi_lsc*/0); ++ if (unlikely(err)) ++ goto out; ++ err = au_alive_dir(dentry); ++ if (!err) ++ err = au_vdir_init(file); ++ di_downgrade_lock(dentry, AuLock_IR); ++ if (unlikely(err)) ++ goto out_unlock; ++ ++ h_inode = au_h_iptr(inode, au_ibtop(inode)); ++ if (!au_test_nfsd()) { ++ err = au_vdir_fill_de(file, ctx); ++ fsstack_copy_attr_atime(inode, h_inode); ++ } else { ++ /* ++ * nfsd filldir may call lookup_one_len(), vfs_getattr(), ++ * encode_fh() and others. ++ */ ++ atomic_inc(&h_inode->i_count); ++ di_read_unlock(dentry, AuLock_IR); ++ si_read_unlock(sb); ++ err = au_vdir_fill_de(file, ctx); ++ fsstack_copy_attr_atime(inode, h_inode); ++ fi_write_unlock(file); ++ iput(h_inode); ++ ++ AuTraceErr(err); ++ return err; ++ } ++ ++out_unlock: ++ di_read_unlock(dentry, AuLock_IR); ++ fi_write_unlock(file); ++out: ++ si_read_unlock(sb); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++#define AuTestEmpty_WHONLY 1 ++#define AuTestEmpty_CALLED (1 << 1) ++#define AuTestEmpty_SHWH (1 << 2) ++#define au_ftest_testempty(flags, name) ((flags) & AuTestEmpty_##name) ++#define au_fset_testempty(flags, name) \ ++ do { (flags) |= AuTestEmpty_##name; } while (0) ++#define au_fclr_testempty(flags, name) \ ++ do { (flags) &= ~AuTestEmpty_##name; } while (0) ++ ++#ifndef CONFIG_AUFS_SHWH ++#undef AuTestEmpty_SHWH ++#define AuTestEmpty_SHWH 0 ++#endif ++ ++struct test_empty_arg { ++ struct dir_context ctx; ++ struct au_nhash *whlist; ++ unsigned int flags; ++ int err; ++ aufs_bindex_t bindex; ++}; ++ ++static int test_empty_cb(struct dir_context *ctx, const char *__name, ++ int namelen, loff_t offset __maybe_unused, u64 ino, ++ unsigned int d_type) ++{ ++ struct test_empty_arg *arg = container_of(ctx, struct test_empty_arg, ++ ctx); ++ char *name = (void *)__name; ++ ++ arg->err = 0; ++ au_fset_testempty(arg->flags, CALLED); ++ /* smp_mb(); */ ++ if (name[0] == '.' ++ && (namelen == 1 || (name[1] == '.' && namelen == 2))) ++ goto out; /* success */ ++ ++ if (namelen <= AUFS_WH_PFX_LEN ++ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) { ++ if (au_ftest_testempty(arg->flags, WHONLY) ++ && !au_nhash_test_known_wh(arg->whlist, name, namelen)) ++ arg->err = -ENOTEMPTY; ++ goto out; ++ } ++ ++ name += AUFS_WH_PFX_LEN; ++ namelen -= AUFS_WH_PFX_LEN; ++ if (!au_nhash_test_known_wh(arg->whlist, name, namelen)) ++ arg->err = au_nhash_append_wh ++ (arg->whlist, name, namelen, ino, d_type, arg->bindex, ++ au_ftest_testempty(arg->flags, SHWH)); ++ ++out: ++ /* smp_mb(); */ ++ AuTraceErr(arg->err); ++ return arg->err; ++} ++ ++static int do_test_empty(struct dentry *dentry, struct test_empty_arg *arg) ++{ ++ int err; ++ struct file *h_file; ++ struct au_branch *br; ++ ++ h_file = au_h_open(dentry, arg->bindex, ++ O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_LARGEFILE, ++ /*file*/NULL, /*force_wr*/0); ++ err = PTR_ERR(h_file); ++ if (IS_ERR(h_file)) ++ goto out; ++ ++ err = 0; ++ if (!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE) ++ && !file_inode(h_file)->i_nlink) ++ goto out_put; ++ ++ do { ++ arg->err = 0; ++ au_fclr_testempty(arg->flags, CALLED); ++ /* smp_mb(); */ ++ err = vfsub_iterate_dir(h_file, &arg->ctx); ++ if (err >= 0) ++ err = arg->err; ++ } while (!err && au_ftest_testempty(arg->flags, CALLED)); ++ ++out_put: ++ fput(h_file); ++ br = au_sbr(dentry->d_sb, arg->bindex); ++ au_lcnt_dec(&br->br_nfiles); ++out: ++ return err; ++} ++ ++struct do_test_empty_args { ++ int *errp; ++ struct dentry *dentry; ++ struct test_empty_arg *arg; ++}; ++ ++static void call_do_test_empty(void *args) ++{ ++ struct do_test_empty_args *a = args; ++ *a->errp = do_test_empty(a->dentry, a->arg); ++} ++ ++static int sio_test_empty(struct dentry *dentry, struct test_empty_arg *arg) ++{ ++ int err, wkq_err; ++ struct dentry *h_dentry; ++ struct inode *h_inode; ++ ++ h_dentry = au_h_dptr(dentry, arg->bindex); ++ h_inode = d_inode(h_dentry); ++ /* todo: i_mode changes anytime? */ ++ inode_lock_shared_nested(h_inode, AuLsc_I_CHILD); ++ err = au_test_h_perm_sio(h_inode, MAY_EXEC | MAY_READ); ++ inode_unlock_shared(h_inode); ++ if (!err) ++ err = do_test_empty(dentry, arg); ++ else { ++ struct do_test_empty_args args = { ++ .errp = &err, ++ .dentry = dentry, ++ .arg = arg ++ }; ++ unsigned int flags = arg->flags; ++ ++ wkq_err = au_wkq_wait(call_do_test_empty, &args); ++ if (unlikely(wkq_err)) ++ err = wkq_err; ++ arg->flags = flags; ++ } ++ ++ return err; ++} ++ ++int au_test_empty_lower(struct dentry *dentry) ++{ ++ int err; ++ unsigned int rdhash; ++ aufs_bindex_t bindex, btop, btail; ++ struct au_nhash whlist; ++ struct test_empty_arg arg = { ++ .ctx = { ++ .actor = test_empty_cb ++ } ++ }; ++ int (*test_empty)(struct dentry *dentry, struct test_empty_arg *arg); ++ ++ SiMustAnyLock(dentry->d_sb); ++ ++ rdhash = au_sbi(dentry->d_sb)->si_rdhash; ++ if (!rdhash) ++ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, dentry)); ++ err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS); ++ if (unlikely(err)) ++ goto out; ++ ++ arg.flags = 0; ++ arg.whlist = &whlist; ++ btop = au_dbtop(dentry); ++ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH)) ++ au_fset_testempty(arg.flags, SHWH); ++ test_empty = do_test_empty; ++ if (au_opt_test(au_mntflags(dentry->d_sb), DIRPERM1)) ++ test_empty = sio_test_empty; ++ arg.bindex = btop; ++ err = test_empty(dentry, &arg); ++ if (unlikely(err)) ++ goto out_whlist; ++ ++ au_fset_testempty(arg.flags, WHONLY); ++ btail = au_dbtaildir(dentry); ++ for (bindex = btop + 1; !err && bindex <= btail; bindex++) { ++ struct dentry *h_dentry; ++ ++ h_dentry = au_h_dptr(dentry, bindex); ++ if (h_dentry && d_is_positive(h_dentry)) { ++ arg.bindex = bindex; ++ err = test_empty(dentry, &arg); ++ } ++ } ++ ++out_whlist: ++ au_nhash_wh_free(&whlist); ++out: ++ return err; ++} ++ ++int au_test_empty(struct dentry *dentry, struct au_nhash *whlist) ++{ ++ int err; ++ struct test_empty_arg arg = { ++ .ctx = { ++ .actor = test_empty_cb ++ } ++ }; ++ aufs_bindex_t bindex, btail; ++ ++ err = 0; ++ arg.whlist = whlist; ++ arg.flags = AuTestEmpty_WHONLY; ++ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH)) ++ au_fset_testempty(arg.flags, SHWH); ++ btail = au_dbtaildir(dentry); ++ for (bindex = au_dbtop(dentry); !err && bindex <= btail; bindex++) { ++ struct dentry *h_dentry; ++ ++ h_dentry = au_h_dptr(dentry, bindex); ++ if (h_dentry && d_is_positive(h_dentry)) { ++ arg.bindex = bindex; ++ err = sio_test_empty(dentry, &arg); ++ } ++ } ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++const struct file_operations aufs_dir_fop = { ++ .owner = THIS_MODULE, ++ .llseek = default_llseek, ++ .read = generic_read_dir, ++ .iterate_shared = aufs_iterate_shared, ++ .unlocked_ioctl = aufs_ioctl_dir, ++#ifdef CONFIG_COMPAT ++ .compat_ioctl = aufs_compat_ioctl_dir, ++#endif ++ .open = aufs_open_dir, ++ .release = aufs_release_dir, ++ .flush = aufs_flush_dir, ++ .fsync = aufs_fsync_dir ++}; +diff -Nurp linux-5.4/fs/aufs/dir.h linux-5.4-aufs/fs/aufs/dir.h +--- linux-5.4/fs/aufs/dir.h 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/dir.h 2019-11-28 01:25:59.064925618 +0200 +@@ -0,0 +1,121 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * directory operations ++ */ ++ ++#ifndef __AUFS_DIR_H__ ++#define __AUFS_DIR_H__ ++ ++#ifdef __KERNEL__ ++ ++#include ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* need to be faster and smaller */ ++ ++struct au_nhash { ++ unsigned int nh_num; ++ struct hlist_head *nh_head; ++}; ++ ++struct au_vdir_destr { ++ unsigned char len; ++ unsigned char name[0]; ++} __packed; ++ ++struct au_vdir_dehstr { ++ struct hlist_node hash; ++ struct au_vdir_destr *str; ++ struct rcu_head rcu; ++} ____cacheline_aligned_in_smp; ++ ++struct au_vdir_de { ++ ino_t de_ino; ++ unsigned char de_type; ++ /* caution: packed */ ++ struct au_vdir_destr de_str; ++} __packed; ++ ++struct au_vdir_wh { ++ struct hlist_node wh_hash; ++#ifdef CONFIG_AUFS_SHWH ++ ino_t wh_ino; ++ aufs_bindex_t wh_bindex; ++ unsigned char wh_type; ++#else ++ aufs_bindex_t wh_bindex; ++#endif ++ /* caution: packed */ ++ struct au_vdir_destr wh_str; ++} __packed; ++ ++union au_vdir_deblk_p { ++ unsigned char *deblk; ++ struct au_vdir_de *de; ++}; ++ ++struct au_vdir { ++ unsigned char **vd_deblk; ++ unsigned long vd_nblk; ++ struct { ++ unsigned long ul; ++ union au_vdir_deblk_p p; ++ } vd_last; ++ ++ u64 vd_version; ++ unsigned int vd_deblk_sz; ++ unsigned long vd_jiffy; ++ struct rcu_head rcu; ++} ____cacheline_aligned_in_smp; ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* dir.c */ ++extern const struct file_operations aufs_dir_fop; ++void au_add_nlink(struct inode *dir, struct inode *h_dir); ++void au_sub_nlink(struct inode *dir, struct inode *h_dir); ++loff_t au_dir_size(struct file *file, struct dentry *dentry); ++void au_dir_ts(struct inode *dir, aufs_bindex_t bsrc); ++int au_test_empty_lower(struct dentry *dentry); ++int au_test_empty(struct dentry *dentry, struct au_nhash *whlist); ++ ++/* vdir.c */ ++unsigned int au_rdhash_est(loff_t sz); ++int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp); ++void au_nhash_wh_free(struct au_nhash *whlist); ++int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt, ++ int limit); ++int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen); ++int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino, ++ unsigned int d_type, aufs_bindex_t bindex, ++ unsigned char shwh); ++void au_vdir_free(struct au_vdir *vdir); ++int au_vdir_init(struct file *file); ++int au_vdir_fill_de(struct file *file, struct dir_context *ctx); ++ ++/* ioctl.c */ ++long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg); ++ ++#ifdef CONFIG_AUFS_RDU ++/* rdu.c */ ++long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg); ++#ifdef CONFIG_COMPAT ++long au_rdu_compat_ioctl(struct file *file, unsigned int cmd, ++ unsigned long arg); ++#endif ++#else ++AuStub(long, au_rdu_ioctl, return -EINVAL, struct file *file, ++ unsigned int cmd, unsigned long arg) ++#ifdef CONFIG_COMPAT ++AuStub(long, au_rdu_compat_ioctl, return -EINVAL, struct file *file, ++ unsigned int cmd, unsigned long arg) ++#endif ++#endif ++ ++#endif /* __KERNEL__ */ ++#endif /* __AUFS_DIR_H__ */ +diff -Nurp linux-5.4/fs/aufs/dirren.c linux-5.4-aufs/fs/aufs/dirren.c +--- linux-5.4/fs/aufs/dirren.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/dirren.c 2019-11-28 01:25:59.064925618 +0200 +@@ -0,0 +1,1303 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2017-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * special handling in renaming a directory ++ * in order to support looking-up the before-renamed name on the lower readonly ++ * branches ++ */ ++ ++#include ++#include "aufs.h" ++ ++static void au_dr_hino_del(struct au_dr_br *dr, struct au_dr_hino *ent) ++{ ++ int idx; ++ ++ idx = au_dr_ihash(ent->dr_h_ino); ++ au_hbl_del(&ent->dr_hnode, dr->dr_h_ino + idx); ++} ++ ++static int au_dr_hino_test_empty(struct au_dr_br *dr) ++{ ++ int ret, i; ++ struct hlist_bl_head *hbl; ++ ++ ret = 1; ++ for (i = 0; ret && i < AuDirren_NHASH; i++) { ++ hbl = dr->dr_h_ino + i; ++ hlist_bl_lock(hbl); ++ ret &= hlist_bl_empty(hbl); ++ hlist_bl_unlock(hbl); ++ } ++ ++ return ret; ++} ++ ++static struct au_dr_hino *au_dr_hino_find(struct au_dr_br *dr, ino_t ino) ++{ ++ struct au_dr_hino *found, *ent; ++ struct hlist_bl_head *hbl; ++ struct hlist_bl_node *pos; ++ int idx; ++ ++ found = NULL; ++ idx = au_dr_ihash(ino); ++ hbl = dr->dr_h_ino + idx; ++ hlist_bl_lock(hbl); ++ hlist_bl_for_each_entry(ent, pos, hbl, dr_hnode) ++ if (ent->dr_h_ino == ino) { ++ found = ent; ++ break; ++ } ++ hlist_bl_unlock(hbl); ++ ++ return found; ++} ++ ++int au_dr_hino_test_add(struct au_dr_br *dr, ino_t ino, ++ struct au_dr_hino *add_ent) ++{ ++ int found, idx; ++ struct hlist_bl_head *hbl; ++ struct hlist_bl_node *pos; ++ struct au_dr_hino *ent; ++ ++ found = 0; ++ idx = au_dr_ihash(ino); ++ hbl = dr->dr_h_ino + idx; ++#if 0 ++ { ++ struct hlist_bl_node *tmp; ++ ++ hlist_bl_for_each_entry_safe(ent, pos, tmp, hbl, dr_hnode) ++ AuDbg("hi%llu\n", (unsigned long long)ent->dr_h_ino); ++ } ++#endif ++ hlist_bl_lock(hbl); ++ hlist_bl_for_each_entry(ent, pos, hbl, dr_hnode) ++ if (ent->dr_h_ino == ino) { ++ found = 1; ++ break; ++ } ++ if (!found && add_ent) ++ hlist_bl_add_head(&add_ent->dr_hnode, hbl); ++ hlist_bl_unlock(hbl); ++ ++ if (!found && add_ent) ++ AuDbg("i%llu added\n", (unsigned long long)add_ent->dr_h_ino); ++ ++ return found; ++} ++ ++void au_dr_hino_free(struct au_dr_br *dr) ++{ ++ int i; ++ struct hlist_bl_head *hbl; ++ struct hlist_bl_node *pos, *tmp; ++ struct au_dr_hino *ent; ++ ++ /* SiMustWriteLock(sb); */ ++ ++ for (i = 0; i < AuDirren_NHASH; i++) { ++ hbl = dr->dr_h_ino + i; ++ /* no spinlock since sbinfo must be write-locked */ ++ hlist_bl_for_each_entry_safe(ent, pos, tmp, hbl, dr_hnode) ++ au_kfree_rcu(ent); ++ INIT_HLIST_BL_HEAD(hbl); ++ } ++} ++ ++/* returns the number of inodes or an error */ ++static int au_dr_hino_store(struct super_block *sb, struct au_branch *br, ++ struct file *hinofile) ++{ ++ int err, i; ++ ssize_t ssz; ++ loff_t pos, oldsize; ++ __be64 u64; ++ struct inode *hinoinode; ++ struct hlist_bl_head *hbl; ++ struct hlist_bl_node *n1, *n2; ++ struct au_dr_hino *ent; ++ ++ SiMustWriteLock(sb); ++ AuDebugOn(!au_br_writable(br->br_perm)); ++ ++ hinoinode = file_inode(hinofile); ++ oldsize = i_size_read(hinoinode); ++ ++ err = 0; ++ pos = 0; ++ hbl = br->br_dirren.dr_h_ino; ++ for (i = 0; !err && i < AuDirren_NHASH; i++, hbl++) { ++ /* no bit-lock since sbinfo must be write-locked */ ++ hlist_bl_for_each_entry_safe(ent, n1, n2, hbl, dr_hnode) { ++ AuDbg("hi%llu, %pD2\n", ++ (unsigned long long)ent->dr_h_ino, hinofile); ++ u64 = cpu_to_be64(ent->dr_h_ino); ++ ssz = vfsub_write_k(hinofile, &u64, sizeof(u64), &pos); ++ if (ssz == sizeof(u64)) ++ continue; ++ ++ /* write error */ ++ pr_err("ssz %zd, %pD2\n", ssz, hinofile); ++ err = -ENOSPC; ++ if (ssz < 0) ++ err = ssz; ++ break; ++ } ++ } ++ /* regardless the error */ ++ if (pos < oldsize) { ++ err = vfsub_trunc(&hinofile->f_path, pos, /*attr*/0, hinofile); ++ AuTraceErr(err); ++ } ++ ++ AuTraceErr(err); ++ return err; ++} ++ ++static int au_dr_hino_load(struct au_dr_br *dr, struct file *hinofile) ++{ ++ int err, hidx; ++ ssize_t ssz; ++ size_t sz, n; ++ loff_t pos; ++ uint64_t u64; ++ struct au_dr_hino *ent; ++ struct inode *hinoinode; ++ struct hlist_bl_head *hbl; ++ ++ err = 0; ++ pos = 0; ++ hbl = dr->dr_h_ino; ++ hinoinode = file_inode(hinofile); ++ sz = i_size_read(hinoinode); ++ AuDebugOn(sz % sizeof(u64)); ++ n = sz / sizeof(u64); ++ while (n--) { ++ ssz = vfsub_read_k(hinofile, &u64, sizeof(u64), &pos); ++ if (unlikely(ssz != sizeof(u64))) { ++ pr_err("ssz %zd, %pD2\n", ssz, hinofile); ++ err = -EINVAL; ++ if (ssz < 0) ++ err = ssz; ++ goto out_free; ++ } ++ ++ ent = kmalloc(sizeof(*ent), GFP_NOFS); ++ if (!ent) { ++ err = -ENOMEM; ++ AuTraceErr(err); ++ goto out_free; ++ } ++ ent->dr_h_ino = be64_to_cpu((__force __be64)u64); ++ AuDbg("hi%llu, %pD2\n", ++ (unsigned long long)ent->dr_h_ino, hinofile); ++ hidx = au_dr_ihash(ent->dr_h_ino); ++ au_hbl_add(&ent->dr_hnode, hbl + hidx); ++ } ++ goto out; /* success */ ++ ++out_free: ++ au_dr_hino_free(dr); ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++/* ++ * @bindex/@br is a switch to distinguish whether suspending hnotify or not. ++ * @path is a switch to distinguish load and store. ++ */ ++static int au_dr_hino(struct super_block *sb, aufs_bindex_t bindex, ++ struct au_branch *br, const struct path *path) ++{ ++ int err, flags; ++ unsigned char load, suspend; ++ struct file *hinofile; ++ struct au_hinode *hdir; ++ struct inode *dir, *delegated; ++ struct path hinopath; ++ struct qstr hinoname = QSTR_INIT(AUFS_WH_DR_BRHINO, ++ sizeof(AUFS_WH_DR_BRHINO) - 1); ++ ++ AuDebugOn(bindex < 0 && !br); ++ AuDebugOn(bindex >= 0 && br); ++ ++ err = -EINVAL; ++ suspend = !br; ++ if (suspend) ++ br = au_sbr(sb, bindex); ++ load = !!path; ++ if (!load) { ++ path = &br->br_path; ++ AuDebugOn(!au_br_writable(br->br_perm)); ++ if (unlikely(!au_br_writable(br->br_perm))) ++ goto out; ++ } ++ ++ hdir = NULL; ++ if (suspend) { ++ dir = d_inode(sb->s_root); ++ hdir = au_hinode(au_ii(dir), bindex); ++ dir = hdir->hi_inode; ++ au_hn_inode_lock_nested(hdir, AuLsc_I_CHILD); ++ } else { ++ dir = d_inode(path->dentry); ++ inode_lock_nested(dir, AuLsc_I_CHILD); ++ } ++ hinopath.dentry = vfsub_lkup_one(&hinoname, path->dentry); ++ err = PTR_ERR(hinopath.dentry); ++ if (IS_ERR(hinopath.dentry)) ++ goto out_unlock; ++ ++ err = 0; ++ flags = O_RDONLY; ++ if (load) { ++ if (d_is_negative(hinopath.dentry)) ++ goto out_dput; /* success */ ++ } else { ++ if (au_dr_hino_test_empty(&br->br_dirren)) { ++ if (d_is_positive(hinopath.dentry)) { ++ delegated = NULL; ++ err = vfsub_unlink(dir, &hinopath, &delegated, ++ /*force*/0); ++ AuTraceErr(err); ++ if (unlikely(err)) ++ pr_err("ignored err %d, %pd2\n", ++ err, hinopath.dentry); ++ if (unlikely(err == -EWOULDBLOCK)) ++ iput(delegated); ++ err = 0; ++ } ++ goto out_dput; ++ } else if (!d_is_positive(hinopath.dentry)) { ++ err = vfsub_create(dir, &hinopath, 0600, ++ /*want_excl*/false); ++ AuTraceErr(err); ++ if (unlikely(err)) ++ goto out_dput; ++ } ++ flags = O_WRONLY; ++ } ++ hinopath.mnt = path->mnt; ++ hinofile = vfsub_dentry_open(&hinopath, flags); ++ if (suspend) ++ au_hn_inode_unlock(hdir); ++ else ++ inode_unlock(dir); ++ dput(hinopath.dentry); ++ AuTraceErrPtr(hinofile); ++ if (IS_ERR(hinofile)) { ++ err = PTR_ERR(hinofile); ++ goto out; ++ } ++ ++ if (load) ++ err = au_dr_hino_load(&br->br_dirren, hinofile); ++ else ++ err = au_dr_hino_store(sb, br, hinofile); ++ fput(hinofile); ++ goto out; ++ ++out_dput: ++ dput(hinopath.dentry); ++out_unlock: ++ if (suspend) ++ au_hn_inode_unlock(hdir); ++ else ++ inode_unlock(dir); ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int au_dr_brid_init(struct au_dr_brid *brid, const struct path *path) ++{ ++ int err; ++ struct kstatfs kstfs; ++ dev_t dev; ++ struct dentry *dentry; ++ struct super_block *sb; ++ ++ err = vfs_statfs((void *)path, &kstfs); ++ AuTraceErr(err); ++ if (unlikely(err)) ++ goto out; ++ ++ /* todo: support for UUID */ ++ ++ if (kstfs.f_fsid.val[0] || kstfs.f_fsid.val[1]) { ++ brid->type = AuBrid_FSID; ++ brid->fsid = kstfs.f_fsid; ++ } else { ++ dentry = path->dentry; ++ sb = dentry->d_sb; ++ dev = sb->s_dev; ++ if (dev) { ++ brid->type = AuBrid_DEV; ++ brid->dev = dev; ++ } ++ } ++ ++out: ++ return err; ++} ++ ++int au_dr_br_init(struct super_block *sb, struct au_branch *br, ++ const struct path *path) ++{ ++ int err, i; ++ struct au_dr_br *dr; ++ struct hlist_bl_head *hbl; ++ ++ dr = &br->br_dirren; ++ hbl = dr->dr_h_ino; ++ for (i = 0; i < AuDirren_NHASH; i++, hbl++) ++ INIT_HLIST_BL_HEAD(hbl); ++ ++ err = au_dr_brid_init(&dr->dr_brid, path); ++ if (unlikely(err)) ++ goto out; ++ ++ if (au_opt_test(au_mntflags(sb), DIRREN)) ++ err = au_dr_hino(sb, /*bindex*/-1, br, path); ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++int au_dr_br_fin(struct super_block *sb, struct au_branch *br) ++{ ++ int err; ++ ++ err = 0; ++ if (au_br_writable(br->br_perm)) ++ err = au_dr_hino(sb, /*bindex*/-1, br, /*path*/NULL); ++ if (!err) ++ au_dr_hino_free(&br->br_dirren); ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int au_brid_str(struct au_dr_brid *brid, struct inode *h_inode, ++ char *buf, size_t sz) ++{ ++ int err; ++ unsigned int major, minor; ++ char *p; ++ ++ p = buf; ++ err = snprintf(p, sz, "%d_", brid->type); ++ AuDebugOn(err > sz); ++ p += err; ++ sz -= err; ++ switch (brid->type) { ++ case AuBrid_Unset: ++ return -EINVAL; ++ case AuBrid_UUID: ++ err = snprintf(p, sz, "%pU", brid->uuid.b); ++ break; ++ case AuBrid_FSID: ++ err = snprintf(p, sz, "%08x-%08x", ++ brid->fsid.val[0], brid->fsid.val[1]); ++ break; ++ case AuBrid_DEV: ++ major = MAJOR(brid->dev); ++ minor = MINOR(brid->dev); ++ if (major <= 0xff && minor <= 0xff) ++ err = snprintf(p, sz, "%02x%02x", major, minor); ++ else ++ err = snprintf(p, sz, "%03x:%05x", major, minor); ++ break; ++ } ++ AuDebugOn(err > sz); ++ p += err; ++ sz -= err; ++ err = snprintf(p, sz, "_%llu", (unsigned long long)h_inode->i_ino); ++ AuDebugOn(err > sz); ++ p += err; ++ sz -= err; ++ ++ return p - buf; ++} ++ ++static int au_drinfo_name(struct au_branch *br, char *name, int len) ++{ ++ int rlen; ++ struct dentry *br_dentry; ++ struct inode *br_inode; ++ ++ br_dentry = au_br_dentry(br); ++ br_inode = d_inode(br_dentry); ++ rlen = au_brid_str(&br->br_dirren.dr_brid, br_inode, name, len); ++ AuDebugOn(rlen >= AUFS_DIRREN_ENV_VAL_SZ); ++ AuDebugOn(rlen > len); ++ ++ return rlen; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * from the given @h_dentry, construct drinfo at @*fdata. ++ * when the size of @*fdata is not enough, reallocate and return new @fdata and ++ * @allocated. ++ */ ++static int au_drinfo_construct(struct au_drinfo_fdata **fdata, ++ struct dentry *h_dentry, ++ unsigned char *allocated) ++{ ++ int err, v; ++ struct au_drinfo_fdata *f, *p; ++ struct au_drinfo *drinfo; ++ struct inode *h_inode; ++ struct qstr *qname; ++ ++ err = 0; ++ f = *fdata; ++ h_inode = d_inode(h_dentry); ++ qname = &h_dentry->d_name; ++ drinfo = &f->drinfo; ++ drinfo->ino = (__force uint64_t)cpu_to_be64(h_inode->i_ino); ++ drinfo->oldnamelen = qname->len; ++ if (*allocated < sizeof(*f) + qname->len) { ++ v = roundup_pow_of_two(*allocated + qname->len); ++ p = au_krealloc(f, v, GFP_NOFS, /*may_shrink*/0); ++ if (unlikely(!p)) { ++ err = -ENOMEM; ++ AuTraceErr(err); ++ goto out; ++ } ++ f = p; ++ *fdata = f; ++ *allocated = v; ++ drinfo = &f->drinfo; ++ } ++ memcpy(drinfo->oldname, qname->name, qname->len); ++ AuDbg("i%llu, %.*s\n", ++ be64_to_cpu((__force __be64)drinfo->ino), drinfo->oldnamelen, ++ drinfo->oldname); ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++/* callers have to free the return value */ ++static struct au_drinfo *au_drinfo_read_k(struct file *file, ino_t h_ino) ++{ ++ struct au_drinfo *ret, *drinfo; ++ struct au_drinfo_fdata fdata; ++ int len; ++ loff_t pos; ++ ssize_t ssz; ++ ++ ret = ERR_PTR(-EIO); ++ pos = 0; ++ ssz = vfsub_read_k(file, &fdata, sizeof(fdata), &pos); ++ if (unlikely(ssz != sizeof(fdata))) { ++ AuIOErr("ssz %zd, %u, %pD2\n", ++ ssz, (unsigned int)sizeof(fdata), file); ++ goto out; ++ } ++ ++ fdata.magic = ntohl((__force __be32)fdata.magic); ++ switch (fdata.magic) { ++ case AUFS_DRINFO_MAGIC_V1: ++ break; ++ default: ++ AuIOErr("magic-num 0x%x, 0x%x, %pD2\n", ++ fdata.magic, AUFS_DRINFO_MAGIC_V1, file); ++ goto out; ++ } ++ ++ drinfo = &fdata.drinfo; ++ len = drinfo->oldnamelen; ++ if (!len) { ++ AuIOErr("broken drinfo %pD2\n", file); ++ goto out; ++ } ++ ++ ret = NULL; ++ drinfo->ino = be64_to_cpu((__force __be64)drinfo->ino); ++ if (unlikely(h_ino && drinfo->ino != h_ino)) { ++ AuDbg("ignored i%llu, i%llu, %pD2\n", ++ (unsigned long long)drinfo->ino, ++ (unsigned long long)h_ino, file); ++ goto out; /* success */ ++ } ++ ++ ret = kmalloc(sizeof(*ret) + len, GFP_NOFS); ++ if (unlikely(!ret)) { ++ ret = ERR_PTR(-ENOMEM); ++ AuTraceErrPtr(ret); ++ goto out; ++ } ++ ++ *ret = *drinfo; ++ ssz = vfsub_read_k(file, (void *)ret->oldname, len, &pos); ++ if (unlikely(ssz != len)) { ++ au_kfree_rcu(ret); ++ ret = ERR_PTR(-EIO); ++ AuIOErr("ssz %zd, %u, %pD2\n", ssz, len, file); ++ goto out; ++ } ++ ++ AuDbg("oldname %.*s\n", ret->oldnamelen, ret->oldname); ++ ++out: ++ return ret; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* in order to be revertible */ ++struct au_drinfo_rev_elm { ++ int created; ++ struct dentry *info_dentry; ++ struct au_drinfo *info_last; ++}; ++ ++struct au_drinfo_rev { ++ unsigned char already; ++ aufs_bindex_t nelm; ++ struct au_drinfo_rev_elm elm[0]; ++}; ++ ++/* todo: isn't it too large? */ ++struct au_drinfo_store { ++ struct path h_ppath; ++ struct dentry *h_dentry; ++ struct au_drinfo_fdata *fdata; ++ char *infoname; /* inside of whname, just after PFX */ ++ char whname[sizeof(AUFS_WH_DR_INFO_PFX) + AUFS_DIRREN_ENV_VAL_SZ]; ++ aufs_bindex_t btgt, btail; ++ unsigned char no_sio, ++ allocated, /* current size of *fdata */ ++ infonamelen, /* room size for p */ ++ whnamelen, /* length of the generated name */ ++ renameback; /* renamed back */ ++}; ++ ++/* on rename(2) error, the caller should revert it using @elm */ ++static int au_drinfo_do_store(struct au_drinfo_store *w, ++ struct au_drinfo_rev_elm *elm) ++{ ++ int err, len; ++ ssize_t ssz; ++ loff_t pos; ++ struct path infopath = { ++ .mnt = w->h_ppath.mnt ++ }; ++ struct inode *h_dir, *h_inode, *delegated; ++ struct file *infofile; ++ struct qstr *qname; ++ ++ AuDebugOn(elm ++ && memcmp(elm, page_address(ZERO_PAGE(0)), sizeof(*elm))); ++ ++ infopath.dentry = vfsub_lookup_one_len(w->whname, w->h_ppath.dentry, ++ w->whnamelen); ++ AuTraceErrPtr(infopath.dentry); ++ if (IS_ERR(infopath.dentry)) { ++ err = PTR_ERR(infopath.dentry); ++ goto out; ++ } ++ ++ err = 0; ++ h_dir = d_inode(w->h_ppath.dentry); ++ if (elm && d_is_negative(infopath.dentry)) { ++ err = vfsub_create(h_dir, &infopath, 0600, /*want_excl*/true); ++ AuTraceErr(err); ++ if (unlikely(err)) ++ goto out_dput; ++ elm->created = 1; ++ elm->info_dentry = dget(infopath.dentry); ++ } ++ ++ infofile = vfsub_dentry_open(&infopath, O_RDWR); ++ AuTraceErrPtr(infofile); ++ if (IS_ERR(infofile)) { ++ err = PTR_ERR(infofile); ++ goto out_dput; ++ } ++ ++ h_inode = d_inode(infopath.dentry); ++ if (elm && i_size_read(h_inode)) { ++ h_inode = d_inode(w->h_dentry); ++ elm->info_last = au_drinfo_read_k(infofile, h_inode->i_ino); ++ AuTraceErrPtr(elm->info_last); ++ if (IS_ERR(elm->info_last)) { ++ err = PTR_ERR(elm->info_last); ++ elm->info_last = NULL; ++ AuDebugOn(elm->info_dentry); ++ goto out_fput; ++ } ++ } ++ ++ if (elm && w->renameback) { ++ delegated = NULL; ++ err = vfsub_unlink(h_dir, &infopath, &delegated, /*force*/0); ++ AuTraceErr(err); ++ if (unlikely(err == -EWOULDBLOCK)) ++ iput(delegated); ++ goto out_fput; ++ } ++ ++ pos = 0; ++ qname = &w->h_dentry->d_name; ++ len = sizeof(*w->fdata) + qname->len; ++ if (!elm) ++ len = sizeof(*w->fdata) + w->fdata->drinfo.oldnamelen; ++ ssz = vfsub_write_k(infofile, w->fdata, len, &pos); ++ if (ssz == len) { ++ AuDbg("hi%llu, %.*s\n", w->fdata->drinfo.ino, ++ w->fdata->drinfo.oldnamelen, w->fdata->drinfo.oldname); ++ goto out_fput; /* success */ ++ } else { ++ err = -EIO; ++ if (ssz < 0) ++ err = ssz; ++ /* the caller should revert it using @elm */ ++ } ++ ++out_fput: ++ fput(infofile); ++out_dput: ++ dput(infopath.dentry); ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++struct au_call_drinfo_do_store_args { ++ int *errp; ++ struct au_drinfo_store *w; ++ struct au_drinfo_rev_elm *elm; ++}; ++ ++static void au_call_drinfo_do_store(void *args) ++{ ++ struct au_call_drinfo_do_store_args *a = args; ++ ++ *a->errp = au_drinfo_do_store(a->w, a->elm); ++} ++ ++static int au_drinfo_store_sio(struct au_drinfo_store *w, ++ struct au_drinfo_rev_elm *elm) ++{ ++ int err, wkq_err; ++ ++ if (w->no_sio) ++ err = au_drinfo_do_store(w, elm); ++ else { ++ struct au_call_drinfo_do_store_args a = { ++ .errp = &err, ++ .w = w, ++ .elm = elm ++ }; ++ wkq_err = au_wkq_wait(au_call_drinfo_do_store, &a); ++ if (unlikely(wkq_err)) ++ err = wkq_err; ++ } ++ AuTraceErr(err); ++ ++ return err; ++} ++ ++static int au_drinfo_store_work_init(struct au_drinfo_store *w, ++ aufs_bindex_t btgt) ++{ ++ int err; ++ ++ memset(w, 0, sizeof(*w)); ++ w->allocated = roundup_pow_of_two(sizeof(*w->fdata) + 40); ++ strcpy(w->whname, AUFS_WH_DR_INFO_PFX); ++ w->infoname = w->whname + sizeof(AUFS_WH_DR_INFO_PFX) - 1; ++ w->infonamelen = sizeof(w->whname) - sizeof(AUFS_WH_DR_INFO_PFX); ++ w->btgt = btgt; ++ w->no_sio = !!uid_eq(current_fsuid(), GLOBAL_ROOT_UID); ++ ++ err = -ENOMEM; ++ w->fdata = kcalloc(1, w->allocated, GFP_NOFS); ++ if (unlikely(!w->fdata)) { ++ AuTraceErr(err); ++ goto out; ++ } ++ w->fdata->magic = (__force uint32_t)htonl(AUFS_DRINFO_MAGIC_V1); ++ err = 0; ++ ++out: ++ return err; ++} ++ ++static void au_drinfo_store_work_fin(struct au_drinfo_store *w) ++{ ++ au_kfree_rcu(w->fdata); ++} ++ ++static void au_drinfo_store_rev(struct au_drinfo_rev *rev, ++ struct au_drinfo_store *w) ++{ ++ struct au_drinfo_rev_elm *elm; ++ struct inode *h_dir, *delegated; ++ int err, nelm; ++ struct path infopath = { ++ .mnt = w->h_ppath.mnt ++ }; ++ ++ h_dir = d_inode(w->h_ppath.dentry); ++ IMustLock(h_dir); ++ ++ err = 0; ++ elm = rev->elm; ++ for (nelm = rev->nelm; nelm > 0; nelm--, elm++) { ++ AuDebugOn(elm->created && elm->info_last); ++ if (elm->created) { ++ AuDbg("here\n"); ++ delegated = NULL; ++ infopath.dentry = elm->info_dentry; ++ err = vfsub_unlink(h_dir, &infopath, &delegated, ++ !w->no_sio); ++ AuTraceErr(err); ++ if (unlikely(err == -EWOULDBLOCK)) ++ iput(delegated); ++ dput(elm->info_dentry); ++ } else if (elm->info_last) { ++ AuDbg("here\n"); ++ w->fdata->drinfo = *elm->info_last; ++ memcpy(w->fdata->drinfo.oldname, ++ elm->info_last->oldname, ++ elm->info_last->oldnamelen); ++ err = au_drinfo_store_sio(w, /*elm*/NULL); ++ au_kfree_rcu(elm->info_last); ++ } ++ if (unlikely(err)) ++ AuIOErr("%d, %s\n", err, w->whname); ++ /* go on even if err */ ++ } ++} ++ ++/* caller has to call au_dr_rename_fin() later */ ++static int au_drinfo_store(struct dentry *dentry, aufs_bindex_t btgt, ++ struct qstr *dst_name, void *_rev) ++{ ++ int err, sz, nelm; ++ aufs_bindex_t bindex, btail; ++ struct au_drinfo_store work; ++ struct au_drinfo_rev *rev, **p; ++ struct au_drinfo_rev_elm *elm; ++ struct super_block *sb; ++ struct au_branch *br; ++ struct au_hinode *hdir; ++ ++ err = au_drinfo_store_work_init(&work, btgt); ++ AuTraceErr(err); ++ if (unlikely(err)) ++ goto out; ++ ++ err = -ENOMEM; ++ btail = au_dbtaildir(dentry); ++ nelm = btail - btgt; ++ sz = sizeof(*rev) + sizeof(*elm) * nelm; ++ rev = kcalloc(1, sz, GFP_NOFS); ++ if (unlikely(!rev)) { ++ AuTraceErr(err); ++ goto out_args; ++ } ++ rev->nelm = nelm; ++ elm = rev->elm; ++ p = _rev; ++ *p = rev; ++ ++ err = 0; ++ sb = dentry->d_sb; ++ work.h_ppath.dentry = au_h_dptr(dentry, btgt); ++ work.h_ppath.mnt = au_sbr_mnt(sb, btgt); ++ hdir = au_hi(d_inode(dentry), btgt); ++ au_hn_inode_lock_nested(hdir, AuLsc_I_CHILD); ++ for (bindex = btgt + 1; bindex <= btail; bindex++, elm++) { ++ work.h_dentry = au_h_dptr(dentry, bindex); ++ if (!work.h_dentry) ++ continue; ++ ++ err = au_drinfo_construct(&work.fdata, work.h_dentry, ++ &work.allocated); ++ AuTraceErr(err); ++ if (unlikely(err)) ++ break; ++ ++ work.renameback = au_qstreq(&work.h_dentry->d_name, dst_name); ++ br = au_sbr(sb, bindex); ++ work.whnamelen = sizeof(AUFS_WH_DR_INFO_PFX) - 1; ++ work.whnamelen += au_drinfo_name(br, work.infoname, ++ work.infonamelen); ++ AuDbg("whname %.*s, i%llu, %.*s\n", ++ work.whnamelen, work.whname, ++ be64_to_cpu((__force __be64)work.fdata->drinfo.ino), ++ work.fdata->drinfo.oldnamelen, ++ work.fdata->drinfo.oldname); ++ ++ err = au_drinfo_store_sio(&work, elm); ++ AuTraceErr(err); ++ if (unlikely(err)) ++ break; ++ } ++ if (unlikely(err)) { ++ /* revert all drinfo */ ++ au_drinfo_store_rev(rev, &work); ++ au_kfree_try_rcu(rev); ++ *p = NULL; ++ } ++ au_hn_inode_unlock(hdir); ++ ++out_args: ++ au_drinfo_store_work_fin(&work); ++out: ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++int au_dr_rename(struct dentry *src, aufs_bindex_t bindex, ++ struct qstr *dst_name, void *_rev) ++{ ++ int err, already; ++ ino_t ino; ++ struct super_block *sb; ++ struct au_branch *br; ++ struct au_dr_br *dr; ++ struct dentry *h_dentry; ++ struct inode *h_inode; ++ struct au_dr_hino *ent; ++ struct au_drinfo_rev *rev, **p; ++ ++ AuDbg("bindex %d\n", bindex); ++ ++ err = -ENOMEM; ++ ent = kmalloc(sizeof(*ent), GFP_NOFS); ++ if (unlikely(!ent)) ++ goto out; ++ ++ sb = src->d_sb; ++ br = au_sbr(sb, bindex); ++ dr = &br->br_dirren; ++ h_dentry = au_h_dptr(src, bindex); ++ h_inode = d_inode(h_dentry); ++ ino = h_inode->i_ino; ++ ent->dr_h_ino = ino; ++ already = au_dr_hino_test_add(dr, ino, ent); ++ AuDbg("b%d, hi%llu, already %d\n", ++ bindex, (unsigned long long)ino, already); ++ ++ err = au_drinfo_store(src, bindex, dst_name, _rev); ++ AuTraceErr(err); ++ if (!err) { ++ p = _rev; ++ rev = *p; ++ rev->already = already; ++ goto out; /* success */ ++ } ++ ++ /* revert */ ++ if (!already) ++ au_dr_hino_del(dr, ent); ++ au_kfree_rcu(ent); ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++void au_dr_rename_fin(struct dentry *src, aufs_bindex_t btgt, void *_rev) ++{ ++ struct au_drinfo_rev *rev; ++ struct au_drinfo_rev_elm *elm; ++ int nelm; ++ ++ rev = _rev; ++ elm = rev->elm; ++ for (nelm = rev->nelm; nelm > 0; nelm--, elm++) { ++ dput(elm->info_dentry); ++ au_kfree_rcu(elm->info_last); ++ } ++ au_kfree_try_rcu(rev); ++} ++ ++void au_dr_rename_rev(struct dentry *src, aufs_bindex_t btgt, void *_rev) ++{ ++ int err; ++ struct au_drinfo_store work; ++ struct au_drinfo_rev *rev = _rev; ++ struct super_block *sb; ++ struct au_branch *br; ++ struct inode *h_inode; ++ struct au_dr_br *dr; ++ struct au_dr_hino *ent; ++ ++ err = au_drinfo_store_work_init(&work, btgt); ++ if (unlikely(err)) ++ goto out; ++ ++ sb = src->d_sb; ++ br = au_sbr(sb, btgt); ++ work.h_ppath.dentry = au_h_dptr(src, btgt); ++ work.h_ppath.mnt = au_br_mnt(br); ++ au_drinfo_store_rev(rev, &work); ++ au_drinfo_store_work_fin(&work); ++ if (rev->already) ++ goto out; ++ ++ dr = &br->br_dirren; ++ h_inode = d_inode(work.h_ppath.dentry); ++ ent = au_dr_hino_find(dr, h_inode->i_ino); ++ BUG_ON(!ent); ++ au_dr_hino_del(dr, ent); ++ au_kfree_rcu(ent); ++ ++out: ++ au_kfree_try_rcu(rev); ++ if (unlikely(err)) ++ pr_err("failed to remove dirren info\n"); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static struct au_drinfo *au_drinfo_do_load(struct path *h_ppath, ++ char *whname, int whnamelen, ++ struct dentry **info_dentry) ++{ ++ struct au_drinfo *drinfo; ++ struct file *f; ++ struct inode *h_dir; ++ struct path infopath; ++ int unlocked; ++ ++ AuDbg("%pd/%.*s\n", h_ppath->dentry, whnamelen, whname); ++ ++ *info_dentry = NULL; ++ drinfo = NULL; ++ unlocked = 0; ++ h_dir = d_inode(h_ppath->dentry); ++ inode_lock_shared_nested(h_dir, AuLsc_I_PARENT); ++ infopath.dentry = vfsub_lookup_one_len(whname, h_ppath->dentry, ++ whnamelen); ++ if (IS_ERR(infopath.dentry)) { ++ drinfo = (void *)infopath.dentry; ++ goto out; ++ } ++ ++ if (d_is_negative(infopath.dentry)) ++ goto out_dput; /* success */ ++ ++ infopath.mnt = h_ppath->mnt; ++ f = vfsub_dentry_open(&infopath, O_RDONLY); ++ inode_unlock_shared(h_dir); ++ unlocked = 1; ++ if (IS_ERR(f)) { ++ drinfo = (void *)f; ++ goto out_dput; ++ } ++ ++ drinfo = au_drinfo_read_k(f, /*h_ino*/0); ++ if (IS_ERR_OR_NULL(drinfo)) ++ goto out_fput; ++ ++ AuDbg("oldname %.*s\n", drinfo->oldnamelen, drinfo->oldname); ++ *info_dentry = dget(infopath.dentry); /* keep it alive */ ++ ++out_fput: ++ fput(f); ++out_dput: ++ dput(infopath.dentry); ++out: ++ if (!unlocked) ++ inode_unlock_shared(h_dir); ++ AuTraceErrPtr(drinfo); ++ return drinfo; ++} ++ ++struct au_drinfo_do_load_args { ++ struct au_drinfo **drinfop; ++ struct path *h_ppath; ++ char *whname; ++ int whnamelen; ++ struct dentry **info_dentry; ++}; ++ ++static void au_call_drinfo_do_load(void *args) ++{ ++ struct au_drinfo_do_load_args *a = args; ++ ++ *a->drinfop = au_drinfo_do_load(a->h_ppath, a->whname, a->whnamelen, ++ a->info_dentry); ++} ++ ++struct au_drinfo_load { ++ struct path h_ppath; ++ struct qstr *qname; ++ unsigned char no_sio; ++ ++ aufs_bindex_t ninfo; ++ struct au_drinfo **drinfo; ++}; ++ ++static int au_drinfo_load(struct au_drinfo_load *w, aufs_bindex_t bindex, ++ struct au_branch *br) ++{ ++ int err, wkq_err, whnamelen, e; ++ char whname[sizeof(AUFS_WH_DR_INFO_PFX) + AUFS_DIRREN_ENV_VAL_SZ] ++ = AUFS_WH_DR_INFO_PFX; ++ struct au_drinfo *drinfo; ++ struct qstr oldname; ++ struct inode *h_dir, *delegated; ++ struct dentry *info_dentry; ++ struct path infopath; ++ ++ whnamelen = sizeof(AUFS_WH_DR_INFO_PFX) - 1; ++ whnamelen += au_drinfo_name(br, whname + whnamelen, ++ sizeof(whname) - whnamelen); ++ if (w->no_sio) ++ drinfo = au_drinfo_do_load(&w->h_ppath, whname, whnamelen, ++ &info_dentry); ++ else { ++ struct au_drinfo_do_load_args args = { ++ .drinfop = &drinfo, ++ .h_ppath = &w->h_ppath, ++ .whname = whname, ++ .whnamelen = whnamelen, ++ .info_dentry = &info_dentry ++ }; ++ wkq_err = au_wkq_wait(au_call_drinfo_do_load, &args); ++ if (unlikely(wkq_err)) ++ drinfo = ERR_PTR(wkq_err); ++ } ++ err = PTR_ERR(drinfo); ++ if (IS_ERR_OR_NULL(drinfo)) ++ goto out; ++ ++ err = 0; ++ oldname.len = drinfo->oldnamelen; ++ oldname.name = drinfo->oldname; ++ if (au_qstreq(w->qname, &oldname)) { ++ /* the name is renamed back */ ++ au_kfree_rcu(drinfo); ++ drinfo = NULL; ++ ++ infopath.dentry = info_dentry; ++ infopath.mnt = w->h_ppath.mnt; ++ h_dir = d_inode(w->h_ppath.dentry); ++ delegated = NULL; ++ inode_lock_nested(h_dir, AuLsc_I_PARENT); ++ e = vfsub_unlink(h_dir, &infopath, &delegated, !w->no_sio); ++ inode_unlock(h_dir); ++ if (unlikely(e)) ++ AuIOErr("ignored %d, %pd2\n", e, &infopath.dentry); ++ if (unlikely(e == -EWOULDBLOCK)) ++ iput(delegated); ++ } ++ au_kfree_rcu(w->drinfo[bindex]); ++ w->drinfo[bindex] = drinfo; ++ dput(info_dentry); ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static void au_dr_lkup_free(struct au_drinfo **drinfo, int n) ++{ ++ struct au_drinfo **p = drinfo; ++ ++ while (n-- > 0) ++ au_kfree_rcu(*drinfo++); ++ au_kfree_try_rcu(p); ++} ++ ++int au_dr_lkup(struct au_do_lookup_args *lkup, struct dentry *dentry, ++ aufs_bindex_t btgt) ++{ ++ int err, ninfo; ++ struct au_drinfo_load w; ++ aufs_bindex_t bindex, bbot; ++ struct au_branch *br; ++ struct inode *h_dir; ++ struct au_dr_hino *ent; ++ struct super_block *sb; ++ ++ AuDbg("%.*s, name %.*s, whname %.*s, b%d\n", ++ AuLNPair(&dentry->d_name), AuLNPair(&lkup->dirren.dr_name), ++ AuLNPair(&lkup->whname), btgt); ++ ++ sb = dentry->d_sb; ++ bbot = au_sbbot(sb); ++ w.ninfo = bbot + 1; ++ if (!lkup->dirren.drinfo) { ++ lkup->dirren.drinfo = kcalloc(w.ninfo, ++ sizeof(*lkup->dirren.drinfo), ++ GFP_NOFS); ++ if (unlikely(!lkup->dirren.drinfo)) { ++ err = -ENOMEM; ++ goto out; ++ } ++ lkup->dirren.ninfo = w.ninfo; ++ } ++ w.drinfo = lkup->dirren.drinfo; ++ w.no_sio = !!uid_eq(current_fsuid(), GLOBAL_ROOT_UID); ++ w.h_ppath.dentry = au_h_dptr(dentry, btgt); ++ AuDebugOn(!w.h_ppath.dentry); ++ w.h_ppath.mnt = au_sbr_mnt(sb, btgt); ++ w.qname = &dentry->d_name; ++ ++ ninfo = 0; ++ for (bindex = btgt + 1; bindex <= bbot; bindex++) { ++ br = au_sbr(sb, bindex); ++ err = au_drinfo_load(&w, bindex, br); ++ if (unlikely(err)) ++ goto out_free; ++ if (w.drinfo[bindex]) ++ ninfo++; ++ } ++ if (!ninfo) { ++ br = au_sbr(sb, btgt); ++ h_dir = d_inode(w.h_ppath.dentry); ++ ent = au_dr_hino_find(&br->br_dirren, h_dir->i_ino); ++ AuDebugOn(!ent); ++ au_dr_hino_del(&br->br_dirren, ent); ++ au_kfree_rcu(ent); ++ } ++ goto out; /* success */ ++ ++out_free: ++ au_dr_lkup_free(lkup->dirren.drinfo, lkup->dirren.ninfo); ++ lkup->dirren.ninfo = 0; ++ lkup->dirren.drinfo = NULL; ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++void au_dr_lkup_fin(struct au_do_lookup_args *lkup) ++{ ++ au_dr_lkup_free(lkup->dirren.drinfo, lkup->dirren.ninfo); ++} ++ ++int au_dr_lkup_name(struct au_do_lookup_args *lkup, aufs_bindex_t btgt) ++{ ++ int err; ++ struct au_drinfo *drinfo; ++ ++ err = 0; ++ if (!lkup->dirren.drinfo) ++ goto out; ++ AuDebugOn(lkup->dirren.ninfo < btgt + 1); ++ drinfo = lkup->dirren.drinfo[btgt + 1]; ++ if (!drinfo) ++ goto out; ++ ++ au_kfree_try_rcu(lkup->whname.name); ++ lkup->whname.name = NULL; ++ lkup->dirren.dr_name.len = drinfo->oldnamelen; ++ lkup->dirren.dr_name.name = drinfo->oldname; ++ lkup->name = &lkup->dirren.dr_name; ++ err = au_wh_name_alloc(&lkup->whname, lkup->name); ++ if (!err) ++ AuDbg("name %.*s, whname %.*s, b%d\n", ++ AuLNPair(lkup->name), AuLNPair(&lkup->whname), ++ btgt); ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++int au_dr_lkup_h_ino(struct au_do_lookup_args *lkup, aufs_bindex_t bindex, ++ ino_t h_ino) ++{ ++ int match; ++ struct au_drinfo *drinfo; ++ ++ match = 1; ++ if (!lkup->dirren.drinfo) ++ goto out; ++ AuDebugOn(lkup->dirren.ninfo < bindex + 1); ++ drinfo = lkup->dirren.drinfo[bindex + 1]; ++ if (!drinfo) ++ goto out; ++ ++ match = (drinfo->ino == h_ino); ++ AuDbg("match %d\n", match); ++ ++out: ++ return match; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++int au_dr_opt_set(struct super_block *sb) ++{ ++ int err; ++ aufs_bindex_t bindex, bbot; ++ struct au_branch *br; ++ ++ err = 0; ++ bbot = au_sbbot(sb); ++ for (bindex = 0; !err && bindex <= bbot; bindex++) { ++ br = au_sbr(sb, bindex); ++ err = au_dr_hino(sb, bindex, /*br*/NULL, &br->br_path); ++ } ++ ++ return err; ++} ++ ++int au_dr_opt_flush(struct super_block *sb) ++{ ++ int err; ++ aufs_bindex_t bindex, bbot; ++ struct au_branch *br; ++ ++ err = 0; ++ bbot = au_sbbot(sb); ++ for (bindex = 0; !err && bindex <= bbot; bindex++) { ++ br = au_sbr(sb, bindex); ++ if (au_br_writable(br->br_perm)) ++ err = au_dr_hino(sb, bindex, /*br*/NULL, /*path*/NULL); ++ } ++ ++ return err; ++} ++ ++int au_dr_opt_clr(struct super_block *sb, int no_flush) ++{ ++ int err; ++ aufs_bindex_t bindex, bbot; ++ struct au_branch *br; ++ ++ err = 0; ++ if (!no_flush) { ++ err = au_dr_opt_flush(sb); ++ if (unlikely(err)) ++ goto out; ++ } ++ ++ bbot = au_sbbot(sb); ++ for (bindex = 0; bindex <= bbot; bindex++) { ++ br = au_sbr(sb, bindex); ++ au_dr_hino_free(&br->br_dirren); ++ } ++ ++out: ++ return err; ++} +diff -Nurp linux-5.4/fs/aufs/dirren.h linux-5.4-aufs/fs/aufs/dirren.h +--- linux-5.4/fs/aufs/dirren.h 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/dirren.h 2019-11-28 01:25:59.064925618 +0200 +@@ -0,0 +1,127 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2017-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * renamed dir info ++ */ ++ ++#ifndef __AUFS_DIRREN_H__ ++#define __AUFS_DIRREN_H__ ++ ++#ifdef __KERNEL__ ++ ++#include ++#include ++#include ++#include "hbl.h" ++ ++#define AuDirren_NHASH 100 ++ ++#ifdef CONFIG_AUFS_DIRREN ++enum au_brid_type { ++ AuBrid_Unset, ++ AuBrid_UUID, ++ AuBrid_FSID, ++ AuBrid_DEV ++}; ++ ++struct au_dr_brid { ++ enum au_brid_type type; ++ union { ++ uuid_t uuid; /* unimplemented yet */ ++ fsid_t fsid; ++ dev_t dev; ++ }; ++}; ++ ++/* 20 is the max digits length of ulong 64 */ ++/* brid-type "_" uuid "_" inum */ ++#define AUFS_DIRREN_FNAME_SZ (1 + 1 + UUID_STRING_LEN + 20) ++#define AUFS_DIRREN_ENV_VAL_SZ (AUFS_DIRREN_FNAME_SZ + 1 + 20) ++ ++struct au_dr_hino { ++ struct hlist_bl_node dr_hnode; ++ ino_t dr_h_ino; ++}; ++ ++struct au_dr_br { ++ struct hlist_bl_head dr_h_ino[AuDirren_NHASH]; ++ struct au_dr_brid dr_brid; ++}; ++ ++struct au_dr_lookup { ++ /* dr_name is pointed by struct au_do_lookup_args.name */ ++ struct qstr dr_name; /* subset of dr_info */ ++ aufs_bindex_t ninfo; ++ struct au_drinfo **drinfo; ++}; ++#else ++struct au_dr_hino; ++/* empty */ ++struct au_dr_br { }; ++struct au_dr_lookup { }; ++#endif ++ ++/* ---------------------------------------------------------------------- */ ++ ++struct au_branch; ++struct au_do_lookup_args; ++struct au_hinode; ++#ifdef CONFIG_AUFS_DIRREN ++int au_dr_hino_test_add(struct au_dr_br *dr, ino_t h_ino, ++ struct au_dr_hino *add_ent); ++void au_dr_hino_free(struct au_dr_br *dr); ++int au_dr_br_init(struct super_block *sb, struct au_branch *br, ++ const struct path *path); ++int au_dr_br_fin(struct super_block *sb, struct au_branch *br); ++int au_dr_rename(struct dentry *src, aufs_bindex_t bindex, ++ struct qstr *dst_name, void *_rev); ++void au_dr_rename_fin(struct dentry *src, aufs_bindex_t btgt, void *rev); ++void au_dr_rename_rev(struct dentry *src, aufs_bindex_t bindex, void *rev); ++int au_dr_lkup(struct au_do_lookup_args *lkup, struct dentry *dentry, ++ aufs_bindex_t bindex); ++int au_dr_lkup_name(struct au_do_lookup_args *lkup, aufs_bindex_t btgt); ++int au_dr_lkup_h_ino(struct au_do_lookup_args *lkup, aufs_bindex_t bindex, ++ ino_t h_ino); ++void au_dr_lkup_fin(struct au_do_lookup_args *lkup); ++int au_dr_opt_set(struct super_block *sb); ++int au_dr_opt_flush(struct super_block *sb); ++int au_dr_opt_clr(struct super_block *sb, int no_flush); ++#else ++AuStubInt0(au_dr_hino_test_add, struct au_dr_br *dr, ino_t h_ino, ++ struct au_dr_hino *add_ent); ++AuStubVoid(au_dr_hino_free, struct au_dr_br *dr); ++AuStubInt0(au_dr_br_init, struct super_block *sb, struct au_branch *br, ++ const struct path *path); ++AuStubInt0(au_dr_br_fin, struct super_block *sb, struct au_branch *br); ++AuStubInt0(au_dr_rename, struct dentry *src, aufs_bindex_t bindex, ++ struct qstr *dst_name, void *_rev); ++AuStubVoid(au_dr_rename_fin, struct dentry *src, aufs_bindex_t btgt, void *rev); ++AuStubVoid(au_dr_rename_rev, struct dentry *src, aufs_bindex_t bindex, ++ void *rev); ++AuStubInt0(au_dr_lkup, struct au_do_lookup_args *lkup, struct dentry *dentry, ++ aufs_bindex_t bindex); ++AuStubInt0(au_dr_lkup_name, struct au_do_lookup_args *lkup, aufs_bindex_t btgt); ++AuStubInt0(au_dr_lkup_h_ino, struct au_do_lookup_args *lkup, ++ aufs_bindex_t bindex, ino_t h_ino); ++AuStubVoid(au_dr_lkup_fin, struct au_do_lookup_args *lkup); ++AuStubInt0(au_dr_opt_set, struct super_block *sb); ++AuStubInt0(au_dr_opt_flush, struct super_block *sb); ++AuStubInt0(au_dr_opt_clr, struct super_block *sb, int no_flush); ++#endif ++ ++/* ---------------------------------------------------------------------- */ ++ ++#ifdef CONFIG_AUFS_DIRREN ++static inline int au_dr_ihash(ino_t h_ino) ++{ ++ return h_ino % AuDirren_NHASH; ++} ++#else ++AuStubInt0(au_dr_ihash, ino_t h_ino); ++#endif ++ ++#endif /* __KERNEL__ */ ++#endif /* __AUFS_DIRREN_H__ */ +diff -Nurp linux-5.4/fs/aufs/dynop.c linux-5.4-aufs/fs/aufs/dynop.c +--- linux-5.4/fs/aufs/dynop.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/dynop.c 2019-11-28 01:25:59.064925618 +0200 +@@ -0,0 +1,354 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2010-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * dynamically customizable operations for regular files ++ */ ++ ++#include "aufs.h" ++ ++#define DyPrSym(key) AuDbgSym(key->dk_op.dy_hop) ++ ++/* ++ * How large will these lists be? ++ * Usually just a few elements, 20-30 at most for each, I guess. ++ */ ++static struct hlist_bl_head dynop[AuDyLast]; ++ ++static struct au_dykey *dy_gfind_get(struct hlist_bl_head *hbl, ++ const void *h_op) ++{ ++ struct au_dykey *key, *tmp; ++ struct hlist_bl_node *pos; ++ ++ key = NULL; ++ hlist_bl_lock(hbl); ++ hlist_bl_for_each_entry(tmp, pos, hbl, dk_hnode) ++ if (tmp->dk_op.dy_hop == h_op) { ++ if (kref_get_unless_zero(&tmp->dk_kref)) ++ key = tmp; ++ break; ++ } ++ hlist_bl_unlock(hbl); ++ ++ return key; ++} ++ ++static struct au_dykey *dy_bradd(struct au_branch *br, struct au_dykey *key) ++{ ++ struct au_dykey **k, *found; ++ const void *h_op = key->dk_op.dy_hop; ++ int i; ++ ++ found = NULL; ++ k = br->br_dykey; ++ for (i = 0; i < AuBrDynOp; i++) ++ if (k[i]) { ++ if (k[i]->dk_op.dy_hop == h_op) { ++ found = k[i]; ++ break; ++ } ++ } else ++ break; ++ if (!found) { ++ spin_lock(&br->br_dykey_lock); ++ for (; i < AuBrDynOp; i++) ++ if (k[i]) { ++ if (k[i]->dk_op.dy_hop == h_op) { ++ found = k[i]; ++ break; ++ } ++ } else { ++ k[i] = key; ++ break; ++ } ++ spin_unlock(&br->br_dykey_lock); ++ BUG_ON(i == AuBrDynOp); /* expand the array */ ++ } ++ ++ return found; ++} ++ ++/* kref_get() if @key is already added */ ++static struct au_dykey *dy_gadd(struct hlist_bl_head *hbl, struct au_dykey *key) ++{ ++ struct au_dykey *tmp, *found; ++ struct hlist_bl_node *pos; ++ const void *h_op = key->dk_op.dy_hop; ++ ++ found = NULL; ++ hlist_bl_lock(hbl); ++ hlist_bl_for_each_entry(tmp, pos, hbl, dk_hnode) ++ if (tmp->dk_op.dy_hop == h_op) { ++ if (kref_get_unless_zero(&tmp->dk_kref)) ++ found = tmp; ++ break; ++ } ++ if (!found) ++ hlist_bl_add_head(&key->dk_hnode, hbl); ++ hlist_bl_unlock(hbl); ++ ++ if (!found) ++ DyPrSym(key); ++ return found; ++} ++ ++static void dy_free_rcu(struct rcu_head *rcu) ++{ ++ struct au_dykey *key; ++ ++ key = container_of(rcu, struct au_dykey, dk_rcu); ++ DyPrSym(key); ++ kfree(key); ++} ++ ++static void dy_free(struct kref *kref) ++{ ++ struct au_dykey *key; ++ struct hlist_bl_head *hbl; ++ ++ key = container_of(kref, struct au_dykey, dk_kref); ++ hbl = dynop + key->dk_op.dy_type; ++ au_hbl_del(&key->dk_hnode, hbl); ++ call_rcu(&key->dk_rcu, dy_free_rcu); ++} ++ ++void au_dy_put(struct au_dykey *key) ++{ ++ kref_put(&key->dk_kref, dy_free); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++#define DyDbgSize(cnt, op) AuDebugOn(cnt != sizeof(op)/sizeof(void *)) ++ ++#ifdef CONFIG_AUFS_DEBUG ++#define DyDbgDeclare(cnt) unsigned int cnt = 0 ++#define DyDbgInc(cnt) do { cnt++; } while (0) ++#else ++#define DyDbgDeclare(cnt) do {} while (0) ++#define DyDbgInc(cnt) do {} while (0) ++#endif ++ ++#define DySet(func, dst, src, h_op, h_sb) do { \ ++ DyDbgInc(cnt); \ ++ if (h_op->func) { \ ++ if (src.func) \ ++ dst.func = src.func; \ ++ else \ ++ AuDbg("%s %s\n", au_sbtype(h_sb), #func); \ ++ } \ ++} while (0) ++ ++#define DySetForce(func, dst, src) do { \ ++ AuDebugOn(!src.func); \ ++ DyDbgInc(cnt); \ ++ dst.func = src.func; \ ++} while (0) ++ ++#define DySetAop(func) \ ++ DySet(func, dyaop->da_op, aufs_aop, h_aop, h_sb) ++#define DySetAopForce(func) \ ++ DySetForce(func, dyaop->da_op, aufs_aop) ++ ++static void dy_aop(struct au_dykey *key, const void *h_op, ++ struct super_block *h_sb __maybe_unused) ++{ ++ struct au_dyaop *dyaop = (void *)key; ++ const struct address_space_operations *h_aop = h_op; ++ DyDbgDeclare(cnt); ++ ++ AuDbg("%s\n", au_sbtype(h_sb)); ++ ++ DySetAop(writepage); ++ DySetAopForce(readpage); /* force */ ++ DySetAop(writepages); ++ DySetAop(set_page_dirty); ++ DySetAop(readpages); ++ DySetAop(write_begin); ++ DySetAop(write_end); ++ DySetAop(bmap); ++ DySetAop(invalidatepage); ++ DySetAop(releasepage); ++ DySetAop(freepage); ++ /* this one will be changed according to an aufs mount option */ ++ DySetAop(direct_IO); ++ DySetAop(migratepage); ++ DySetAop(isolate_page); ++ DySetAop(putback_page); ++ DySetAop(launder_page); ++ DySetAop(is_partially_uptodate); ++ DySetAop(is_dirty_writeback); ++ DySetAop(error_remove_page); ++ DySetAop(swap_activate); ++ DySetAop(swap_deactivate); ++ ++ DyDbgSize(cnt, *h_aop); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static void dy_bug(struct kref *kref) ++{ ++ BUG(); ++} ++ ++static struct au_dykey *dy_get(struct au_dynop *op, struct au_branch *br) ++{ ++ struct au_dykey *key, *old; ++ struct hlist_bl_head *hbl; ++ struct op { ++ unsigned int sz; ++ void (*set)(struct au_dykey *key, const void *h_op, ++ struct super_block *h_sb __maybe_unused); ++ }; ++ static const struct op a[] = { ++ [AuDy_AOP] = { ++ .sz = sizeof(struct au_dyaop), ++ .set = dy_aop ++ } ++ }; ++ const struct op *p; ++ ++ hbl = dynop + op->dy_type; ++ key = dy_gfind_get(hbl, op->dy_hop); ++ if (key) ++ goto out_add; /* success */ ++ ++ p = a + op->dy_type; ++ key = kzalloc(p->sz, GFP_NOFS); ++ if (unlikely(!key)) { ++ key = ERR_PTR(-ENOMEM); ++ goto out; ++ } ++ ++ key->dk_op.dy_hop = op->dy_hop; ++ kref_init(&key->dk_kref); ++ p->set(key, op->dy_hop, au_br_sb(br)); ++ old = dy_gadd(hbl, key); ++ if (old) { ++ au_kfree_rcu(key); ++ key = old; ++ } ++ ++out_add: ++ old = dy_bradd(br, key); ++ if (old) ++ /* its ref-count should never be zero here */ ++ kref_put(&key->dk_kref, dy_bug); ++out: ++ return key; ++} ++ ++/* ---------------------------------------------------------------------- */ ++/* ++ * Aufs prohibits O_DIRECT by default even if the branch supports it. ++ * This behaviour is necessary to return an error from open(O_DIRECT) instead ++ * of the succeeding I/O. The dio mount option enables O_DIRECT and makes ++ * open(O_DIRECT) always succeed, but the succeeding I/O may return an error. ++ * See the aufs manual in detail. ++ */ ++static void dy_adx(struct au_dyaop *dyaop, int do_dx) ++{ ++ if (!do_dx) ++ dyaop->da_op.direct_IO = NULL; ++ else ++ dyaop->da_op.direct_IO = aufs_aop.direct_IO; ++} ++ ++static struct au_dyaop *dy_aget(struct au_branch *br, ++ const struct address_space_operations *h_aop, ++ int do_dx) ++{ ++ struct au_dyaop *dyaop; ++ struct au_dynop op; ++ ++ op.dy_type = AuDy_AOP; ++ op.dy_haop = h_aop; ++ dyaop = (void *)dy_get(&op, br); ++ if (IS_ERR(dyaop)) ++ goto out; ++ dy_adx(dyaop, do_dx); ++ ++out: ++ return dyaop; ++} ++ ++int au_dy_iaop(struct inode *inode, aufs_bindex_t bindex, ++ struct inode *h_inode) ++{ ++ int err, do_dx; ++ struct super_block *sb; ++ struct au_branch *br; ++ struct au_dyaop *dyaop; ++ ++ AuDebugOn(!S_ISREG(h_inode->i_mode)); ++ IiMustWriteLock(inode); ++ ++ sb = inode->i_sb; ++ br = au_sbr(sb, bindex); ++ do_dx = !!au_opt_test(au_mntflags(sb), DIO); ++ dyaop = dy_aget(br, h_inode->i_mapping->a_ops, do_dx); ++ err = PTR_ERR(dyaop); ++ if (IS_ERR(dyaop)) ++ /* unnecessary to call dy_fput() */ ++ goto out; ++ ++ err = 0; ++ inode->i_mapping->a_ops = &dyaop->da_op; ++ ++out: ++ return err; ++} ++ ++/* ++ * Is it safe to replace a_ops during the inode/file is in operation? ++ * Yes, I hope so. ++ */ ++int au_dy_irefresh(struct inode *inode) ++{ ++ int err; ++ aufs_bindex_t btop; ++ struct inode *h_inode; ++ ++ err = 0; ++ if (S_ISREG(inode->i_mode)) { ++ btop = au_ibtop(inode); ++ h_inode = au_h_iptr(inode, btop); ++ err = au_dy_iaop(inode, btop, h_inode); ++ } ++ return err; ++} ++ ++void au_dy_arefresh(int do_dx) ++{ ++ struct hlist_bl_head *hbl; ++ struct hlist_bl_node *pos; ++ struct au_dykey *key; ++ ++ hbl = dynop + AuDy_AOP; ++ hlist_bl_lock(hbl); ++ hlist_bl_for_each_entry(key, pos, hbl, dk_hnode) ++ dy_adx((void *)key, do_dx); ++ hlist_bl_unlock(hbl); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++void __init au_dy_init(void) ++{ ++ int i; ++ ++ for (i = 0; i < AuDyLast; i++) ++ INIT_HLIST_BL_HEAD(dynop + i); ++} ++ ++void au_dy_fin(void) ++{ ++ int i; ++ ++ for (i = 0; i < AuDyLast; i++) ++ WARN_ON(!hlist_bl_empty(dynop + i)); ++} +diff -Nurp linux-5.4/fs/aufs/dynop.h linux-5.4-aufs/fs/aufs/dynop.h +--- linux-5.4/fs/aufs/dynop.h 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/dynop.h 2019-11-28 01:25:59.064925618 +0200 +@@ -0,0 +1,64 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2010-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * dynamically customizable operations (for regular files only) ++ */ ++ ++#ifndef __AUFS_DYNOP_H__ ++#define __AUFS_DYNOP_H__ ++ ++#ifdef __KERNEL__ ++ ++#include ++#include ++ ++enum {AuDy_AOP, AuDyLast}; ++ ++struct au_dynop { ++ int dy_type; ++ union { ++ const void *dy_hop; ++ const struct address_space_operations *dy_haop; ++ }; ++}; ++ ++struct au_dykey { ++ union { ++ struct hlist_bl_node dk_hnode; ++ struct rcu_head dk_rcu; ++ }; ++ struct au_dynop dk_op; ++ ++ /* ++ * during I am in the branch local array, kref is gotten. when the ++ * branch is removed, kref is put. ++ */ ++ struct kref dk_kref; ++}; ++ ++/* stop unioning since their sizes are very different from each other */ ++struct au_dyaop { ++ struct au_dykey da_key; ++ struct address_space_operations da_op; /* not const */ ++}; ++/* make sure that 'struct au_dykey *' can be any type */ ++static_assert(!offsetof(struct au_dyaop, da_key)); ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* dynop.c */ ++struct au_branch; ++void au_dy_put(struct au_dykey *key); ++int au_dy_iaop(struct inode *inode, aufs_bindex_t bindex, ++ struct inode *h_inode); ++int au_dy_irefresh(struct inode *inode); ++void au_dy_arefresh(int do_dio); ++ ++void __init au_dy_init(void); ++void au_dy_fin(void); ++ ++#endif /* __KERNEL__ */ ++#endif /* __AUFS_DYNOP_H__ */ +diff -Nurp linux-5.4/fs/aufs/export.c linux-5.4-aufs/fs/aufs/export.c +--- linux-5.4/fs/aufs/export.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/export.c 2019-11-28 01:25:59.064925618 +0200 +@@ -0,0 +1,825 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * export via nfs ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "aufs.h" ++ ++union conv { ++#ifdef CONFIG_AUFS_INO_T_64 ++ __u32 a[2]; ++#else ++ __u32 a[1]; ++#endif ++ ino_t ino; ++}; ++ ++static ino_t decode_ino(__u32 *a) ++{ ++ union conv u; ++ ++ BUILD_BUG_ON(sizeof(u.ino) != sizeof(u.a)); ++ u.a[0] = a[0]; ++#ifdef CONFIG_AUFS_INO_T_64 ++ u.a[1] = a[1]; ++#endif ++ return u.ino; ++} ++ ++static void encode_ino(__u32 *a, ino_t ino) ++{ ++ union conv u; ++ ++ u.ino = ino; ++ a[0] = u.a[0]; ++#ifdef CONFIG_AUFS_INO_T_64 ++ a[1] = u.a[1]; ++#endif ++} ++ ++/* NFS file handle */ ++enum { ++ Fh_br_id, ++ Fh_sigen, ++#ifdef CONFIG_AUFS_INO_T_64 ++ /* support 64bit inode number */ ++ Fh_ino1, ++ Fh_ino2, ++ Fh_dir_ino1, ++ Fh_dir_ino2, ++#else ++ Fh_ino1, ++ Fh_dir_ino1, ++#endif ++ Fh_igen, ++ Fh_h_type, ++ Fh_tail, ++ ++ Fh_ino = Fh_ino1, ++ Fh_dir_ino = Fh_dir_ino1 ++}; ++ ++static int au_test_anon(struct dentry *dentry) ++{ ++ /* note: read d_flags without d_lock */ ++ return !!(dentry->d_flags & DCACHE_DISCONNECTED); ++} ++ ++int au_test_nfsd(void) ++{ ++ int ret; ++ struct task_struct *tsk = current; ++ char comm[sizeof(tsk->comm)]; ++ ++ ret = 0; ++ if (tsk->flags & PF_KTHREAD) { ++ get_task_comm(comm, tsk); ++ ret = !strcmp(comm, "nfsd"); ++ } ++ ++ return ret; ++} ++ ++/* ---------------------------------------------------------------------- */ ++/* inode generation external table */ ++ ++void au_xigen_inc(struct inode *inode) ++{ ++ loff_t pos; ++ ssize_t sz; ++ __u32 igen; ++ struct super_block *sb; ++ struct au_sbinfo *sbinfo; ++ ++ sb = inode->i_sb; ++ AuDebugOn(!au_opt_test(au_mntflags(sb), XINO)); ++ ++ sbinfo = au_sbi(sb); ++ pos = inode->i_ino; ++ pos *= sizeof(igen); ++ igen = inode->i_generation + 1; ++ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xigen, &igen, ++ sizeof(igen), &pos); ++ if (sz == sizeof(igen)) ++ return; /* success */ ++ ++ if (unlikely(sz >= 0)) ++ AuIOErr("xigen error (%zd)\n", sz); ++} ++ ++int au_xigen_new(struct inode *inode) ++{ ++ int err; ++ loff_t pos; ++ ssize_t sz; ++ struct super_block *sb; ++ struct au_sbinfo *sbinfo; ++ struct file *file; ++ ++ err = 0; ++ /* todo: dirty, at mount time */ ++ if (inode->i_ino == AUFS_ROOT_INO) ++ goto out; ++ sb = inode->i_sb; ++ SiMustAnyLock(sb); ++ if (unlikely(!au_opt_test(au_mntflags(sb), XINO))) ++ goto out; ++ ++ err = -EFBIG; ++ pos = inode->i_ino; ++ if (unlikely(au_loff_max / sizeof(inode->i_generation) - 1 < pos)) { ++ AuIOErr1("too large i%lld\n", pos); ++ goto out; ++ } ++ pos *= sizeof(inode->i_generation); ++ ++ err = 0; ++ sbinfo = au_sbi(sb); ++ file = sbinfo->si_xigen; ++ BUG_ON(!file); ++ ++ if (vfsub_f_size_read(file) ++ < pos + sizeof(inode->i_generation)) { ++ inode->i_generation = atomic_inc_return(&sbinfo->si_xigen_next); ++ sz = xino_fwrite(sbinfo->si_xwrite, file, &inode->i_generation, ++ sizeof(inode->i_generation), &pos); ++ } else ++ sz = xino_fread(sbinfo->si_xread, file, &inode->i_generation, ++ sizeof(inode->i_generation), &pos); ++ if (sz == sizeof(inode->i_generation)) ++ goto out; /* success */ ++ ++ err = sz; ++ if (unlikely(sz >= 0)) { ++ err = -EIO; ++ AuIOErr("xigen error (%zd)\n", sz); ++ } ++ ++out: ++ return err; ++} ++ ++int au_xigen_set(struct super_block *sb, struct path *path) ++{ ++ int err; ++ struct au_sbinfo *sbinfo; ++ struct file *file; ++ ++ SiMustWriteLock(sb); ++ ++ sbinfo = au_sbi(sb); ++ file = au_xino_create2(sb, path, sbinfo->si_xigen); ++ err = PTR_ERR(file); ++ if (IS_ERR(file)) ++ goto out; ++ err = 0; ++ if (sbinfo->si_xigen) ++ fput(sbinfo->si_xigen); ++ sbinfo->si_xigen = file; ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++void au_xigen_clr(struct super_block *sb) ++{ ++ struct au_sbinfo *sbinfo; ++ ++ SiMustWriteLock(sb); ++ ++ sbinfo = au_sbi(sb); ++ if (sbinfo->si_xigen) { ++ fput(sbinfo->si_xigen); ++ sbinfo->si_xigen = NULL; ++ } ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static struct dentry *decode_by_ino(struct super_block *sb, ino_t ino, ++ ino_t dir_ino) ++{ ++ struct dentry *dentry, *d; ++ struct inode *inode; ++ unsigned int sigen; ++ ++ dentry = NULL; ++ inode = ilookup(sb, ino); ++ if (!inode) ++ goto out; ++ ++ dentry = ERR_PTR(-ESTALE); ++ sigen = au_sigen(sb); ++ if (unlikely(au_is_bad_inode(inode) ++ || IS_DEADDIR(inode) ++ || sigen != au_iigen(inode, NULL))) ++ goto out_iput; ++ ++ dentry = NULL; ++ if (!dir_ino || S_ISDIR(inode->i_mode)) ++ dentry = d_find_alias(inode); ++ else { ++ spin_lock(&inode->i_lock); ++ hlist_for_each_entry(d, &inode->i_dentry, d_u.d_alias) { ++ spin_lock(&d->d_lock); ++ if (!au_test_anon(d) ++ && d_inode(d->d_parent)->i_ino == dir_ino) { ++ dentry = dget_dlock(d); ++ spin_unlock(&d->d_lock); ++ break; ++ } ++ spin_unlock(&d->d_lock); ++ } ++ spin_unlock(&inode->i_lock); ++ } ++ if (unlikely(dentry && au_digen_test(dentry, sigen))) { ++ /* need to refresh */ ++ dput(dentry); ++ dentry = NULL; ++ } ++ ++out_iput: ++ iput(inode); ++out: ++ AuTraceErrPtr(dentry); ++ return dentry; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* todo: dirty? */ ++/* if exportfs_decode_fh() passed vfsmount*, we could be happy */ ++ ++struct au_compare_mnt_args { ++ /* input */ ++ struct super_block *sb; ++ ++ /* output */ ++ struct vfsmount *mnt; ++}; ++ ++static int au_compare_mnt(struct vfsmount *mnt, void *arg) ++{ ++ struct au_compare_mnt_args *a = arg; ++ ++ if (mnt->mnt_sb != a->sb) ++ return 0; ++ a->mnt = mntget(mnt); ++ return 1; ++} ++ ++static struct vfsmount *au_mnt_get(struct super_block *sb) ++{ ++ int err; ++ struct path root; ++ struct au_compare_mnt_args args = { ++ .sb = sb ++ }; ++ ++ get_fs_root(current->fs, &root); ++ rcu_read_lock(); ++ err = iterate_mounts(au_compare_mnt, &args, root.mnt); ++ rcu_read_unlock(); ++ path_put(&root); ++ AuDebugOn(!err); ++ AuDebugOn(!args.mnt); ++ return args.mnt; ++} ++ ++struct au_nfsd_si_lock { ++ unsigned int sigen; ++ aufs_bindex_t bindex, br_id; ++ unsigned char force_lock; ++}; ++ ++static int si_nfsd_read_lock(struct super_block *sb, ++ struct au_nfsd_si_lock *nsi_lock) ++{ ++ int err; ++ aufs_bindex_t bindex; ++ ++ si_read_lock(sb, AuLock_FLUSH); ++ ++ /* branch id may be wrapped around */ ++ err = 0; ++ bindex = au_br_index(sb, nsi_lock->br_id); ++ if (bindex >= 0 && nsi_lock->sigen + AUFS_BRANCH_MAX > au_sigen(sb)) ++ goto out; /* success */ ++ ++ err = -ESTALE; ++ bindex = -1; ++ if (!nsi_lock->force_lock) ++ si_read_unlock(sb); ++ ++out: ++ nsi_lock->bindex = bindex; ++ return err; ++} ++ ++struct find_name_by_ino { ++ struct dir_context ctx; ++ int called, found; ++ ino_t ino; ++ char *name; ++ int namelen; ++}; ++ ++static int ++find_name_by_ino(struct dir_context *ctx, const char *name, int namelen, ++ loff_t offset, u64 ino, unsigned int d_type) ++{ ++ struct find_name_by_ino *a = container_of(ctx, struct find_name_by_ino, ++ ctx); ++ ++ a->called++; ++ if (a->ino != ino) ++ return 0; ++ ++ memcpy(a->name, name, namelen); ++ a->namelen = namelen; ++ a->found = 1; ++ return 1; ++} ++ ++static struct dentry *au_lkup_by_ino(struct path *path, ino_t ino, ++ struct au_nfsd_si_lock *nsi_lock) ++{ ++ struct dentry *dentry, *parent; ++ struct file *file; ++ struct inode *dir; ++ struct find_name_by_ino arg = { ++ .ctx = { ++ .actor = find_name_by_ino ++ } ++ }; ++ int err; ++ ++ parent = path->dentry; ++ if (nsi_lock) ++ si_read_unlock(parent->d_sb); ++ file = vfsub_dentry_open(path, au_dir_roflags); ++ dentry = (void *)file; ++ if (IS_ERR(file)) ++ goto out; ++ ++ dentry = ERR_PTR(-ENOMEM); ++ arg.name = (void *)__get_free_page(GFP_NOFS); ++ if (unlikely(!arg.name)) ++ goto out_file; ++ arg.ino = ino; ++ arg.found = 0; ++ do { ++ arg.called = 0; ++ /* smp_mb(); */ ++ err = vfsub_iterate_dir(file, &arg.ctx); ++ } while (!err && !arg.found && arg.called); ++ dentry = ERR_PTR(err); ++ if (unlikely(err)) ++ goto out_name; ++ /* instead of ENOENT */ ++ dentry = ERR_PTR(-ESTALE); ++ if (!arg.found) ++ goto out_name; ++ ++ /* do not call vfsub_lkup_one() */ ++ dir = d_inode(parent); ++ dentry = vfsub_lookup_one_len_unlocked(arg.name, parent, arg.namelen); ++ AuTraceErrPtr(dentry); ++ if (IS_ERR(dentry)) ++ goto out_name; ++ AuDebugOn(au_test_anon(dentry)); ++ if (unlikely(d_really_is_negative(dentry))) { ++ dput(dentry); ++ dentry = ERR_PTR(-ENOENT); ++ } ++ ++out_name: ++ free_page((unsigned long)arg.name); ++out_file: ++ fput(file); ++out: ++ if (unlikely(nsi_lock ++ && si_nfsd_read_lock(parent->d_sb, nsi_lock) < 0)) ++ if (!IS_ERR(dentry)) { ++ dput(dentry); ++ dentry = ERR_PTR(-ESTALE); ++ } ++ AuTraceErrPtr(dentry); ++ return dentry; ++} ++ ++static struct dentry *decode_by_dir_ino(struct super_block *sb, ino_t ino, ++ ino_t dir_ino, ++ struct au_nfsd_si_lock *nsi_lock) ++{ ++ struct dentry *dentry; ++ struct path path; ++ ++ if (dir_ino != AUFS_ROOT_INO) { ++ path.dentry = decode_by_ino(sb, dir_ino, 0); ++ dentry = path.dentry; ++ if (!path.dentry || IS_ERR(path.dentry)) ++ goto out; ++ AuDebugOn(au_test_anon(path.dentry)); ++ } else ++ path.dentry = dget(sb->s_root); ++ ++ path.mnt = au_mnt_get(sb); ++ dentry = au_lkup_by_ino(&path, ino, nsi_lock); ++ path_put(&path); ++ ++out: ++ AuTraceErrPtr(dentry); ++ return dentry; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int h_acceptable(void *expv, struct dentry *dentry) ++{ ++ return 1; ++} ++ ++static char *au_build_path(struct dentry *h_parent, struct path *h_rootpath, ++ char *buf, int len, struct super_block *sb) ++{ ++ char *p; ++ int n; ++ struct path path; ++ ++ p = d_path(h_rootpath, buf, len); ++ if (IS_ERR(p)) ++ goto out; ++ n = strlen(p); ++ ++ path.mnt = h_rootpath->mnt; ++ path.dentry = h_parent; ++ p = d_path(&path, buf, len); ++ if (IS_ERR(p)) ++ goto out; ++ if (n != 1) ++ p += n; ++ ++ path.mnt = au_mnt_get(sb); ++ path.dentry = sb->s_root; ++ p = d_path(&path, buf, len - strlen(p)); ++ mntput(path.mnt); ++ if (IS_ERR(p)) ++ goto out; ++ if (n != 1) ++ p[strlen(p)] = '/'; ++ ++out: ++ AuTraceErrPtr(p); ++ return p; ++} ++ ++static ++struct dentry *decode_by_path(struct super_block *sb, ino_t ino, __u32 *fh, ++ int fh_len, struct au_nfsd_si_lock *nsi_lock) ++{ ++ struct dentry *dentry, *h_parent, *root; ++ struct super_block *h_sb; ++ char *pathname, *p; ++ struct vfsmount *h_mnt; ++ struct au_branch *br; ++ int err; ++ struct path path; ++ ++ br = au_sbr(sb, nsi_lock->bindex); ++ h_mnt = au_br_mnt(br); ++ h_sb = h_mnt->mnt_sb; ++ /* todo: call lower fh_to_dentry()? fh_to_parent()? */ ++ lockdep_off(); ++ h_parent = exportfs_decode_fh(h_mnt, (void *)(fh + Fh_tail), ++ fh_len - Fh_tail, fh[Fh_h_type], ++ h_acceptable, /*context*/NULL); ++ lockdep_on(); ++ dentry = h_parent; ++ if (unlikely(!h_parent || IS_ERR(h_parent))) { ++ AuWarn1("%s decode_fh failed, %ld\n", ++ au_sbtype(h_sb), PTR_ERR(h_parent)); ++ goto out; ++ } ++ dentry = NULL; ++ if (unlikely(au_test_anon(h_parent))) { ++ AuWarn1("%s decode_fh returned a disconnected dentry\n", ++ au_sbtype(h_sb)); ++ goto out_h_parent; ++ } ++ ++ dentry = ERR_PTR(-ENOMEM); ++ pathname = (void *)__get_free_page(GFP_NOFS); ++ if (unlikely(!pathname)) ++ goto out_h_parent; ++ ++ root = sb->s_root; ++ path.mnt = h_mnt; ++ di_read_lock_parent(root, !AuLock_IR); ++ path.dentry = au_h_dptr(root, nsi_lock->bindex); ++ di_read_unlock(root, !AuLock_IR); ++ p = au_build_path(h_parent, &path, pathname, PAGE_SIZE, sb); ++ dentry = (void *)p; ++ if (IS_ERR(p)) ++ goto out_pathname; ++ ++ si_read_unlock(sb); ++ err = vfsub_kern_path(p, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path); ++ dentry = ERR_PTR(err); ++ if (unlikely(err)) ++ goto out_relock; ++ ++ dentry = ERR_PTR(-ENOENT); ++ AuDebugOn(au_test_anon(path.dentry)); ++ if (unlikely(d_really_is_negative(path.dentry))) ++ goto out_path; ++ ++ if (ino != d_inode(path.dentry)->i_ino) ++ dentry = au_lkup_by_ino(&path, ino, /*nsi_lock*/NULL); ++ else ++ dentry = dget(path.dentry); ++ ++out_path: ++ path_put(&path); ++out_relock: ++ if (unlikely(si_nfsd_read_lock(sb, nsi_lock) < 0)) ++ if (!IS_ERR(dentry)) { ++ dput(dentry); ++ dentry = ERR_PTR(-ESTALE); ++ } ++out_pathname: ++ free_page((unsigned long)pathname); ++out_h_parent: ++ dput(h_parent); ++out: ++ AuTraceErrPtr(dentry); ++ return dentry; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static struct dentry * ++aufs_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len, ++ int fh_type) ++{ ++ struct dentry *dentry; ++ __u32 *fh = fid->raw; ++ struct au_branch *br; ++ ino_t ino, dir_ino; ++ struct au_nfsd_si_lock nsi_lock = { ++ .force_lock = 0 ++ }; ++ ++ dentry = ERR_PTR(-ESTALE); ++ /* it should never happen, but the file handle is unreliable */ ++ if (unlikely(fh_len < Fh_tail)) ++ goto out; ++ nsi_lock.sigen = fh[Fh_sigen]; ++ nsi_lock.br_id = fh[Fh_br_id]; ++ ++ /* branch id may be wrapped around */ ++ br = NULL; ++ if (unlikely(si_nfsd_read_lock(sb, &nsi_lock))) ++ goto out; ++ nsi_lock.force_lock = 1; ++ ++ /* is this inode still cached? */ ++ ino = decode_ino(fh + Fh_ino); ++ /* it should never happen */ ++ if (unlikely(ino == AUFS_ROOT_INO)) ++ goto out_unlock; ++ ++ dir_ino = decode_ino(fh + Fh_dir_ino); ++ dentry = decode_by_ino(sb, ino, dir_ino); ++ if (IS_ERR(dentry)) ++ goto out_unlock; ++ if (dentry) ++ goto accept; ++ ++ /* is the parent dir cached? */ ++ br = au_sbr(sb, nsi_lock.bindex); ++ au_lcnt_inc(&br->br_nfiles); ++ dentry = decode_by_dir_ino(sb, ino, dir_ino, &nsi_lock); ++ if (IS_ERR(dentry)) ++ goto out_unlock; ++ if (dentry) ++ goto accept; ++ ++ /* lookup path */ ++ dentry = decode_by_path(sb, ino, fh, fh_len, &nsi_lock); ++ if (IS_ERR(dentry)) ++ goto out_unlock; ++ if (unlikely(!dentry)) ++ /* todo?: make it ESTALE */ ++ goto out_unlock; ++ ++accept: ++ if (!au_digen_test(dentry, au_sigen(sb)) ++ && d_inode(dentry)->i_generation == fh[Fh_igen]) ++ goto out_unlock; /* success */ ++ ++ dput(dentry); ++ dentry = ERR_PTR(-ESTALE); ++out_unlock: ++ if (br) ++ au_lcnt_dec(&br->br_nfiles); ++ si_read_unlock(sb); ++out: ++ AuTraceErrPtr(dentry); ++ return dentry; ++} ++ ++#if 0 /* reserved for future use */ ++/* support subtreecheck option */ ++static struct dentry *aufs_fh_to_parent(struct super_block *sb, struct fid *fid, ++ int fh_len, int fh_type) ++{ ++ struct dentry *parent; ++ __u32 *fh = fid->raw; ++ ino_t dir_ino; ++ ++ dir_ino = decode_ino(fh + Fh_dir_ino); ++ parent = decode_by_ino(sb, dir_ino, 0); ++ if (IS_ERR(parent)) ++ goto out; ++ if (!parent) ++ parent = decode_by_path(sb, au_br_index(sb, fh[Fh_br_id]), ++ dir_ino, fh, fh_len); ++ ++out: ++ AuTraceErrPtr(parent); ++ return parent; ++} ++#endif ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int aufs_encode_fh(struct inode *inode, __u32 *fh, int *max_len, ++ struct inode *dir) ++{ ++ int err; ++ aufs_bindex_t bindex; ++ struct super_block *sb, *h_sb; ++ struct dentry *dentry, *parent, *h_parent; ++ struct inode *h_dir; ++ struct au_branch *br; ++ ++ err = -ENOSPC; ++ if (unlikely(*max_len <= Fh_tail)) { ++ AuWarn1("NFSv2 client (max_len %d)?\n", *max_len); ++ goto out; ++ } ++ ++ err = FILEID_ROOT; ++ if (inode->i_ino == AUFS_ROOT_INO) { ++ AuDebugOn(inode->i_ino != AUFS_ROOT_INO); ++ goto out; ++ } ++ ++ h_parent = NULL; ++ sb = inode->i_sb; ++ err = si_read_lock(sb, AuLock_FLUSH); ++ if (unlikely(err)) ++ goto out; ++ ++#ifdef CONFIG_AUFS_DEBUG ++ if (unlikely(!au_opt_test(au_mntflags(sb), XINO))) ++ AuWarn1("NFS-exporting requires xino\n"); ++#endif ++ err = -EIO; ++ parent = NULL; ++ ii_read_lock_child(inode); ++ bindex = au_ibtop(inode); ++ if (!dir) { ++ dentry = d_find_any_alias(inode); ++ if (unlikely(!dentry)) ++ goto out_unlock; ++ AuDebugOn(au_test_anon(dentry)); ++ parent = dget_parent(dentry); ++ dput(dentry); ++ if (unlikely(!parent)) ++ goto out_unlock; ++ if (d_really_is_positive(parent)) ++ dir = d_inode(parent); ++ } ++ ++ ii_read_lock_parent(dir); ++ h_dir = au_h_iptr(dir, bindex); ++ ii_read_unlock(dir); ++ if (unlikely(!h_dir)) ++ goto out_parent; ++ h_parent = d_find_any_alias(h_dir); ++ if (unlikely(!h_parent)) ++ goto out_hparent; ++ ++ err = -EPERM; ++ br = au_sbr(sb, bindex); ++ h_sb = au_br_sb(br); ++ if (unlikely(!h_sb->s_export_op)) { ++ AuErr1("%s branch is not exportable\n", au_sbtype(h_sb)); ++ goto out_hparent; ++ } ++ ++ fh[Fh_br_id] = br->br_id; ++ fh[Fh_sigen] = au_sigen(sb); ++ encode_ino(fh + Fh_ino, inode->i_ino); ++ encode_ino(fh + Fh_dir_ino, dir->i_ino); ++ fh[Fh_igen] = inode->i_generation; ++ ++ *max_len -= Fh_tail; ++ fh[Fh_h_type] = exportfs_encode_fh(h_parent, (void *)(fh + Fh_tail), ++ max_len, ++ /*connectable or subtreecheck*/0); ++ err = fh[Fh_h_type]; ++ *max_len += Fh_tail; ++ /* todo: macros? */ ++ if (err != FILEID_INVALID) ++ err = 99; ++ else ++ AuWarn1("%s encode_fh failed\n", au_sbtype(h_sb)); ++ ++out_hparent: ++ dput(h_parent); ++out_parent: ++ dput(parent); ++out_unlock: ++ ii_read_unlock(inode); ++ si_read_unlock(sb); ++out: ++ if (unlikely(err < 0)) ++ err = FILEID_INVALID; ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int aufs_commit_metadata(struct inode *inode) ++{ ++ int err; ++ aufs_bindex_t bindex; ++ struct super_block *sb; ++ struct inode *h_inode; ++ int (*f)(struct inode *inode); ++ ++ sb = inode->i_sb; ++ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); ++ ii_write_lock_child(inode); ++ bindex = au_ibtop(inode); ++ AuDebugOn(bindex < 0); ++ h_inode = au_h_iptr(inode, bindex); ++ ++ f = h_inode->i_sb->s_export_op->commit_metadata; ++ if (f) ++ err = f(h_inode); ++ else { ++ struct writeback_control wbc = { ++ .sync_mode = WB_SYNC_ALL, ++ .nr_to_write = 0 /* metadata only */ ++ }; ++ ++ err = sync_inode(h_inode, &wbc); ++ } ++ ++ au_cpup_attr_timesizes(inode); ++ ii_write_unlock(inode); ++ si_read_unlock(sb); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static struct export_operations aufs_export_op = { ++ .fh_to_dentry = aufs_fh_to_dentry, ++ /* .fh_to_parent = aufs_fh_to_parent, */ ++ .encode_fh = aufs_encode_fh, ++ .commit_metadata = aufs_commit_metadata ++}; ++ ++void au_export_init(struct super_block *sb) ++{ ++ struct au_sbinfo *sbinfo; ++ __u32 u; ++ ++ BUILD_BUG_ON_MSG(IS_BUILTIN(CONFIG_AUFS_FS) ++ && IS_MODULE(CONFIG_EXPORTFS), ++ AUFS_NAME ": unsupported configuration " ++ "CONFIG_EXPORTFS=m and CONFIG_AUFS_FS=y"); ++ ++ sb->s_export_op = &aufs_export_op; ++ sbinfo = au_sbi(sb); ++ sbinfo->si_xigen = NULL; ++ get_random_bytes(&u, sizeof(u)); ++ BUILD_BUG_ON(sizeof(u) != sizeof(int)); ++ atomic_set(&sbinfo->si_xigen_next, u); ++} +diff -Nurp linux-5.4/fs/aufs/fhsm.c linux-5.4-aufs/fs/aufs/fhsm.c +--- linux-5.4/fs/aufs/fhsm.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/fhsm.c 2019-11-28 01:25:59.064925618 +0200 +@@ -0,0 +1,413 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2011-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * File-based Hierarchy Storage Management ++ */ ++ ++#include ++#include ++#include ++#include ++#include "aufs.h" ++ ++static aufs_bindex_t au_fhsm_bottom(struct super_block *sb) ++{ ++ struct au_sbinfo *sbinfo; ++ struct au_fhsm *fhsm; ++ ++ SiMustAnyLock(sb); ++ ++ sbinfo = au_sbi(sb); ++ fhsm = &sbinfo->si_fhsm; ++ AuDebugOn(!fhsm); ++ return fhsm->fhsm_bottom; ++} ++ ++void au_fhsm_set_bottom(struct super_block *sb, aufs_bindex_t bindex) ++{ ++ struct au_sbinfo *sbinfo; ++ struct au_fhsm *fhsm; ++ ++ SiMustWriteLock(sb); ++ ++ sbinfo = au_sbi(sb); ++ fhsm = &sbinfo->si_fhsm; ++ AuDebugOn(!fhsm); ++ fhsm->fhsm_bottom = bindex; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int au_fhsm_test_jiffy(struct au_sbinfo *sbinfo, struct au_branch *br) ++{ ++ struct au_br_fhsm *bf; ++ ++ bf = br->br_fhsm; ++ MtxMustLock(&bf->bf_lock); ++ ++ return !bf->bf_readable ++ || time_after(jiffies, ++ bf->bf_jiffy + sbinfo->si_fhsm.fhsm_expire); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static void au_fhsm_notify(struct super_block *sb, int val) ++{ ++ struct au_sbinfo *sbinfo; ++ struct au_fhsm *fhsm; ++ ++ SiMustAnyLock(sb); ++ ++ sbinfo = au_sbi(sb); ++ fhsm = &sbinfo->si_fhsm; ++ if (au_fhsm_pid(fhsm) ++ && atomic_read(&fhsm->fhsm_readable) != -1) { ++ atomic_set(&fhsm->fhsm_readable, val); ++ if (val) ++ wake_up(&fhsm->fhsm_wqh); ++ } ++} ++ ++static int au_fhsm_stfs(struct super_block *sb, aufs_bindex_t bindex, ++ struct aufs_stfs *rstfs, int do_lock, int do_notify) ++{ ++ int err; ++ struct au_branch *br; ++ struct au_br_fhsm *bf; ++ ++ br = au_sbr(sb, bindex); ++ AuDebugOn(au_br_rdonly(br)); ++ bf = br->br_fhsm; ++ AuDebugOn(!bf); ++ ++ if (do_lock) ++ mutex_lock(&bf->bf_lock); ++ else ++ MtxMustLock(&bf->bf_lock); ++ ++ /* sb->s_root for NFS is unreliable */ ++ err = au_br_stfs(br, &bf->bf_stfs); ++ if (unlikely(err)) { ++ AuErr1("FHSM failed (%d), b%d, ignored.\n", bindex, err); ++ goto out; ++ } ++ ++ bf->bf_jiffy = jiffies; ++ bf->bf_readable = 1; ++ if (do_notify) ++ au_fhsm_notify(sb, /*val*/1); ++ if (rstfs) ++ *rstfs = bf->bf_stfs; ++ ++out: ++ if (do_lock) ++ mutex_unlock(&bf->bf_lock); ++ au_fhsm_notify(sb, /*val*/1); ++ ++ return err; ++} ++ ++void au_fhsm_wrote(struct super_block *sb, aufs_bindex_t bindex, int force) ++{ ++ int err; ++ struct au_sbinfo *sbinfo; ++ struct au_fhsm *fhsm; ++ struct au_branch *br; ++ struct au_br_fhsm *bf; ++ ++ AuDbg("b%d, force %d\n", bindex, force); ++ SiMustAnyLock(sb); ++ ++ sbinfo = au_sbi(sb); ++ fhsm = &sbinfo->si_fhsm; ++ if (!au_ftest_si(sbinfo, FHSM) ++ || fhsm->fhsm_bottom == bindex) ++ return; ++ ++ br = au_sbr(sb, bindex); ++ bf = br->br_fhsm; ++ AuDebugOn(!bf); ++ mutex_lock(&bf->bf_lock); ++ if (force ++ || au_fhsm_pid(fhsm) ++ || au_fhsm_test_jiffy(sbinfo, br)) ++ err = au_fhsm_stfs(sb, bindex, /*rstfs*/NULL, /*do_lock*/0, ++ /*do_notify*/1); ++ mutex_unlock(&bf->bf_lock); ++} ++ ++void au_fhsm_wrote_all(struct super_block *sb, int force) ++{ ++ aufs_bindex_t bindex, bbot; ++ struct au_branch *br; ++ ++ /* exclude the bottom */ ++ bbot = au_fhsm_bottom(sb); ++ for (bindex = 0; bindex < bbot; bindex++) { ++ br = au_sbr(sb, bindex); ++ if (au_br_fhsm(br->br_perm)) ++ au_fhsm_wrote(sb, bindex, force); ++ } ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static __poll_t au_fhsm_poll(struct file *file, struct poll_table_struct *wait) ++{ ++ __poll_t mask; ++ struct au_sbinfo *sbinfo; ++ struct au_fhsm *fhsm; ++ ++ mask = 0; ++ sbinfo = file->private_data; ++ fhsm = &sbinfo->si_fhsm; ++ poll_wait(file, &fhsm->fhsm_wqh, wait); ++ if (atomic_read(&fhsm->fhsm_readable)) ++ mask = EPOLLIN /* | EPOLLRDNORM */; ++ ++ if (!mask) ++ AuDbg("mask 0x%x\n", mask); ++ return mask; ++} ++ ++static int au_fhsm_do_read_one(struct aufs_stbr __user *stbr, ++ struct aufs_stfs *stfs, __s16 brid) ++{ ++ int err; ++ ++ err = copy_to_user(&stbr->stfs, stfs, sizeof(*stfs)); ++ if (!err) ++ err = __put_user(brid, &stbr->brid); ++ if (unlikely(err)) ++ err = -EFAULT; ++ ++ return err; ++} ++ ++static ssize_t au_fhsm_do_read(struct super_block *sb, ++ struct aufs_stbr __user *stbr, size_t count) ++{ ++ ssize_t err; ++ int nstbr; ++ aufs_bindex_t bindex, bbot; ++ struct au_branch *br; ++ struct au_br_fhsm *bf; ++ ++ /* except the bottom branch */ ++ err = 0; ++ nstbr = 0; ++ bbot = au_fhsm_bottom(sb); ++ for (bindex = 0; !err && bindex < bbot; bindex++) { ++ br = au_sbr(sb, bindex); ++ if (!au_br_fhsm(br->br_perm)) ++ continue; ++ ++ bf = br->br_fhsm; ++ mutex_lock(&bf->bf_lock); ++ if (bf->bf_readable) { ++ err = -EFAULT; ++ if (count >= sizeof(*stbr)) ++ err = au_fhsm_do_read_one(stbr++, &bf->bf_stfs, ++ br->br_id); ++ if (!err) { ++ bf->bf_readable = 0; ++ count -= sizeof(*stbr); ++ nstbr++; ++ } ++ } ++ mutex_unlock(&bf->bf_lock); ++ } ++ if (!err) ++ err = sizeof(*stbr) * nstbr; ++ ++ return err; ++} ++ ++static ssize_t au_fhsm_read(struct file *file, char __user *buf, size_t count, ++ loff_t *pos) ++{ ++ ssize_t err; ++ int readable; ++ aufs_bindex_t nfhsm, bindex, bbot; ++ struct au_sbinfo *sbinfo; ++ struct au_fhsm *fhsm; ++ struct au_branch *br; ++ struct super_block *sb; ++ ++ err = 0; ++ sbinfo = file->private_data; ++ fhsm = &sbinfo->si_fhsm; ++need_data: ++ spin_lock_irq(&fhsm->fhsm_wqh.lock); ++ if (!atomic_read(&fhsm->fhsm_readable)) { ++ if (vfsub_file_flags(file) & O_NONBLOCK) ++ err = -EAGAIN; ++ else ++ err = wait_event_interruptible_locked_irq ++ (fhsm->fhsm_wqh, ++ atomic_read(&fhsm->fhsm_readable)); ++ } ++ spin_unlock_irq(&fhsm->fhsm_wqh.lock); ++ if (unlikely(err)) ++ goto out; ++ ++ /* sb may already be dead */ ++ au_rw_read_lock(&sbinfo->si_rwsem); ++ readable = atomic_read(&fhsm->fhsm_readable); ++ if (readable > 0) { ++ sb = sbinfo->si_sb; ++ AuDebugOn(!sb); ++ /* exclude the bottom branch */ ++ nfhsm = 0; ++ bbot = au_fhsm_bottom(sb); ++ for (bindex = 0; bindex < bbot; bindex++) { ++ br = au_sbr(sb, bindex); ++ if (au_br_fhsm(br->br_perm)) ++ nfhsm++; ++ } ++ err = -EMSGSIZE; ++ if (nfhsm * sizeof(struct aufs_stbr) <= count) { ++ atomic_set(&fhsm->fhsm_readable, 0); ++ err = au_fhsm_do_read(sbinfo->si_sb, (void __user *)buf, ++ count); ++ } ++ } ++ au_rw_read_unlock(&sbinfo->si_rwsem); ++ if (!readable) ++ goto need_data; ++ ++out: ++ return err; ++} ++ ++static int au_fhsm_release(struct inode *inode, struct file *file) ++{ ++ struct au_sbinfo *sbinfo; ++ struct au_fhsm *fhsm; ++ ++ /* sb may already be dead */ ++ sbinfo = file->private_data; ++ fhsm = &sbinfo->si_fhsm; ++ spin_lock(&fhsm->fhsm_spin); ++ fhsm->fhsm_pid = 0; ++ spin_unlock(&fhsm->fhsm_spin); ++ kobject_put(&sbinfo->si_kobj); ++ ++ return 0; ++} ++ ++static const struct file_operations au_fhsm_fops = { ++ .owner = THIS_MODULE, ++ .llseek = noop_llseek, ++ .read = au_fhsm_read, ++ .poll = au_fhsm_poll, ++ .release = au_fhsm_release ++}; ++ ++int au_fhsm_fd(struct super_block *sb, int oflags) ++{ ++ int err, fd; ++ struct au_sbinfo *sbinfo; ++ struct au_fhsm *fhsm; ++ ++ err = -EPERM; ++ if (unlikely(!capable(CAP_SYS_ADMIN))) ++ goto out; ++ ++ err = -EINVAL; ++ if (unlikely(oflags & ~(O_CLOEXEC | O_NONBLOCK))) ++ goto out; ++ ++ err = 0; ++ sbinfo = au_sbi(sb); ++ fhsm = &sbinfo->si_fhsm; ++ spin_lock(&fhsm->fhsm_spin); ++ if (!fhsm->fhsm_pid) ++ fhsm->fhsm_pid = current->pid; ++ else ++ err = -EBUSY; ++ spin_unlock(&fhsm->fhsm_spin); ++ if (unlikely(err)) ++ goto out; ++ ++ oflags |= O_RDONLY; ++ /* oflags |= FMODE_NONOTIFY; */ ++ fd = anon_inode_getfd("[aufs_fhsm]", &au_fhsm_fops, sbinfo, oflags); ++ err = fd; ++ if (unlikely(fd < 0)) ++ goto out_pid; ++ ++ /* succeed regardless 'fhsm' status */ ++ kobject_get(&sbinfo->si_kobj); ++ si_noflush_read_lock(sb); ++ if (au_ftest_si(sbinfo, FHSM)) ++ au_fhsm_wrote_all(sb, /*force*/0); ++ si_read_unlock(sb); ++ goto out; /* success */ ++ ++out_pid: ++ spin_lock(&fhsm->fhsm_spin); ++ fhsm->fhsm_pid = 0; ++ spin_unlock(&fhsm->fhsm_spin); ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++int au_fhsm_br_alloc(struct au_branch *br) ++{ ++ int err; ++ ++ err = 0; ++ br->br_fhsm = kmalloc(sizeof(*br->br_fhsm), GFP_NOFS); ++ if (br->br_fhsm) ++ au_br_fhsm_init(br->br_fhsm); ++ else ++ err = -ENOMEM; ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++void au_fhsm_fin(struct super_block *sb) ++{ ++ au_fhsm_notify(sb, /*val*/-1); ++} ++ ++void au_fhsm_init(struct au_sbinfo *sbinfo) ++{ ++ struct au_fhsm *fhsm; ++ ++ fhsm = &sbinfo->si_fhsm; ++ spin_lock_init(&fhsm->fhsm_spin); ++ init_waitqueue_head(&fhsm->fhsm_wqh); ++ atomic_set(&fhsm->fhsm_readable, 0); ++ fhsm->fhsm_expire ++ = msecs_to_jiffies(AUFS_FHSM_CACHE_DEF_SEC * MSEC_PER_SEC); ++ fhsm->fhsm_bottom = -1; ++} ++ ++void au_fhsm_set(struct au_sbinfo *sbinfo, unsigned int sec) ++{ ++ sbinfo->si_fhsm.fhsm_expire ++ = msecs_to_jiffies(sec * MSEC_PER_SEC); ++} ++ ++void au_fhsm_show(struct seq_file *seq, struct au_sbinfo *sbinfo) ++{ ++ unsigned int u; ++ ++ if (!au_ftest_si(sbinfo, FHSM)) ++ return; ++ ++ u = jiffies_to_msecs(sbinfo->si_fhsm.fhsm_expire) / MSEC_PER_SEC; ++ if (u != AUFS_FHSM_CACHE_DEF_SEC) ++ seq_printf(seq, ",fhsm_sec=%u", u); ++} +diff -Nurp linux-5.4/fs/aufs/file.c linux-5.4-aufs/fs/aufs/file.c +--- linux-5.4/fs/aufs/file.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/file.c 2019-11-28 01:25:59.065925618 +0200 +@@ -0,0 +1,850 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * handling file/dir, and address_space operation ++ */ ++ ++#ifdef CONFIG_AUFS_DEBUG ++#include ++#endif ++#include ++#include "aufs.h" ++ ++/* drop flags for writing */ ++unsigned int au_file_roflags(unsigned int flags) ++{ ++ flags &= ~(O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_TRUNC); ++ flags |= O_RDONLY | O_NOATIME; ++ return flags; ++} ++ ++/* common functions to regular file and dir */ ++struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags, ++ struct file *file, int force_wr) ++{ ++ struct file *h_file; ++ struct dentry *h_dentry; ++ struct inode *h_inode; ++ struct super_block *sb; ++ struct au_branch *br; ++ struct path h_path; ++ int err; ++ ++ /* a race condition can happen between open and unlink/rmdir */ ++ h_file = ERR_PTR(-ENOENT); ++ h_dentry = au_h_dptr(dentry, bindex); ++ if (au_test_nfsd() && (!h_dentry || d_is_negative(h_dentry))) ++ goto out; ++ h_inode = d_inode(h_dentry); ++ spin_lock(&h_dentry->d_lock); ++ err = (!d_unhashed(dentry) && d_unlinked(h_dentry)) ++ /* || !d_inode(dentry)->i_nlink */ ++ ; ++ spin_unlock(&h_dentry->d_lock); ++ if (unlikely(err)) ++ goto out; ++ ++ sb = dentry->d_sb; ++ br = au_sbr(sb, bindex); ++ err = au_br_test_oflag(flags, br); ++ h_file = ERR_PTR(err); ++ if (unlikely(err)) ++ goto out; ++ ++ /* drop flags for writing */ ++ if (au_test_ro(sb, bindex, d_inode(dentry))) { ++ if (force_wr && !(flags & O_WRONLY)) ++ force_wr = 0; ++ flags = au_file_roflags(flags); ++ if (force_wr) { ++ h_file = ERR_PTR(-EROFS); ++ flags = au_file_roflags(flags); ++ if (unlikely(vfsub_native_ro(h_inode) ++ || IS_APPEND(h_inode))) ++ goto out; ++ flags &= ~O_ACCMODE; ++ flags |= O_WRONLY; ++ } ++ } ++ flags &= ~O_CREAT; ++ au_lcnt_inc(&br->br_nfiles); ++ h_path.dentry = h_dentry; ++ h_path.mnt = au_br_mnt(br); ++ h_file = vfsub_dentry_open(&h_path, flags); ++ if (IS_ERR(h_file)) ++ goto out_br; ++ ++ if (flags & __FMODE_EXEC) { ++ err = deny_write_access(h_file); ++ if (unlikely(err)) { ++ fput(h_file); ++ h_file = ERR_PTR(err); ++ goto out_br; ++ } ++ } ++ fsnotify_open(h_file); ++ goto out; /* success */ ++ ++out_br: ++ au_lcnt_dec(&br->br_nfiles); ++out: ++ return h_file; ++} ++ ++static int au_cmoo(struct dentry *dentry) ++{ ++ int err, cmoo, matched; ++ unsigned int udba; ++ struct path h_path; ++ struct au_pin pin; ++ struct au_cp_generic cpg = { ++ .dentry = dentry, ++ .bdst = -1, ++ .bsrc = -1, ++ .len = -1, ++ .pin = &pin, ++ .flags = AuCpup_DTIME | AuCpup_HOPEN ++ }; ++ struct inode *delegated; ++ struct super_block *sb; ++ struct au_sbinfo *sbinfo; ++ struct au_fhsm *fhsm; ++ pid_t pid; ++ struct au_branch *br; ++ struct dentry *parent; ++ struct au_hinode *hdir; ++ ++ DiMustWriteLock(dentry); ++ IiMustWriteLock(d_inode(dentry)); ++ ++ err = 0; ++ if (IS_ROOT(dentry)) ++ goto out; ++ cpg.bsrc = au_dbtop(dentry); ++ if (!cpg.bsrc) ++ goto out; ++ ++ sb = dentry->d_sb; ++ sbinfo = au_sbi(sb); ++ fhsm = &sbinfo->si_fhsm; ++ pid = au_fhsm_pid(fhsm); ++ rcu_read_lock(); ++ matched = (pid ++ && (current->pid == pid ++ || rcu_dereference(current->real_parent)->pid == pid)); ++ rcu_read_unlock(); ++ if (matched) ++ goto out; ++ ++ br = au_sbr(sb, cpg.bsrc); ++ cmoo = au_br_cmoo(br->br_perm); ++ if (!cmoo) ++ goto out; ++ if (!d_is_reg(dentry)) ++ cmoo &= AuBrAttr_COO_ALL; ++ if (!cmoo) ++ goto out; ++ ++ parent = dget_parent(dentry); ++ di_write_lock_parent(parent); ++ err = au_wbr_do_copyup_bu(dentry, cpg.bsrc - 1); ++ cpg.bdst = err; ++ if (unlikely(err < 0)) { ++ err = 0; /* there is no upper writable branch */ ++ goto out_dgrade; ++ } ++ AuDbg("bsrc %d, bdst %d\n", cpg.bsrc, cpg.bdst); ++ ++ /* do not respect the coo attrib for the target branch */ ++ err = au_cpup_dirs(dentry, cpg.bdst); ++ if (unlikely(err)) ++ goto out_dgrade; ++ ++ di_downgrade_lock(parent, AuLock_IR); ++ udba = au_opt_udba(sb); ++ err = au_pin(&pin, dentry, cpg.bdst, udba, ++ AuPin_DI_LOCKED | AuPin_MNT_WRITE); ++ if (unlikely(err)) ++ goto out_parent; ++ ++ err = au_sio_cpup_simple(&cpg); ++ au_unpin(&pin); ++ if (unlikely(err)) ++ goto out_parent; ++ if (!(cmoo & AuBrWAttr_MOO)) ++ goto out_parent; /* success */ ++ ++ err = au_pin(&pin, dentry, cpg.bsrc, udba, ++ AuPin_DI_LOCKED | AuPin_MNT_WRITE); ++ if (unlikely(err)) ++ goto out_parent; ++ ++ h_path.mnt = au_br_mnt(br); ++ h_path.dentry = au_h_dptr(dentry, cpg.bsrc); ++ hdir = au_hi(d_inode(parent), cpg.bsrc); ++ delegated = NULL; ++ err = vfsub_unlink(hdir->hi_inode, &h_path, &delegated, /*force*/1); ++ au_unpin(&pin); ++ /* todo: keep h_dentry or not? */ ++ if (unlikely(err == -EWOULDBLOCK)) { ++ pr_warn("cannot retry for NFSv4 delegation" ++ " for an internal unlink\n"); ++ iput(delegated); ++ } ++ if (unlikely(err)) { ++ pr_err("unlink %pd after coo failed (%d), ignored\n", ++ dentry, err); ++ err = 0; ++ } ++ goto out_parent; /* success */ ++ ++out_dgrade: ++ di_downgrade_lock(parent, AuLock_IR); ++out_parent: ++ di_read_unlock(parent, AuLock_IR); ++ dput(parent); ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++int au_do_open(struct file *file, struct au_do_open_args *args) ++{ ++ int err, aopen = args->aopen; ++ struct dentry *dentry; ++ struct au_finfo *finfo; ++ ++ if (!aopen) ++ err = au_finfo_init(file, args->fidir); ++ else { ++ lockdep_off(); ++ err = au_finfo_init(file, args->fidir); ++ lockdep_on(); ++ } ++ if (unlikely(err)) ++ goto out; ++ ++ dentry = file->f_path.dentry; ++ AuDebugOn(IS_ERR_OR_NULL(dentry)); ++ di_write_lock_child(dentry); ++ err = au_cmoo(dentry); ++ di_downgrade_lock(dentry, AuLock_IR); ++ if (!err) { ++ if (!aopen) ++ err = args->open(file, vfsub_file_flags(file), NULL); ++ else { ++ lockdep_off(); ++ err = args->open(file, vfsub_file_flags(file), ++ args->h_file); ++ lockdep_on(); ++ } ++ } ++ di_read_unlock(dentry, AuLock_IR); ++ ++ finfo = au_fi(file); ++ if (!err) { ++ finfo->fi_file = file; ++ au_hbl_add(&finfo->fi_hlist, ++ &au_sbi(file->f_path.dentry->d_sb)->si_files); ++ } ++ if (!aopen) ++ fi_write_unlock(file); ++ else { ++ lockdep_off(); ++ fi_write_unlock(file); ++ lockdep_on(); ++ } ++ if (unlikely(err)) { ++ finfo->fi_hdir = NULL; ++ au_finfo_fin(file); ++ } ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++int au_reopen_nondir(struct file *file) ++{ ++ int err; ++ aufs_bindex_t btop; ++ struct dentry *dentry; ++ struct au_branch *br; ++ struct file *h_file, *h_file_tmp; ++ ++ dentry = file->f_path.dentry; ++ btop = au_dbtop(dentry); ++ br = au_sbr(dentry->d_sb, btop); ++ h_file_tmp = NULL; ++ if (au_fbtop(file) == btop) { ++ h_file = au_hf_top(file); ++ if (file->f_mode == h_file->f_mode) ++ return 0; /* success */ ++ h_file_tmp = h_file; ++ get_file(h_file_tmp); ++ au_lcnt_inc(&br->br_nfiles); ++ au_set_h_fptr(file, btop, NULL); ++ } ++ AuDebugOn(au_fi(file)->fi_hdir); ++ /* ++ * it can happen ++ * file exists on both of rw and ro ++ * open --> dbtop and fbtop are both 0 ++ * prepend a branch as rw, "rw" become ro ++ * remove rw/file ++ * delete the top branch, "rw" becomes rw again ++ * --> dbtop is 1, fbtop is still 0 ++ * write --> fbtop is 0 but dbtop is 1 ++ */ ++ /* AuDebugOn(au_fbtop(file) < btop); */ ++ ++ h_file = au_h_open(dentry, btop, vfsub_file_flags(file) & ~O_TRUNC, ++ file, /*force_wr*/0); ++ err = PTR_ERR(h_file); ++ if (IS_ERR(h_file)) { ++ if (h_file_tmp) { ++ /* revert */ ++ au_set_h_fptr(file, btop, h_file_tmp); ++ h_file_tmp = NULL; ++ } ++ goto out; /* todo: close all? */ ++ } ++ ++ err = 0; ++ au_set_fbtop(file, btop); ++ au_set_h_fptr(file, btop, h_file); ++ au_update_figen(file); ++ /* todo: necessary? */ ++ /* file->f_ra = h_file->f_ra; */ ++ ++out: ++ if (h_file_tmp) { ++ fput(h_file_tmp); ++ au_lcnt_dec(&br->br_nfiles); ++ } ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int au_reopen_wh(struct file *file, aufs_bindex_t btgt, ++ struct dentry *hi_wh) ++{ ++ int err; ++ aufs_bindex_t btop; ++ struct au_dinfo *dinfo; ++ struct dentry *h_dentry; ++ struct au_hdentry *hdp; ++ ++ dinfo = au_di(file->f_path.dentry); ++ AuRwMustWriteLock(&dinfo->di_rwsem); ++ ++ btop = dinfo->di_btop; ++ dinfo->di_btop = btgt; ++ hdp = au_hdentry(dinfo, btgt); ++ h_dentry = hdp->hd_dentry; ++ hdp->hd_dentry = hi_wh; ++ err = au_reopen_nondir(file); ++ hdp->hd_dentry = h_dentry; ++ dinfo->di_btop = btop; ++ ++ return err; ++} ++ ++static int au_ready_to_write_wh(struct file *file, loff_t len, ++ aufs_bindex_t bcpup, struct au_pin *pin) ++{ ++ int err; ++ struct inode *inode, *h_inode; ++ struct dentry *h_dentry, *hi_wh; ++ struct au_cp_generic cpg = { ++ .dentry = file->f_path.dentry, ++ .bdst = bcpup, ++ .bsrc = -1, ++ .len = len, ++ .pin = pin ++ }; ++ ++ au_update_dbtop(cpg.dentry); ++ inode = d_inode(cpg.dentry); ++ h_inode = NULL; ++ if (au_dbtop(cpg.dentry) <= bcpup ++ && au_dbbot(cpg.dentry) >= bcpup) { ++ h_dentry = au_h_dptr(cpg.dentry, bcpup); ++ if (h_dentry && d_is_positive(h_dentry)) ++ h_inode = d_inode(h_dentry); ++ } ++ hi_wh = au_hi_wh(inode, bcpup); ++ if (!hi_wh && !h_inode) ++ err = au_sio_cpup_wh(&cpg, file); ++ else ++ /* already copied-up after unlink */ ++ err = au_reopen_wh(file, bcpup, hi_wh); ++ ++ if (!err ++ && (inode->i_nlink > 1 ++ || (inode->i_state & I_LINKABLE)) ++ && au_opt_test(au_mntflags(cpg.dentry->d_sb), PLINK)) ++ au_plink_append(inode, bcpup, au_h_dptr(cpg.dentry, bcpup)); ++ ++ return err; ++} ++ ++/* ++ * prepare the @file for writing. ++ */ ++int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin) ++{ ++ int err; ++ aufs_bindex_t dbtop; ++ struct dentry *parent; ++ struct inode *inode; ++ struct super_block *sb; ++ struct file *h_file; ++ struct au_cp_generic cpg = { ++ .dentry = file->f_path.dentry, ++ .bdst = -1, ++ .bsrc = -1, ++ .len = len, ++ .pin = pin, ++ .flags = AuCpup_DTIME ++ }; ++ ++ sb = cpg.dentry->d_sb; ++ inode = d_inode(cpg.dentry); ++ cpg.bsrc = au_fbtop(file); ++ err = au_test_ro(sb, cpg.bsrc, inode); ++ if (!err && (au_hf_top(file)->f_mode & FMODE_WRITE)) { ++ err = au_pin(pin, cpg.dentry, cpg.bsrc, AuOpt_UDBA_NONE, ++ /*flags*/0); ++ goto out; ++ } ++ ++ /* need to cpup or reopen */ ++ parent = dget_parent(cpg.dentry); ++ di_write_lock_parent(parent); ++ err = AuWbrCopyup(au_sbi(sb), cpg.dentry); ++ cpg.bdst = err; ++ if (unlikely(err < 0)) ++ goto out_dgrade; ++ err = 0; ++ ++ if (!d_unhashed(cpg.dentry) && !au_h_dptr(parent, cpg.bdst)) { ++ err = au_cpup_dirs(cpg.dentry, cpg.bdst); ++ if (unlikely(err)) ++ goto out_dgrade; ++ } ++ ++ err = au_pin(pin, cpg.dentry, cpg.bdst, AuOpt_UDBA_NONE, ++ AuPin_DI_LOCKED | AuPin_MNT_WRITE); ++ if (unlikely(err)) ++ goto out_dgrade; ++ ++ dbtop = au_dbtop(cpg.dentry); ++ if (dbtop <= cpg.bdst) ++ cpg.bsrc = cpg.bdst; ++ ++ if (dbtop <= cpg.bdst /* just reopen */ ++ || !d_unhashed(cpg.dentry) /* copyup and reopen */ ++ ) { ++ h_file = au_h_open_pre(cpg.dentry, cpg.bsrc, /*force_wr*/0); ++ if (IS_ERR(h_file)) ++ err = PTR_ERR(h_file); ++ else { ++ di_downgrade_lock(parent, AuLock_IR); ++ if (dbtop > cpg.bdst) ++ err = au_sio_cpup_simple(&cpg); ++ if (!err) ++ err = au_reopen_nondir(file); ++ au_h_open_post(cpg.dentry, cpg.bsrc, h_file); ++ } ++ } else { /* copyup as wh and reopen */ ++ /* ++ * since writable hfsplus branch is not supported, ++ * h_open_pre/post() are unnecessary. ++ */ ++ err = au_ready_to_write_wh(file, len, cpg.bdst, pin); ++ di_downgrade_lock(parent, AuLock_IR); ++ } ++ ++ if (!err) { ++ au_pin_set_parent_lflag(pin, /*lflag*/0); ++ goto out_dput; /* success */ ++ } ++ au_unpin(pin); ++ goto out_unlock; ++ ++out_dgrade: ++ di_downgrade_lock(parent, AuLock_IR); ++out_unlock: ++ di_read_unlock(parent, AuLock_IR); ++out_dput: ++ dput(parent); ++out: ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++int au_do_flush(struct file *file, fl_owner_t id, ++ int (*flush)(struct file *file, fl_owner_t id)) ++{ ++ int err; ++ struct super_block *sb; ++ struct inode *inode; ++ ++ inode = file_inode(file); ++ sb = inode->i_sb; ++ si_noflush_read_lock(sb); ++ fi_read_lock(file); ++ ii_read_lock_child(inode); ++ ++ err = flush(file, id); ++ au_cpup_attr_timesizes(inode); ++ ++ ii_read_unlock(inode); ++ fi_read_unlock(file); ++ si_read_unlock(sb); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int au_file_refresh_by_inode(struct file *file, int *need_reopen) ++{ ++ int err; ++ struct au_pin pin; ++ struct au_finfo *finfo; ++ struct dentry *parent, *hi_wh; ++ struct inode *inode; ++ struct super_block *sb; ++ struct au_cp_generic cpg = { ++ .dentry = file->f_path.dentry, ++ .bdst = -1, ++ .bsrc = -1, ++ .len = -1, ++ .pin = &pin, ++ .flags = AuCpup_DTIME ++ }; ++ ++ FiMustWriteLock(file); ++ ++ err = 0; ++ finfo = au_fi(file); ++ sb = cpg.dentry->d_sb; ++ inode = d_inode(cpg.dentry); ++ cpg.bdst = au_ibtop(inode); ++ if (cpg.bdst == finfo->fi_btop || IS_ROOT(cpg.dentry)) ++ goto out; ++ ++ parent = dget_parent(cpg.dentry); ++ if (au_test_ro(sb, cpg.bdst, inode)) { ++ di_read_lock_parent(parent, !AuLock_IR); ++ err = AuWbrCopyup(au_sbi(sb), cpg.dentry); ++ cpg.bdst = err; ++ di_read_unlock(parent, !AuLock_IR); ++ if (unlikely(err < 0)) ++ goto out_parent; ++ err = 0; ++ } ++ ++ di_read_lock_parent(parent, AuLock_IR); ++ hi_wh = au_hi_wh(inode, cpg.bdst); ++ if (!S_ISDIR(inode->i_mode) ++ && au_opt_test(au_mntflags(sb), PLINK) ++ && au_plink_test(inode) ++ && !d_unhashed(cpg.dentry) ++ && cpg.bdst < au_dbtop(cpg.dentry)) { ++ err = au_test_and_cpup_dirs(cpg.dentry, cpg.bdst); ++ if (unlikely(err)) ++ goto out_unlock; ++ ++ /* always superio. */ ++ err = au_pin(&pin, cpg.dentry, cpg.bdst, AuOpt_UDBA_NONE, ++ AuPin_DI_LOCKED | AuPin_MNT_WRITE); ++ if (!err) { ++ err = au_sio_cpup_simple(&cpg); ++ au_unpin(&pin); ++ } ++ } else if (hi_wh) { ++ /* already copied-up after unlink */ ++ err = au_reopen_wh(file, cpg.bdst, hi_wh); ++ *need_reopen = 0; ++ } ++ ++out_unlock: ++ di_read_unlock(parent, AuLock_IR); ++out_parent: ++ dput(parent); ++out: ++ return err; ++} ++ ++static void au_do_refresh_dir(struct file *file) ++{ ++ aufs_bindex_t bindex, bbot, new_bindex, brid; ++ struct au_hfile *p, tmp, *q; ++ struct au_finfo *finfo; ++ struct super_block *sb; ++ struct au_fidir *fidir; ++ ++ FiMustWriteLock(file); ++ ++ sb = file->f_path.dentry->d_sb; ++ finfo = au_fi(file); ++ fidir = finfo->fi_hdir; ++ AuDebugOn(!fidir); ++ p = fidir->fd_hfile + finfo->fi_btop; ++ brid = p->hf_br->br_id; ++ bbot = fidir->fd_bbot; ++ for (bindex = finfo->fi_btop; bindex <= bbot; bindex++, p++) { ++ if (!p->hf_file) ++ continue; ++ ++ new_bindex = au_br_index(sb, p->hf_br->br_id); ++ if (new_bindex == bindex) ++ continue; ++ if (new_bindex < 0) { ++ au_set_h_fptr(file, bindex, NULL); ++ continue; ++ } ++ ++ /* swap two lower inode, and loop again */ ++ q = fidir->fd_hfile + new_bindex; ++ tmp = *q; ++ *q = *p; ++ *p = tmp; ++ if (tmp.hf_file) { ++ bindex--; ++ p--; ++ } ++ } ++ ++ p = fidir->fd_hfile; ++ if (!au_test_mmapped(file) && !d_unlinked(file->f_path.dentry)) { ++ bbot = au_sbbot(sb); ++ for (finfo->fi_btop = 0; finfo->fi_btop <= bbot; ++ finfo->fi_btop++, p++) ++ if (p->hf_file) { ++ if (file_inode(p->hf_file)) ++ break; ++ au_hfput(p, /*execed*/0); ++ } ++ } else { ++ bbot = au_br_index(sb, brid); ++ for (finfo->fi_btop = 0; finfo->fi_btop < bbot; ++ finfo->fi_btop++, p++) ++ if (p->hf_file) ++ au_hfput(p, /*execed*/0); ++ bbot = au_sbbot(sb); ++ } ++ ++ p = fidir->fd_hfile + bbot; ++ for (fidir->fd_bbot = bbot; fidir->fd_bbot >= finfo->fi_btop; ++ fidir->fd_bbot--, p--) ++ if (p->hf_file) { ++ if (file_inode(p->hf_file)) ++ break; ++ au_hfput(p, /*execed*/0); ++ } ++ AuDebugOn(fidir->fd_bbot < finfo->fi_btop); ++} ++ ++/* ++ * after branch manipulating, refresh the file. ++ */ ++static int refresh_file(struct file *file, int (*reopen)(struct file *file)) ++{ ++ int err, need_reopen, nbr; ++ aufs_bindex_t bbot, bindex; ++ struct dentry *dentry; ++ struct super_block *sb; ++ struct au_finfo *finfo; ++ struct au_hfile *hfile; ++ ++ dentry = file->f_path.dentry; ++ sb = dentry->d_sb; ++ nbr = au_sbbot(sb) + 1; ++ finfo = au_fi(file); ++ if (!finfo->fi_hdir) { ++ hfile = &finfo->fi_htop; ++ AuDebugOn(!hfile->hf_file); ++ bindex = au_br_index(sb, hfile->hf_br->br_id); ++ AuDebugOn(bindex < 0); ++ if (bindex != finfo->fi_btop) ++ au_set_fbtop(file, bindex); ++ } else { ++ err = au_fidir_realloc(finfo, nbr, /*may_shrink*/0); ++ if (unlikely(err)) ++ goto out; ++ au_do_refresh_dir(file); ++ } ++ ++ err = 0; ++ need_reopen = 1; ++ if (!au_test_mmapped(file)) ++ err = au_file_refresh_by_inode(file, &need_reopen); ++ if (finfo->fi_hdir) ++ /* harmless if err */ ++ au_fidir_realloc(finfo, nbr, /*may_shrink*/1); ++ if (!err && need_reopen && !d_unlinked(dentry)) ++ err = reopen(file); ++ if (!err) { ++ au_update_figen(file); ++ goto out; /* success */ ++ } ++ ++ /* error, close all lower files */ ++ if (finfo->fi_hdir) { ++ bbot = au_fbbot_dir(file); ++ for (bindex = au_fbtop(file); bindex <= bbot; bindex++) ++ au_set_h_fptr(file, bindex, NULL); ++ } ++ ++out: ++ return err; ++} ++ ++/* common function to regular file and dir */ ++int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file), ++ int wlock, unsigned int fi_lsc) ++{ ++ int err; ++ unsigned int sigen, figen; ++ aufs_bindex_t btop; ++ unsigned char pseudo_link; ++ struct dentry *dentry; ++ struct inode *inode; ++ ++ err = 0; ++ dentry = file->f_path.dentry; ++ inode = d_inode(dentry); ++ sigen = au_sigen(dentry->d_sb); ++ fi_write_lock_nested(file, fi_lsc); ++ figen = au_figen(file); ++ if (!fi_lsc) ++ di_write_lock_child(dentry); ++ else ++ di_write_lock_child2(dentry); ++ btop = au_dbtop(dentry); ++ pseudo_link = (btop != au_ibtop(inode)); ++ if (sigen == figen && !pseudo_link && au_fbtop(file) == btop) { ++ if (!wlock) { ++ di_downgrade_lock(dentry, AuLock_IR); ++ fi_downgrade_lock(file); ++ } ++ goto out; /* success */ ++ } ++ ++ AuDbg("sigen %d, figen %d\n", sigen, figen); ++ if (au_digen_test(dentry, sigen)) { ++ err = au_reval_dpath(dentry, sigen); ++ AuDebugOn(!err && au_digen_test(dentry, sigen)); ++ } ++ ++ if (!err) ++ err = refresh_file(file, reopen); ++ if (!err) { ++ if (!wlock) { ++ di_downgrade_lock(dentry, AuLock_IR); ++ fi_downgrade_lock(file); ++ } ++ } else { ++ di_write_unlock(dentry); ++ fi_write_unlock(file); ++ } ++ ++out: ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* cf. aufs_nopage() */ ++/* for madvise(2) */ ++static int aufs_readpage(struct file *file __maybe_unused, struct page *page) ++{ ++ unlock_page(page); ++ return 0; ++} ++ ++/* it will never be called, but necessary to support O_DIRECT */ ++static ssize_t aufs_direct_IO(struct kiocb *iocb, struct iov_iter *iter) ++{ BUG(); return 0; } ++ ++/* they will never be called. */ ++#ifdef CONFIG_AUFS_DEBUG ++static int aufs_write_begin(struct file *file, struct address_space *mapping, ++ loff_t pos, unsigned len, unsigned flags, ++ struct page **pagep, void **fsdata) ++{ AuUnsupport(); return 0; } ++static int aufs_write_end(struct file *file, struct address_space *mapping, ++ loff_t pos, unsigned len, unsigned copied, ++ struct page *page, void *fsdata) ++{ AuUnsupport(); return 0; } ++static int aufs_writepage(struct page *page, struct writeback_control *wbc) ++{ AuUnsupport(); return 0; } ++ ++static int aufs_set_page_dirty(struct page *page) ++{ AuUnsupport(); return 0; } ++static void aufs_invalidatepage(struct page *page, unsigned int offset, ++ unsigned int length) ++{ AuUnsupport(); } ++static int aufs_releasepage(struct page *page, gfp_t gfp) ++{ AuUnsupport(); return 0; } ++#if 0 /* called by memory compaction regardless file */ ++static int aufs_migratepage(struct address_space *mapping, struct page *newpage, ++ struct page *page, enum migrate_mode mode) ++{ AuUnsupport(); return 0; } ++#endif ++static bool aufs_isolate_page(struct page *page, isolate_mode_t mode) ++{ AuUnsupport(); return true; } ++static void aufs_putback_page(struct page *page) ++{ AuUnsupport(); } ++static int aufs_launder_page(struct page *page) ++{ AuUnsupport(); return 0; } ++static int aufs_is_partially_uptodate(struct page *page, ++ unsigned long from, ++ unsigned long count) ++{ AuUnsupport(); return 0; } ++static void aufs_is_dirty_writeback(struct page *page, bool *dirty, ++ bool *writeback) ++{ AuUnsupport(); } ++static int aufs_error_remove_page(struct address_space *mapping, ++ struct page *page) ++{ AuUnsupport(); return 0; } ++static int aufs_swap_activate(struct swap_info_struct *sis, struct file *file, ++ sector_t *span) ++{ AuUnsupport(); return 0; } ++static void aufs_swap_deactivate(struct file *file) ++{ AuUnsupport(); } ++#endif /* CONFIG_AUFS_DEBUG */ ++ ++const struct address_space_operations aufs_aop = { ++ .readpage = aufs_readpage, ++ .direct_IO = aufs_direct_IO, ++#ifdef CONFIG_AUFS_DEBUG ++ .writepage = aufs_writepage, ++ /* no writepages, because of writepage */ ++ .set_page_dirty = aufs_set_page_dirty, ++ /* no readpages, because of readpage */ ++ .write_begin = aufs_write_begin, ++ .write_end = aufs_write_end, ++ /* no bmap, no block device */ ++ .invalidatepage = aufs_invalidatepage, ++ .releasepage = aufs_releasepage, ++ /* is fallback_migrate_page ok? */ ++ /* .migratepage = aufs_migratepage, */ ++ .isolate_page = aufs_isolate_page, ++ .putback_page = aufs_putback_page, ++ .launder_page = aufs_launder_page, ++ .is_partially_uptodate = aufs_is_partially_uptodate, ++ .is_dirty_writeback = aufs_is_dirty_writeback, ++ .error_remove_page = aufs_error_remove_page, ++ .swap_activate = aufs_swap_activate, ++ .swap_deactivate = aufs_swap_deactivate ++#endif /* CONFIG_AUFS_DEBUG */ ++}; +diff -Nurp linux-5.4/fs/aufs/file.h linux-5.4-aufs/fs/aufs/file.h +--- linux-5.4/fs/aufs/file.h 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/file.h 2019-11-28 01:25:59.065925618 +0200 +@@ -0,0 +1,329 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * file operations ++ */ ++ ++#ifndef __AUFS_FILE_H__ ++#define __AUFS_FILE_H__ ++ ++#ifdef __KERNEL__ ++ ++#include ++#include ++#include ++#include ++#include "rwsem.h" ++ ++struct au_branch; ++struct au_hfile { ++ struct file *hf_file; ++ struct au_branch *hf_br; ++}; ++ ++struct au_vdir; ++struct au_fidir { ++ aufs_bindex_t fd_bbot; ++ aufs_bindex_t fd_nent; ++ struct au_vdir *fd_vdir_cache; ++ struct au_hfile fd_hfile[]; ++}; ++ ++static inline int au_fidir_sz(int nent) ++{ ++ AuDebugOn(nent < 0); ++ return sizeof(struct au_fidir) + sizeof(struct au_hfile) * nent; ++} ++ ++struct au_finfo { ++ atomic_t fi_generation; ++ ++ struct au_rwsem fi_rwsem; ++ aufs_bindex_t fi_btop; ++ ++ /* do not union them */ ++ struct { /* for non-dir */ ++ struct au_hfile fi_htop; ++ atomic_t fi_mmapped; ++ }; ++ struct au_fidir *fi_hdir; /* for dir only */ ++ ++ struct hlist_bl_node fi_hlist; ++ struct file *fi_file; /* very ugly */ ++ struct rcu_head rcu; ++} ____cacheline_aligned_in_smp; ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* file.c */ ++extern const struct address_space_operations aufs_aop; ++unsigned int au_file_roflags(unsigned int flags); ++struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags, ++ struct file *file, int force_wr); ++struct au_do_open_args { ++ int aopen; ++ int (*open)(struct file *file, int flags, ++ struct file *h_file); ++ struct au_fidir *fidir; ++ struct file *h_file; ++}; ++int au_do_open(struct file *file, struct au_do_open_args *args); ++int au_reopen_nondir(struct file *file); ++struct au_pin; ++int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin); ++int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file), ++ int wlock, unsigned int fi_lsc); ++int au_do_flush(struct file *file, fl_owner_t id, ++ int (*flush)(struct file *file, fl_owner_t id)); ++ ++/* poll.c */ ++#ifdef CONFIG_AUFS_POLL ++__poll_t aufs_poll(struct file *file, struct poll_table_struct *pt); ++#endif ++ ++#ifdef CONFIG_AUFS_BR_HFSPLUS ++/* hfsplus.c */ ++struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex, ++ int force_wr); ++void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex, ++ struct file *h_file); ++#else ++AuStub(struct file *, au_h_open_pre, return NULL, struct dentry *dentry, ++ aufs_bindex_t bindex, int force_wr) ++AuStubVoid(au_h_open_post, struct dentry *dentry, aufs_bindex_t bindex, ++ struct file *h_file); ++#endif ++ ++/* f_op.c */ ++extern const struct file_operations aufs_file_fop; ++int au_do_open_nondir(struct file *file, int flags, struct file *h_file); ++int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file); ++struct file *au_read_pre(struct file *file, int keep_fi, unsigned int lsc); ++ ++/* finfo.c */ ++void au_hfput(struct au_hfile *hf, int execed); ++void au_set_h_fptr(struct file *file, aufs_bindex_t bindex, ++ struct file *h_file); ++ ++void au_update_figen(struct file *file); ++struct au_fidir *au_fidir_alloc(struct super_block *sb); ++int au_fidir_realloc(struct au_finfo *finfo, int nbr, int may_shrink); ++ ++void au_fi_init_once(void *_fi); ++void au_finfo_fin(struct file *file); ++int au_finfo_init(struct file *file, struct au_fidir *fidir); ++ ++/* ioctl.c */ ++long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg); ++#ifdef CONFIG_COMPAT ++long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd, ++ unsigned long arg); ++long aufs_compat_ioctl_nondir(struct file *file, unsigned int cmd, ++ unsigned long arg); ++#endif ++ ++/* ---------------------------------------------------------------------- */ ++ ++static inline struct au_finfo *au_fi(struct file *file) ++{ ++ return file->private_data; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++#define fi_read_lock(f) au_rw_read_lock(&au_fi(f)->fi_rwsem) ++#define fi_write_lock(f) au_rw_write_lock(&au_fi(f)->fi_rwsem) ++#define fi_read_trylock(f) au_rw_read_trylock(&au_fi(f)->fi_rwsem) ++#define fi_write_trylock(f) au_rw_write_trylock(&au_fi(f)->fi_rwsem) ++/* ++#define fi_read_trylock_nested(f) \ ++ au_rw_read_trylock_nested(&au_fi(f)->fi_rwsem) ++#define fi_write_trylock_nested(f) \ ++ au_rw_write_trylock_nested(&au_fi(f)->fi_rwsem) ++*/ ++ ++#define fi_read_unlock(f) au_rw_read_unlock(&au_fi(f)->fi_rwsem) ++#define fi_write_unlock(f) au_rw_write_unlock(&au_fi(f)->fi_rwsem) ++#define fi_downgrade_lock(f) au_rw_dgrade_lock(&au_fi(f)->fi_rwsem) ++ ++/* lock subclass for finfo */ ++enum { ++ AuLsc_FI_1, ++ AuLsc_FI_2 ++}; ++ ++static inline void fi_read_lock_nested(struct file *f, unsigned int lsc) ++{ ++ au_rw_read_lock_nested(&au_fi(f)->fi_rwsem, lsc); ++} ++ ++static inline void fi_write_lock_nested(struct file *f, unsigned int lsc) ++{ ++ au_rw_write_lock_nested(&au_fi(f)->fi_rwsem, lsc); ++} ++ ++/* ++ * fi_read_lock_1, fi_write_lock_1, ++ * fi_read_lock_2, fi_write_lock_2 ++ */ ++#define AuReadLockFunc(name) \ ++static inline void fi_read_lock_##name(struct file *f) \ ++{ fi_read_lock_nested(f, AuLsc_FI_##name); } ++ ++#define AuWriteLockFunc(name) \ ++static inline void fi_write_lock_##name(struct file *f) \ ++{ fi_write_lock_nested(f, AuLsc_FI_##name); } ++ ++#define AuRWLockFuncs(name) \ ++ AuReadLockFunc(name) \ ++ AuWriteLockFunc(name) ++ ++AuRWLockFuncs(1); ++AuRWLockFuncs(2); ++ ++#undef AuReadLockFunc ++#undef AuWriteLockFunc ++#undef AuRWLockFuncs ++ ++#define FiMustNoWaiters(f) AuRwMustNoWaiters(&au_fi(f)->fi_rwsem) ++#define FiMustAnyLock(f) AuRwMustAnyLock(&au_fi(f)->fi_rwsem) ++#define FiMustWriteLock(f) AuRwMustWriteLock(&au_fi(f)->fi_rwsem) ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* todo: hard/soft set? */ ++static inline aufs_bindex_t au_fbtop(struct file *file) ++{ ++ FiMustAnyLock(file); ++ return au_fi(file)->fi_btop; ++} ++ ++static inline aufs_bindex_t au_fbbot_dir(struct file *file) ++{ ++ FiMustAnyLock(file); ++ AuDebugOn(!au_fi(file)->fi_hdir); ++ return au_fi(file)->fi_hdir->fd_bbot; ++} ++ ++static inline struct au_vdir *au_fvdir_cache(struct file *file) ++{ ++ FiMustAnyLock(file); ++ AuDebugOn(!au_fi(file)->fi_hdir); ++ return au_fi(file)->fi_hdir->fd_vdir_cache; ++} ++ ++static inline void au_set_fbtop(struct file *file, aufs_bindex_t bindex) ++{ ++ FiMustWriteLock(file); ++ au_fi(file)->fi_btop = bindex; ++} ++ ++static inline void au_set_fbbot_dir(struct file *file, aufs_bindex_t bindex) ++{ ++ FiMustWriteLock(file); ++ AuDebugOn(!au_fi(file)->fi_hdir); ++ au_fi(file)->fi_hdir->fd_bbot = bindex; ++} ++ ++static inline void au_set_fvdir_cache(struct file *file, ++ struct au_vdir *vdir_cache) ++{ ++ FiMustWriteLock(file); ++ AuDebugOn(!au_fi(file)->fi_hdir); ++ au_fi(file)->fi_hdir->fd_vdir_cache = vdir_cache; ++} ++ ++static inline struct file *au_hf_top(struct file *file) ++{ ++ FiMustAnyLock(file); ++ AuDebugOn(au_fi(file)->fi_hdir); ++ return au_fi(file)->fi_htop.hf_file; ++} ++ ++static inline struct file *au_hf_dir(struct file *file, aufs_bindex_t bindex) ++{ ++ FiMustAnyLock(file); ++ AuDebugOn(!au_fi(file)->fi_hdir); ++ return au_fi(file)->fi_hdir->fd_hfile[0 + bindex].hf_file; ++} ++ ++/* todo: memory barrier? */ ++static inline unsigned int au_figen(struct file *f) ++{ ++ return atomic_read(&au_fi(f)->fi_generation); ++} ++ ++static inline void au_set_mmapped(struct file *f) ++{ ++ if (atomic_inc_return(&au_fi(f)->fi_mmapped)) ++ return; ++ pr_warn("fi_mmapped wrapped around\n"); ++ while (!atomic_inc_return(&au_fi(f)->fi_mmapped)) ++ ; ++} ++ ++static inline void au_unset_mmapped(struct file *f) ++{ ++ atomic_dec(&au_fi(f)->fi_mmapped); ++} ++ ++static inline int au_test_mmapped(struct file *f) ++{ ++ return atomic_read(&au_fi(f)->fi_mmapped); ++} ++ ++/* customize vma->vm_file */ ++ ++static inline void au_do_vm_file_reset(struct vm_area_struct *vma, ++ struct file *file) ++{ ++ struct file *f; ++ ++ f = vma->vm_file; ++ get_file(file); ++ vma->vm_file = file; ++ fput(f); ++} ++ ++#ifdef CONFIG_MMU ++#define AuDbgVmRegion(file, vma) do {} while (0) ++ ++static inline void au_vm_file_reset(struct vm_area_struct *vma, ++ struct file *file) ++{ ++ au_do_vm_file_reset(vma, file); ++} ++#else ++#define AuDbgVmRegion(file, vma) \ ++ AuDebugOn((vma)->vm_region && (vma)->vm_region->vm_file != (file)) ++ ++static inline void au_vm_file_reset(struct vm_area_struct *vma, ++ struct file *file) ++{ ++ struct file *f; ++ ++ au_do_vm_file_reset(vma, file); ++ f = vma->vm_region->vm_file; ++ get_file(file); ++ vma->vm_region->vm_file = file; ++ fput(f); ++} ++#endif /* CONFIG_MMU */ ++ ++/* handle vma->vm_prfile */ ++static inline void au_vm_prfile_set(struct vm_area_struct *vma, ++ struct file *file) ++{ ++ get_file(file); ++ vma->vm_prfile = file; ++#ifndef CONFIG_MMU ++ get_file(file); ++ vma->vm_region->vm_prfile = file; ++#endif ++} ++ ++#endif /* __KERNEL__ */ ++#endif /* __AUFS_FILE_H__ */ +diff -Nurp linux-5.4/fs/aufs/finfo.c linux-5.4-aufs/fs/aufs/finfo.c +--- linux-5.4/fs/aufs/finfo.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/finfo.c 2019-11-28 01:25:59.065925618 +0200 +@@ -0,0 +1,136 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * file private data ++ */ ++ ++#include "aufs.h" ++ ++void au_hfput(struct au_hfile *hf, int execed) ++{ ++ if (execed) ++ allow_write_access(hf->hf_file); ++ fput(hf->hf_file); ++ hf->hf_file = NULL; ++ au_lcnt_dec(&hf->hf_br->br_nfiles); ++ hf->hf_br = NULL; ++} ++ ++void au_set_h_fptr(struct file *file, aufs_bindex_t bindex, struct file *val) ++{ ++ struct au_finfo *finfo = au_fi(file); ++ struct au_hfile *hf; ++ struct au_fidir *fidir; ++ ++ fidir = finfo->fi_hdir; ++ if (!fidir) { ++ AuDebugOn(finfo->fi_btop != bindex); ++ hf = &finfo->fi_htop; ++ } else ++ hf = fidir->fd_hfile + bindex; ++ ++ if (hf && hf->hf_file) ++ au_hfput(hf, vfsub_file_execed(file)); ++ if (val) { ++ FiMustWriteLock(file); ++ AuDebugOn(IS_ERR_OR_NULL(file->f_path.dentry)); ++ hf->hf_file = val; ++ hf->hf_br = au_sbr(file->f_path.dentry->d_sb, bindex); ++ } ++} ++ ++void au_update_figen(struct file *file) ++{ ++ atomic_set(&au_fi(file)->fi_generation, au_digen(file->f_path.dentry)); ++ /* smp_mb(); */ /* atomic_set */ ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++struct au_fidir *au_fidir_alloc(struct super_block *sb) ++{ ++ struct au_fidir *fidir; ++ int nbr; ++ ++ nbr = au_sbbot(sb) + 1; ++ if (nbr < 2) ++ nbr = 2; /* initial allocate for 2 branches */ ++ fidir = kzalloc(au_fidir_sz(nbr), GFP_NOFS); ++ if (fidir) { ++ fidir->fd_bbot = -1; ++ fidir->fd_nent = nbr; ++ } ++ ++ return fidir; ++} ++ ++int au_fidir_realloc(struct au_finfo *finfo, int nbr, int may_shrink) ++{ ++ int err; ++ struct au_fidir *fidir, *p; ++ ++ AuRwMustWriteLock(&finfo->fi_rwsem); ++ fidir = finfo->fi_hdir; ++ AuDebugOn(!fidir); ++ ++ err = -ENOMEM; ++ p = au_kzrealloc(fidir, au_fidir_sz(fidir->fd_nent), au_fidir_sz(nbr), ++ GFP_NOFS, may_shrink); ++ if (p) { ++ p->fd_nent = nbr; ++ finfo->fi_hdir = p; ++ err = 0; ++ } ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++void au_finfo_fin(struct file *file) ++{ ++ struct au_finfo *finfo; ++ ++ au_lcnt_dec(&au_sbi(file->f_path.dentry->d_sb)->si_nfiles); ++ ++ finfo = au_fi(file); ++ AuDebugOn(finfo->fi_hdir); ++ AuRwDestroy(&finfo->fi_rwsem); ++ au_cache_free_finfo(finfo); ++} ++ ++void au_fi_init_once(void *_finfo) ++{ ++ struct au_finfo *finfo = _finfo; ++ ++ au_rw_init(&finfo->fi_rwsem); ++} ++ ++int au_finfo_init(struct file *file, struct au_fidir *fidir) ++{ ++ int err; ++ struct au_finfo *finfo; ++ struct dentry *dentry; ++ ++ err = -ENOMEM; ++ dentry = file->f_path.dentry; ++ finfo = au_cache_alloc_finfo(); ++ if (unlikely(!finfo)) ++ goto out; ++ ++ err = 0; ++ au_lcnt_inc(&au_sbi(dentry->d_sb)->si_nfiles); ++ au_rw_write_lock(&finfo->fi_rwsem); ++ finfo->fi_btop = -1; ++ finfo->fi_hdir = fidir; ++ atomic_set(&finfo->fi_generation, au_digen(dentry)); ++ /* smp_mb(); */ /* atomic_set */ ++ ++ file->private_data = finfo; ++ ++out: ++ return err; ++} +diff -Nurp linux-5.4/fs/aufs/f_op.c linux-5.4-aufs/fs/aufs/f_op.c +--- linux-5.4/fs/aufs/f_op.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/f_op.c 2019-11-28 01:25:59.064925618 +0200 +@@ -0,0 +1,806 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * file and vm operations ++ */ ++ ++#include ++#include ++#include ++#include ++#include "aufs.h" ++ ++int au_do_open_nondir(struct file *file, int flags, struct file *h_file) ++{ ++ int err; ++ aufs_bindex_t bindex; ++ struct dentry *dentry, *h_dentry; ++ struct au_finfo *finfo; ++ struct inode *h_inode; ++ ++ FiMustWriteLock(file); ++ ++ err = 0; ++ dentry = file->f_path.dentry; ++ AuDebugOn(IS_ERR_OR_NULL(dentry)); ++ finfo = au_fi(file); ++ memset(&finfo->fi_htop, 0, sizeof(finfo->fi_htop)); ++ atomic_set(&finfo->fi_mmapped, 0); ++ bindex = au_dbtop(dentry); ++ if (!h_file) { ++ h_dentry = au_h_dptr(dentry, bindex); ++ err = vfsub_test_mntns(file->f_path.mnt, h_dentry->d_sb); ++ if (unlikely(err)) ++ goto out; ++ h_file = au_h_open(dentry, bindex, flags, file, /*force_wr*/0); ++ if (IS_ERR(h_file)) { ++ err = PTR_ERR(h_file); ++ goto out; ++ } ++ } else { ++ h_dentry = h_file->f_path.dentry; ++ err = vfsub_test_mntns(file->f_path.mnt, h_dentry->d_sb); ++ if (unlikely(err)) ++ goto out; ++ /* br ref is already inc-ed */ ++ } ++ ++ if ((flags & __O_TMPFILE) ++ && !(flags & O_EXCL)) { ++ h_inode = file_inode(h_file); ++ spin_lock(&h_inode->i_lock); ++ h_inode->i_state |= I_LINKABLE; ++ spin_unlock(&h_inode->i_lock); ++ } ++ au_set_fbtop(file, bindex); ++ au_set_h_fptr(file, bindex, h_file); ++ au_update_figen(file); ++ /* todo: necessary? */ ++ /* file->f_ra = h_file->f_ra; */ ++ ++out: ++ return err; ++} ++ ++static int aufs_open_nondir(struct inode *inode __maybe_unused, ++ struct file *file) ++{ ++ int err; ++ struct super_block *sb; ++ struct au_do_open_args args = { ++ .open = au_do_open_nondir ++ }; ++ ++ AuDbg("%pD, f_flags 0x%x, f_mode 0x%x\n", ++ file, vfsub_file_flags(file), file->f_mode); ++ ++ sb = file->f_path.dentry->d_sb; ++ si_read_lock(sb, AuLock_FLUSH); ++ err = au_do_open(file, &args); ++ si_read_unlock(sb); ++ return err; ++} ++ ++int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file) ++{ ++ struct au_finfo *finfo; ++ aufs_bindex_t bindex; ++ ++ finfo = au_fi(file); ++ au_hbl_del(&finfo->fi_hlist, ++ &au_sbi(file->f_path.dentry->d_sb)->si_files); ++ bindex = finfo->fi_btop; ++ if (bindex >= 0) ++ au_set_h_fptr(file, bindex, NULL); ++ ++ au_finfo_fin(file); ++ return 0; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int au_do_flush_nondir(struct file *file, fl_owner_t id) ++{ ++ int err; ++ struct file *h_file; ++ ++ err = 0; ++ h_file = au_hf_top(file); ++ if (h_file) ++ err = vfsub_flush(h_file, id); ++ return err; ++} ++ ++static int aufs_flush_nondir(struct file *file, fl_owner_t id) ++{ ++ return au_do_flush(file, id, au_do_flush_nondir); ++} ++ ++/* ---------------------------------------------------------------------- */ ++/* ++ * read and write functions acquire [fdi]_rwsem once, but release before ++ * mmap_sem. This is because to stop a race condition between mmap(2). ++ * Releasing these aufs-rwsem should be safe, no branch-management (by keeping ++ * si_rwsem), no harmful copy-up should happen. Actually copy-up may happen in ++ * read functions after [fdi]_rwsem are released, but it should be harmless. ++ */ ++ ++/* Callers should call au_read_post() or fput() in the end */ ++struct file *au_read_pre(struct file *file, int keep_fi, unsigned int lsc) ++{ ++ struct file *h_file; ++ int err; ++ ++ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0, lsc); ++ if (!err) { ++ di_read_unlock(file->f_path.dentry, AuLock_IR); ++ h_file = au_hf_top(file); ++ get_file(h_file); ++ if (!keep_fi) ++ fi_read_unlock(file); ++ } else ++ h_file = ERR_PTR(err); ++ ++ return h_file; ++} ++ ++static void au_read_post(struct inode *inode, struct file *h_file) ++{ ++ /* update without lock, I don't think it a problem */ ++ fsstack_copy_attr_atime(inode, file_inode(h_file)); ++ fput(h_file); ++} ++ ++struct au_write_pre { ++ /* input */ ++ unsigned int lsc; ++ ++ /* output */ ++ blkcnt_t blks; ++ aufs_bindex_t btop; ++}; ++ ++/* ++ * return with iinfo is write-locked ++ * callers should call au_write_post() or iinfo_write_unlock() + fput() in the ++ * end ++ */ ++static struct file *au_write_pre(struct file *file, int do_ready, ++ struct au_write_pre *wpre) ++{ ++ struct file *h_file; ++ struct dentry *dentry; ++ int err; ++ unsigned int lsc; ++ struct au_pin pin; ++ ++ lsc = 0; ++ if (wpre) ++ lsc = wpre->lsc; ++ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1, lsc); ++ h_file = ERR_PTR(err); ++ if (unlikely(err)) ++ goto out; ++ ++ dentry = file->f_path.dentry; ++ if (do_ready) { ++ err = au_ready_to_write(file, -1, &pin); ++ if (unlikely(err)) { ++ h_file = ERR_PTR(err); ++ di_write_unlock(dentry); ++ goto out_fi; ++ } ++ } ++ ++ di_downgrade_lock(dentry, /*flags*/0); ++ if (wpre) ++ wpre->btop = au_fbtop(file); ++ h_file = au_hf_top(file); ++ get_file(h_file); ++ if (wpre) ++ wpre->blks = file_inode(h_file)->i_blocks; ++ if (do_ready) ++ au_unpin(&pin); ++ di_read_unlock(dentry, /*flags*/0); ++ ++out_fi: ++ fi_write_unlock(file); ++out: ++ return h_file; ++} ++ ++static void au_write_post(struct inode *inode, struct file *h_file, ++ struct au_write_pre *wpre, ssize_t written) ++{ ++ struct inode *h_inode; ++ ++ au_cpup_attr_timesizes(inode); ++ AuDebugOn(au_ibtop(inode) != wpre->btop); ++ h_inode = file_inode(h_file); ++ inode->i_mode = h_inode->i_mode; ++ ii_write_unlock(inode); ++ /* AuDbg("blks %llu, %llu\n", (u64)blks, (u64)h_inode->i_blocks); */ ++ if (written > 0) ++ au_fhsm_wrote(inode->i_sb, wpre->btop, ++ /*force*/h_inode->i_blocks > wpre->blks); ++ fput(h_file); ++} ++ ++static ssize_t aufs_read(struct file *file, char __user *buf, size_t count, ++ loff_t *ppos) ++{ ++ ssize_t err; ++ struct inode *inode; ++ struct file *h_file; ++ struct super_block *sb; ++ ++ inode = file_inode(file); ++ sb = inode->i_sb; ++ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); ++ ++ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0); ++ err = PTR_ERR(h_file); ++ if (IS_ERR(h_file)) ++ goto out; ++ ++ /* filedata may be obsoleted by concurrent copyup, but no problem */ ++ err = vfsub_read_u(h_file, buf, count, ppos); ++ /* todo: necessary? */ ++ /* file->f_ra = h_file->f_ra; */ ++ au_read_post(inode, h_file); ++ ++out: ++ si_read_unlock(sb); ++ return err; ++} ++ ++/* ++ * todo: very ugly ++ * it locks both of i_mutex and si_rwsem for read in safe. ++ * if the plink maintenance mode continues forever (that is the problem), ++ * may loop forever. ++ */ ++static void au_mtx_and_read_lock(struct inode *inode) ++{ ++ int err; ++ struct super_block *sb = inode->i_sb; ++ ++ while (1) { ++ inode_lock(inode); ++ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM); ++ if (!err) ++ break; ++ inode_unlock(inode); ++ si_read_lock(sb, AuLock_NOPLMW); ++ si_read_unlock(sb); ++ } ++} ++ ++static ssize_t aufs_write(struct file *file, const char __user *ubuf, ++ size_t count, loff_t *ppos) ++{ ++ ssize_t err; ++ struct au_write_pre wpre; ++ struct inode *inode; ++ struct file *h_file; ++ char __user *buf = (char __user *)ubuf; ++ ++ inode = file_inode(file); ++ au_mtx_and_read_lock(inode); ++ ++ wpre.lsc = 0; ++ h_file = au_write_pre(file, /*do_ready*/1, &wpre); ++ err = PTR_ERR(h_file); ++ if (IS_ERR(h_file)) ++ goto out; ++ ++ err = vfsub_write_u(h_file, buf, count, ppos); ++ au_write_post(inode, h_file, &wpre, err); ++ ++out: ++ si_read_unlock(inode->i_sb); ++ inode_unlock(inode); ++ return err; ++} ++ ++static ssize_t au_do_iter(struct file *h_file, int rw, struct kiocb *kio, ++ struct iov_iter *iov_iter) ++{ ++ ssize_t err; ++ struct file *file; ++ ssize_t (*iter)(struct kiocb *, struct iov_iter *); ++ ++ err = security_file_permission(h_file, rw); ++ if (unlikely(err)) ++ goto out; ++ ++ err = -ENOSYS; ++ iter = NULL; ++ if (rw == MAY_READ) ++ iter = h_file->f_op->read_iter; ++ else if (rw == MAY_WRITE) ++ iter = h_file->f_op->write_iter; ++ ++ file = kio->ki_filp; ++ kio->ki_filp = h_file; ++ if (iter) { ++ lockdep_off(); ++ err = iter(kio, iov_iter); ++ lockdep_on(); ++ } else ++ /* currently there is no such fs */ ++ WARN_ON_ONCE(1); ++ kio->ki_filp = file; ++ ++out: ++ return err; ++} ++ ++static ssize_t aufs_read_iter(struct kiocb *kio, struct iov_iter *iov_iter) ++{ ++ ssize_t err; ++ struct file *file, *h_file; ++ struct inode *inode; ++ struct super_block *sb; ++ ++ file = kio->ki_filp; ++ inode = file_inode(file); ++ sb = inode->i_sb; ++ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); ++ ++ h_file = au_read_pre(file, /*keep_fi*/1, /*lsc*/0); ++ err = PTR_ERR(h_file); ++ if (IS_ERR(h_file)) ++ goto out; ++ ++ if (au_test_loopback_kthread()) { ++ au_warn_loopback(h_file->f_path.dentry->d_sb); ++ if (file->f_mapping != h_file->f_mapping) { ++ file->f_mapping = h_file->f_mapping; ++ smp_mb(); /* unnecessary? */ ++ } ++ } ++ fi_read_unlock(file); ++ ++ err = au_do_iter(h_file, MAY_READ, kio, iov_iter); ++ /* todo: necessary? */ ++ /* file->f_ra = h_file->f_ra; */ ++ au_read_post(inode, h_file); ++ ++out: ++ si_read_unlock(sb); ++ return err; ++} ++ ++static ssize_t aufs_write_iter(struct kiocb *kio, struct iov_iter *iov_iter) ++{ ++ ssize_t err; ++ struct au_write_pre wpre; ++ struct inode *inode; ++ struct file *file, *h_file; ++ ++ file = kio->ki_filp; ++ inode = file_inode(file); ++ au_mtx_and_read_lock(inode); ++ ++ wpre.lsc = 0; ++ h_file = au_write_pre(file, /*do_ready*/1, &wpre); ++ err = PTR_ERR(h_file); ++ if (IS_ERR(h_file)) ++ goto out; ++ ++ err = au_do_iter(h_file, MAY_WRITE, kio, iov_iter); ++ au_write_post(inode, h_file, &wpre, err); ++ ++out: ++ si_read_unlock(inode->i_sb); ++ inode_unlock(inode); ++ return err; ++} ++ ++static ssize_t aufs_splice_read(struct file *file, loff_t *ppos, ++ struct pipe_inode_info *pipe, size_t len, ++ unsigned int flags) ++{ ++ ssize_t err; ++ struct file *h_file; ++ struct inode *inode; ++ struct super_block *sb; ++ ++ inode = file_inode(file); ++ sb = inode->i_sb; ++ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); ++ ++ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0); ++ err = PTR_ERR(h_file); ++ if (IS_ERR(h_file)) ++ goto out; ++ ++ err = vfsub_splice_to(h_file, ppos, pipe, len, flags); ++ /* todo: necessary? */ ++ /* file->f_ra = h_file->f_ra; */ ++ au_read_post(inode, h_file); ++ ++out: ++ si_read_unlock(sb); ++ return err; ++} ++ ++static ssize_t ++aufs_splice_write(struct pipe_inode_info *pipe, struct file *file, loff_t *ppos, ++ size_t len, unsigned int flags) ++{ ++ ssize_t err; ++ struct au_write_pre wpre; ++ struct inode *inode; ++ struct file *h_file; ++ ++ inode = file_inode(file); ++ au_mtx_and_read_lock(inode); ++ ++ wpre.lsc = 0; ++ h_file = au_write_pre(file, /*do_ready*/1, &wpre); ++ err = PTR_ERR(h_file); ++ if (IS_ERR(h_file)) ++ goto out; ++ ++ err = vfsub_splice_from(pipe, h_file, ppos, len, flags); ++ au_write_post(inode, h_file, &wpre, err); ++ ++out: ++ si_read_unlock(inode->i_sb); ++ inode_unlock(inode); ++ return err; ++} ++ ++static long aufs_fallocate(struct file *file, int mode, loff_t offset, ++ loff_t len) ++{ ++ long err; ++ struct au_write_pre wpre; ++ struct inode *inode; ++ struct file *h_file; ++ ++ inode = file_inode(file); ++ au_mtx_and_read_lock(inode); ++ ++ wpre.lsc = 0; ++ h_file = au_write_pre(file, /*do_ready*/1, &wpre); ++ err = PTR_ERR(h_file); ++ if (IS_ERR(h_file)) ++ goto out; ++ ++ lockdep_off(); ++ err = vfs_fallocate(h_file, mode, offset, len); ++ lockdep_on(); ++ au_write_post(inode, h_file, &wpre, /*written*/1); ++ ++out: ++ si_read_unlock(inode->i_sb); ++ inode_unlock(inode); ++ return err; ++} ++ ++static ssize_t aufs_copy_file_range(struct file *src, loff_t src_pos, ++ struct file *dst, loff_t dst_pos, ++ size_t len, unsigned int flags) ++{ ++ ssize_t err; ++ struct au_write_pre wpre; ++ enum { SRC, DST }; ++ struct { ++ struct inode *inode; ++ struct file *h_file; ++ struct super_block *h_sb; ++ } a[2]; ++#define a_src a[SRC] ++#define a_dst a[DST] ++ ++ err = -EINVAL; ++ a_src.inode = file_inode(src); ++ if (unlikely(!S_ISREG(a_src.inode->i_mode))) ++ goto out; ++ a_dst.inode = file_inode(dst); ++ if (unlikely(!S_ISREG(a_dst.inode->i_mode))) ++ goto out; ++ ++ au_mtx_and_read_lock(a_dst.inode); ++ /* ++ * in order to match the order in di_write_lock2_{child,parent}(), ++ * use f_path.dentry for this comparison. ++ */ ++ if (src->f_path.dentry < dst->f_path.dentry) { ++ a_src.h_file = au_read_pre(src, /*keep_fi*/1, AuLsc_FI_1); ++ err = PTR_ERR(a_src.h_file); ++ if (IS_ERR(a_src.h_file)) ++ goto out_si; ++ ++ wpre.lsc = AuLsc_FI_2; ++ a_dst.h_file = au_write_pre(dst, /*do_ready*/1, &wpre); ++ err = PTR_ERR(a_dst.h_file); ++ if (IS_ERR(a_dst.h_file)) { ++ au_read_post(a_src.inode, a_src.h_file); ++ goto out_si; ++ } ++ } else { ++ wpre.lsc = AuLsc_FI_1; ++ a_dst.h_file = au_write_pre(dst, /*do_ready*/1, &wpre); ++ err = PTR_ERR(a_dst.h_file); ++ if (IS_ERR(a_dst.h_file)) ++ goto out_si; ++ ++ a_src.h_file = au_read_pre(src, /*keep_fi*/1, AuLsc_FI_2); ++ err = PTR_ERR(a_src.h_file); ++ if (IS_ERR(a_src.h_file)) { ++ au_write_post(a_dst.inode, a_dst.h_file, &wpre, ++ /*written*/0); ++ goto out_si; ++ } ++ } ++ ++ err = -EXDEV; ++ a_src.h_sb = file_inode(a_src.h_file)->i_sb; ++ a_dst.h_sb = file_inode(a_dst.h_file)->i_sb; ++ if (unlikely(a_src.h_sb != a_dst.h_sb)) { ++ AuDbgFile(src); ++ AuDbgFile(dst); ++ goto out_file; ++ } ++ ++ err = vfsub_copy_file_range(a_src.h_file, src_pos, a_dst.h_file, ++ dst_pos, len, flags); ++ ++out_file: ++ au_write_post(a_dst.inode, a_dst.h_file, &wpre, err); ++ fi_read_unlock(src); ++ au_read_post(a_src.inode, a_src.h_file); ++out_si: ++ si_read_unlock(a_dst.inode->i_sb); ++ inode_unlock(a_dst.inode); ++out: ++ return err; ++#undef a_src ++#undef a_dst ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * The locking order around current->mmap_sem. ++ * - in most and regular cases ++ * file I/O syscall -- aufs_read() or something ++ * -- si_rwsem for read -- mmap_sem ++ * (Note that [fdi]i_rwsem are released before mmap_sem). ++ * - in mmap case ++ * mmap(2) -- mmap_sem -- aufs_mmap() -- si_rwsem for read -- [fdi]i_rwsem ++ * This AB-BA order is definitely bad, but is not a problem since "si_rwsem for ++ * read" allows multiple processes to acquire it and [fdi]i_rwsem are not held ++ * in file I/O. Aufs needs to stop lockdep in aufs_mmap() though. ++ * It means that when aufs acquires si_rwsem for write, the process should never ++ * acquire mmap_sem. ++ * ++ * Actually aufs_iterate() holds [fdi]i_rwsem before mmap_sem, but this is not a ++ * problem either since any directory is not able to be mmap-ed. ++ * The similar scenario is applied to aufs_readlink() too. ++ */ ++ ++#if 0 /* stop calling security_file_mmap() */ ++/* cf. linux/include/linux/mman.h: calc_vm_prot_bits() */ ++#define AuConv_VM_PROT(f, b) _calc_vm_trans(f, VM_##b, PROT_##b) ++ ++static unsigned long au_arch_prot_conv(unsigned long flags) ++{ ++ /* currently ppc64 only */ ++#ifdef CONFIG_PPC64 ++ /* cf. linux/arch/powerpc/include/asm/mman.h */ ++ AuDebugOn(arch_calc_vm_prot_bits(-1) != VM_SAO); ++ return AuConv_VM_PROT(flags, SAO); ++#else ++ AuDebugOn(arch_calc_vm_prot_bits(-1)); ++ return 0; ++#endif ++} ++ ++static unsigned long au_prot_conv(unsigned long flags) ++{ ++ return AuConv_VM_PROT(flags, READ) ++ | AuConv_VM_PROT(flags, WRITE) ++ | AuConv_VM_PROT(flags, EXEC) ++ | au_arch_prot_conv(flags); ++} ++ ++/* cf. linux/include/linux/mman.h: calc_vm_flag_bits() */ ++#define AuConv_VM_MAP(f, b) _calc_vm_trans(f, VM_##b, MAP_##b) ++ ++static unsigned long au_flag_conv(unsigned long flags) ++{ ++ return AuConv_VM_MAP(flags, GROWSDOWN) ++ | AuConv_VM_MAP(flags, DENYWRITE) ++ | AuConv_VM_MAP(flags, LOCKED); ++} ++#endif ++ ++static int aufs_mmap(struct file *file, struct vm_area_struct *vma) ++{ ++ int err; ++ const unsigned char wlock ++ = (file->f_mode & FMODE_WRITE) && (vma->vm_flags & VM_SHARED); ++ struct super_block *sb; ++ struct file *h_file; ++ struct inode *inode; ++ ++ AuDbgVmRegion(file, vma); ++ ++ inode = file_inode(file); ++ sb = inode->i_sb; ++ lockdep_off(); ++ si_read_lock(sb, AuLock_NOPLMW); ++ ++ h_file = au_write_pre(file, wlock, /*wpre*/NULL); ++ lockdep_on(); ++ err = PTR_ERR(h_file); ++ if (IS_ERR(h_file)) ++ goto out; ++ ++ err = 0; ++ au_set_mmapped(file); ++ au_vm_file_reset(vma, h_file); ++ /* ++ * we cannot call security_mmap_file() here since it may acquire ++ * mmap_sem or i_mutex. ++ * ++ * err = security_mmap_file(h_file, au_prot_conv(vma->vm_flags), ++ * au_flag_conv(vma->vm_flags)); ++ */ ++ if (!err) ++ err = call_mmap(h_file, vma); ++ if (!err) { ++ au_vm_prfile_set(vma, file); ++ fsstack_copy_attr_atime(inode, file_inode(h_file)); ++ goto out_fput; /* success */ ++ } ++ au_unset_mmapped(file); ++ au_vm_file_reset(vma, file); ++ ++out_fput: ++ lockdep_off(); ++ ii_write_unlock(inode); ++ lockdep_on(); ++ fput(h_file); ++out: ++ lockdep_off(); ++ si_read_unlock(sb); ++ lockdep_on(); ++ AuTraceErr(err); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int aufs_fsync_nondir(struct file *file, loff_t start, loff_t end, ++ int datasync) ++{ ++ int err; ++ struct au_write_pre wpre; ++ struct inode *inode; ++ struct file *h_file; ++ ++ err = 0; /* -EBADF; */ /* posix? */ ++ if (unlikely(!(file->f_mode & FMODE_WRITE))) ++ goto out; ++ ++ inode = file_inode(file); ++ au_mtx_and_read_lock(inode); ++ ++ wpre.lsc = 0; ++ h_file = au_write_pre(file, /*do_ready*/1, &wpre); ++ err = PTR_ERR(h_file); ++ if (IS_ERR(h_file)) ++ goto out_unlock; ++ ++ err = vfsub_fsync(h_file, &h_file->f_path, datasync); ++ au_write_post(inode, h_file, &wpre, /*written*/0); ++ ++out_unlock: ++ si_read_unlock(inode->i_sb); ++ inode_unlock(inode); ++out: ++ return err; ++} ++ ++static int aufs_fasync(int fd, struct file *file, int flag) ++{ ++ int err; ++ struct file *h_file; ++ struct super_block *sb; ++ ++ sb = file->f_path.dentry->d_sb; ++ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); ++ ++ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0); ++ err = PTR_ERR(h_file); ++ if (IS_ERR(h_file)) ++ goto out; ++ ++ if (h_file->f_op->fasync) ++ err = h_file->f_op->fasync(fd, h_file, flag); ++ fput(h_file); /* instead of au_read_post() */ ++ ++out: ++ si_read_unlock(sb); ++ return err; ++} ++ ++static int aufs_setfl(struct file *file, unsigned long arg) ++{ ++ int err; ++ struct file *h_file; ++ struct super_block *sb; ++ ++ sb = file->f_path.dentry->d_sb; ++ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); ++ ++ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0); ++ err = PTR_ERR(h_file); ++ if (IS_ERR(h_file)) ++ goto out; ++ ++ /* stop calling h_file->fasync */ ++ arg |= vfsub_file_flags(file) & FASYNC; ++ err = setfl(/*unused fd*/-1, h_file, arg); ++ fput(h_file); /* instead of au_read_post() */ ++ ++out: ++ si_read_unlock(sb); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* no one supports this operation, currently */ ++#if 0 ++static ssize_t aufs_sendpage(struct file *file, struct page *page, int offset, ++ size_t len, loff_t *pos, int more) ++{ ++} ++#endif ++ ++/* ---------------------------------------------------------------------- */ ++ ++const struct file_operations aufs_file_fop = { ++ .owner = THIS_MODULE, ++ ++ .llseek = default_llseek, ++ ++ .read = aufs_read, ++ .write = aufs_write, ++ .read_iter = aufs_read_iter, ++ .write_iter = aufs_write_iter, ++ ++#ifdef CONFIG_AUFS_POLL ++ .poll = aufs_poll, ++#endif ++ .unlocked_ioctl = aufs_ioctl_nondir, ++#ifdef CONFIG_COMPAT ++ .compat_ioctl = aufs_compat_ioctl_nondir, ++#endif ++ .mmap = aufs_mmap, ++ .open = aufs_open_nondir, ++ .flush = aufs_flush_nondir, ++ .release = aufs_release_nondir, ++ .fsync = aufs_fsync_nondir, ++ .fasync = aufs_fasync, ++ /* .sendpage = aufs_sendpage, */ ++ .setfl = aufs_setfl, ++ .splice_write = aufs_splice_write, ++ .splice_read = aufs_splice_read, ++#if 0 ++ .aio_splice_write = aufs_aio_splice_write, ++ .aio_splice_read = aufs_aio_splice_read, ++#endif ++ .fallocate = aufs_fallocate, ++ .copy_file_range = aufs_copy_file_range ++}; +diff -Nurp linux-5.4/fs/aufs/fstype.h linux-5.4-aufs/fs/aufs/fstype.h +--- linux-5.4/fs/aufs/fstype.h 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/fstype.h 2019-11-28 01:25:59.065925618 +0200 +@@ -0,0 +1,388 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * judging filesystem type ++ */ ++ ++#ifndef __AUFS_FSTYPE_H__ ++#define __AUFS_FSTYPE_H__ ++ ++#ifdef __KERNEL__ ++ ++#include ++#include ++#include ++#include ++ ++static inline int au_test_aufs(struct super_block *sb) ++{ ++ return sb->s_magic == AUFS_SUPER_MAGIC; ++} ++ ++static inline const char *au_sbtype(struct super_block *sb) ++{ ++ return sb->s_type->name; ++} ++ ++static inline int au_test_iso9660(struct super_block *sb __maybe_unused) ++{ ++#if IS_ENABLED(CONFIG_ISO9660_FS) ++ return sb->s_magic == ISOFS_SUPER_MAGIC; ++#else ++ return 0; ++#endif ++} ++ ++static inline int au_test_romfs(struct super_block *sb __maybe_unused) ++{ ++#if IS_ENABLED(CONFIG_ROMFS_FS) ++ return sb->s_magic == ROMFS_MAGIC; ++#else ++ return 0; ++#endif ++} ++ ++static inline int au_test_cramfs(struct super_block *sb __maybe_unused) ++{ ++#if IS_ENABLED(CONFIG_CRAMFS) ++ return sb->s_magic == CRAMFS_MAGIC; ++#endif ++ return 0; ++} ++ ++static inline int au_test_nfs(struct super_block *sb __maybe_unused) ++{ ++#if IS_ENABLED(CONFIG_NFS_FS) ++ return sb->s_magic == NFS_SUPER_MAGIC; ++#else ++ return 0; ++#endif ++} ++ ++static inline int au_test_fuse(struct super_block *sb __maybe_unused) ++{ ++#if IS_ENABLED(CONFIG_FUSE_FS) ++ return sb->s_magic == FUSE_SUPER_MAGIC; ++#else ++ return 0; ++#endif ++} ++ ++static inline int au_test_xfs(struct super_block *sb __maybe_unused) ++{ ++#if IS_ENABLED(CONFIG_XFS_FS) ++ return sb->s_magic == XFS_SB_MAGIC; ++#else ++ return 0; ++#endif ++} ++ ++static inline int au_test_tmpfs(struct super_block *sb __maybe_unused) ++{ ++#ifdef CONFIG_TMPFS ++ return sb->s_magic == TMPFS_MAGIC; ++#else ++ return 0; ++#endif ++} ++ ++static inline int au_test_ecryptfs(struct super_block *sb __maybe_unused) ++{ ++#if IS_ENABLED(CONFIG_ECRYPT_FS) ++ return !strcmp(au_sbtype(sb), "ecryptfs"); ++#else ++ return 0; ++#endif ++} ++ ++static inline int au_test_ramfs(struct super_block *sb) ++{ ++ return sb->s_magic == RAMFS_MAGIC; ++} ++ ++static inline int au_test_ubifs(struct super_block *sb __maybe_unused) ++{ ++#if IS_ENABLED(CONFIG_UBIFS_FS) ++ return sb->s_magic == UBIFS_SUPER_MAGIC; ++#else ++ return 0; ++#endif ++} ++ ++static inline int au_test_procfs(struct super_block *sb __maybe_unused) ++{ ++#ifdef CONFIG_PROC_FS ++ return sb->s_magic == PROC_SUPER_MAGIC; ++#else ++ return 0; ++#endif ++} ++ ++static inline int au_test_sysfs(struct super_block *sb __maybe_unused) ++{ ++#ifdef CONFIG_SYSFS ++ return sb->s_magic == SYSFS_MAGIC; ++#else ++ return 0; ++#endif ++} ++ ++static inline int au_test_configfs(struct super_block *sb __maybe_unused) ++{ ++#if IS_ENABLED(CONFIG_CONFIGFS_FS) ++ return sb->s_magic == CONFIGFS_MAGIC; ++#else ++ return 0; ++#endif ++} ++ ++static inline int au_test_minix(struct super_block *sb __maybe_unused) ++{ ++#if IS_ENABLED(CONFIG_MINIX_FS) ++ return sb->s_magic == MINIX3_SUPER_MAGIC ++ || sb->s_magic == MINIX2_SUPER_MAGIC ++ || sb->s_magic == MINIX2_SUPER_MAGIC2 ++ || sb->s_magic == MINIX_SUPER_MAGIC ++ || sb->s_magic == MINIX_SUPER_MAGIC2; ++#else ++ return 0; ++#endif ++} ++ ++static inline int au_test_fat(struct super_block *sb __maybe_unused) ++{ ++#if IS_ENABLED(CONFIG_FAT_FS) ++ return sb->s_magic == MSDOS_SUPER_MAGIC; ++#else ++ return 0; ++#endif ++} ++ ++static inline int au_test_msdos(struct super_block *sb) ++{ ++ return au_test_fat(sb); ++} ++ ++static inline int au_test_vfat(struct super_block *sb) ++{ ++ return au_test_fat(sb); ++} ++ ++static inline int au_test_securityfs(struct super_block *sb __maybe_unused) ++{ ++#ifdef CONFIG_SECURITYFS ++ return sb->s_magic == SECURITYFS_MAGIC; ++#else ++ return 0; ++#endif ++} ++ ++static inline int au_test_squashfs(struct super_block *sb __maybe_unused) ++{ ++#if IS_ENABLED(CONFIG_SQUASHFS) ++ return sb->s_magic == SQUASHFS_MAGIC; ++#else ++ return 0; ++#endif ++} ++ ++static inline int au_test_btrfs(struct super_block *sb __maybe_unused) ++{ ++#if IS_ENABLED(CONFIG_BTRFS_FS) ++ return sb->s_magic == BTRFS_SUPER_MAGIC; ++#else ++ return 0; ++#endif ++} ++ ++static inline int au_test_xenfs(struct super_block *sb __maybe_unused) ++{ ++#if IS_ENABLED(CONFIG_XENFS) ++ return sb->s_magic == XENFS_SUPER_MAGIC; ++#else ++ return 0; ++#endif ++} ++ ++static inline int au_test_debugfs(struct super_block *sb __maybe_unused) ++{ ++#ifdef CONFIG_DEBUG_FS ++ return sb->s_magic == DEBUGFS_MAGIC; ++#else ++ return 0; ++#endif ++} ++ ++static inline int au_test_nilfs(struct super_block *sb __maybe_unused) ++{ ++#if IS_ENABLED(CONFIG_NILFS) ++ return sb->s_magic == NILFS_SUPER_MAGIC; ++#else ++ return 0; ++#endif ++} ++ ++static inline int au_test_hfsplus(struct super_block *sb __maybe_unused) ++{ ++#if IS_ENABLED(CONFIG_HFSPLUS_FS) ++ return sb->s_magic == HFSPLUS_SUPER_MAGIC; ++#else ++ return 0; ++#endif ++} ++ ++/* ---------------------------------------------------------------------- */ ++/* ++ * they can't be an aufs branch. ++ */ ++static inline int au_test_fs_unsuppoted(struct super_block *sb) ++{ ++ return ++#ifndef CONFIG_AUFS_BR_RAMFS ++ au_test_ramfs(sb) || ++#endif ++ au_test_procfs(sb) ++ || au_test_sysfs(sb) ++ || au_test_configfs(sb) ++ || au_test_debugfs(sb) ++ || au_test_securityfs(sb) ++ || au_test_xenfs(sb) ++ || au_test_ecryptfs(sb) ++ /* || !strcmp(au_sbtype(sb), "unionfs") */ ++ || au_test_aufs(sb); /* will be supported in next version */ ++} ++ ++static inline int au_test_fs_remote(struct super_block *sb) ++{ ++ return !au_test_tmpfs(sb) ++#ifdef CONFIG_AUFS_BR_RAMFS ++ && !au_test_ramfs(sb) ++#endif ++ && !(sb->s_type->fs_flags & FS_REQUIRES_DEV); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * Note: these functions (below) are created after reading ->getattr() in all ++ * filesystems under linux/fs. it means we have to do so in every update... ++ */ ++ ++/* ++ * some filesystems require getattr to refresh the inode attributes before ++ * referencing. ++ * in most cases, we can rely on the inode attribute in NFS (or every remote fs) ++ * and leave the work for d_revalidate() ++ */ ++static inline int au_test_fs_refresh_iattr(struct super_block *sb) ++{ ++ return au_test_nfs(sb) ++ || au_test_fuse(sb) ++ /* || au_test_btrfs(sb) */ /* untested */ ++ ; ++} ++ ++/* ++ * filesystems which don't maintain i_size or i_blocks. ++ */ ++static inline int au_test_fs_bad_iattr_size(struct super_block *sb) ++{ ++ return au_test_xfs(sb) ++ || au_test_btrfs(sb) ++ || au_test_ubifs(sb) ++ || au_test_hfsplus(sb) /* maintained, but incorrect */ ++ /* || au_test_minix(sb) */ /* untested */ ++ ; ++} ++ ++/* ++ * filesystems which don't store the correct value in some of their inode ++ * attributes. ++ */ ++static inline int au_test_fs_bad_iattr(struct super_block *sb) ++{ ++ return au_test_fs_bad_iattr_size(sb) ++ || au_test_fat(sb) ++ || au_test_msdos(sb) ++ || au_test_vfat(sb); ++} ++ ++/* they don't check i_nlink in link(2) */ ++static inline int au_test_fs_no_limit_nlink(struct super_block *sb) ++{ ++ return au_test_tmpfs(sb) ++#ifdef CONFIG_AUFS_BR_RAMFS ++ || au_test_ramfs(sb) ++#endif ++ || au_test_ubifs(sb) ++ || au_test_hfsplus(sb); ++} ++ ++/* ++ * filesystems which sets S_NOATIME and S_NOCMTIME. ++ */ ++static inline int au_test_fs_notime(struct super_block *sb) ++{ ++ return au_test_nfs(sb) ++ || au_test_fuse(sb) ++ || au_test_ubifs(sb) ++ ; ++} ++ ++/* temporary support for i#1 in cramfs */ ++static inline int au_test_fs_unique_ino(struct inode *inode) ++{ ++ if (au_test_cramfs(inode->i_sb)) ++ return inode->i_ino != 1; ++ return 1; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * the filesystem where the xino files placed must support i/o after unlink and ++ * maintain i_size and i_blocks. ++ */ ++static inline int au_test_fs_bad_xino(struct super_block *sb) ++{ ++ return au_test_fs_remote(sb) ++ || au_test_fs_bad_iattr_size(sb) ++ /* don't want unnecessary work for xino */ ++ || au_test_aufs(sb) ++ || au_test_ecryptfs(sb) ++ || au_test_nilfs(sb); ++} ++ ++static inline int au_test_fs_trunc_xino(struct super_block *sb) ++{ ++ return au_test_tmpfs(sb) ++ || au_test_ramfs(sb); ++} ++ ++/* ++ * test if the @sb is real-readonly. ++ */ ++static inline int au_test_fs_rr(struct super_block *sb) ++{ ++ return au_test_squashfs(sb) ++ || au_test_iso9660(sb) ++ || au_test_cramfs(sb) ++ || au_test_romfs(sb); ++} ++ ++/* ++ * test if the @inode is nfs with 'noacl' option ++ * NFS always sets SB_POSIXACL regardless its mount option 'noacl.' ++ */ ++static inline int au_test_nfs_noacl(struct inode *inode) ++{ ++ return au_test_nfs(inode->i_sb) ++ /* && IS_POSIXACL(inode) */ ++ && !nfs_server_capable(inode, NFS_CAP_ACLS); ++} ++ ++#endif /* __KERNEL__ */ ++#endif /* __AUFS_FSTYPE_H__ */ +diff -Nurp linux-5.4/fs/aufs/hbl.h linux-5.4-aufs/fs/aufs/hbl.h +--- linux-5.4/fs/aufs/hbl.h 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/hbl.h 2019-11-28 01:25:59.065925618 +0200 +@@ -0,0 +1,52 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2017-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * helpers for hlist_bl.h ++ */ ++ ++#ifndef __AUFS_HBL_H__ ++#define __AUFS_HBL_H__ ++ ++#ifdef __KERNEL__ ++ ++#include ++ ++static inline void au_hbl_add(struct hlist_bl_node *node, ++ struct hlist_bl_head *hbl) ++{ ++ hlist_bl_lock(hbl); ++ hlist_bl_add_head(node, hbl); ++ hlist_bl_unlock(hbl); ++} ++ ++static inline void au_hbl_del(struct hlist_bl_node *node, ++ struct hlist_bl_head *hbl) ++{ ++ hlist_bl_lock(hbl); ++ hlist_bl_del(node); ++ hlist_bl_unlock(hbl); ++} ++ ++#define au_hbl_for_each(pos, head) \ ++ for (pos = hlist_bl_first(head); \ ++ pos; \ ++ pos = pos->next) ++ ++static inline unsigned long au_hbl_count(struct hlist_bl_head *hbl) ++{ ++ unsigned long cnt; ++ struct hlist_bl_node *pos; ++ ++ cnt = 0; ++ hlist_bl_lock(hbl); ++ au_hbl_for_each(pos, hbl) ++ cnt++; ++ hlist_bl_unlock(hbl); ++ return cnt; ++} ++ ++#endif /* __KERNEL__ */ ++#endif /* __AUFS_HBL_H__ */ +diff -Nurp linux-5.4/fs/aufs/hfsnotify.c linux-5.4-aufs/fs/aufs/hfsnotify.c +--- linux-5.4/fs/aufs/hfsnotify.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/hfsnotify.c 2019-11-28 01:25:59.065925618 +0200 +@@ -0,0 +1,275 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * fsnotify for the lower directories ++ */ ++ ++#include "aufs.h" ++ ++/* FS_IN_IGNORED is unnecessary */ ++static const __u32 AuHfsnMask = (FS_MOVED_TO | FS_MOVED_FROM | FS_DELETE ++ | FS_CREATE | FS_EVENT_ON_CHILD); ++static DECLARE_WAIT_QUEUE_HEAD(au_hfsn_wq); ++static __cacheline_aligned_in_smp atomic64_t au_hfsn_ifree = ATOMIC64_INIT(0); ++ ++static void au_hfsn_free_mark(struct fsnotify_mark *mark) ++{ ++ struct au_hnotify *hn = container_of(mark, struct au_hnotify, ++ hn_mark); ++ /* AuDbg("here\n"); */ ++ au_cache_free_hnotify(hn); ++ smp_mb__before_atomic(); /* for atomic64_dec */ ++ if (atomic64_dec_and_test(&au_hfsn_ifree)) ++ wake_up(&au_hfsn_wq); ++} ++ ++static int au_hfsn_alloc(struct au_hinode *hinode) ++{ ++ int err; ++ struct au_hnotify *hn; ++ struct super_block *sb; ++ struct au_branch *br; ++ struct fsnotify_mark *mark; ++ aufs_bindex_t bindex; ++ ++ hn = hinode->hi_notify; ++ sb = hn->hn_aufs_inode->i_sb; ++ bindex = au_br_index(sb, hinode->hi_id); ++ br = au_sbr(sb, bindex); ++ AuDebugOn(!br->br_hfsn); ++ ++ mark = &hn->hn_mark; ++ fsnotify_init_mark(mark, br->br_hfsn->hfsn_group); ++ mark->mask = AuHfsnMask; ++ /* ++ * by udba rename or rmdir, aufs assign a new inode to the known ++ * h_inode, so specify 1 to allow dups. ++ */ ++ lockdep_off(); ++ err = fsnotify_add_inode_mark(mark, hinode->hi_inode, /*allow_dups*/1); ++ lockdep_on(); ++ ++ return err; ++} ++ ++static int au_hfsn_free(struct au_hinode *hinode, struct au_hnotify *hn) ++{ ++ struct fsnotify_mark *mark; ++ unsigned long long ull; ++ struct fsnotify_group *group; ++ ++ ull = atomic64_inc_return(&au_hfsn_ifree); ++ BUG_ON(!ull); ++ ++ mark = &hn->hn_mark; ++ spin_lock(&mark->lock); ++ group = mark->group; ++ fsnotify_get_group(group); ++ spin_unlock(&mark->lock); ++ lockdep_off(); ++ fsnotify_destroy_mark(mark, group); ++ fsnotify_put_mark(mark); ++ fsnotify_put_group(group); ++ lockdep_on(); ++ ++ /* free hn by myself */ ++ return 0; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static void au_hfsn_ctl(struct au_hinode *hinode, int do_set) ++{ ++ struct fsnotify_mark *mark; ++ ++ mark = &hinode->hi_notify->hn_mark; ++ spin_lock(&mark->lock); ++ if (do_set) { ++ AuDebugOn(mark->mask & AuHfsnMask); ++ mark->mask |= AuHfsnMask; ++ } else { ++ AuDebugOn(!(mark->mask & AuHfsnMask)); ++ mark->mask &= ~AuHfsnMask; ++ } ++ spin_unlock(&mark->lock); ++ /* fsnotify_recalc_inode_mask(hinode->hi_inode); */ ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* #define AuDbgHnotify */ ++#ifdef AuDbgHnotify ++static char *au_hfsn_name(u32 mask) ++{ ++#ifdef CONFIG_AUFS_DEBUG ++#define test_ret(flag) \ ++ do { \ ++ if (mask & flag) \ ++ return #flag; \ ++ } while (0) ++ test_ret(FS_ACCESS); ++ test_ret(FS_MODIFY); ++ test_ret(FS_ATTRIB); ++ test_ret(FS_CLOSE_WRITE); ++ test_ret(FS_CLOSE_NOWRITE); ++ test_ret(FS_OPEN); ++ test_ret(FS_MOVED_FROM); ++ test_ret(FS_MOVED_TO); ++ test_ret(FS_CREATE); ++ test_ret(FS_DELETE); ++ test_ret(FS_DELETE_SELF); ++ test_ret(FS_MOVE_SELF); ++ test_ret(FS_UNMOUNT); ++ test_ret(FS_Q_OVERFLOW); ++ test_ret(FS_IN_IGNORED); ++ test_ret(FS_ISDIR); ++ test_ret(FS_IN_ONESHOT); ++ test_ret(FS_EVENT_ON_CHILD); ++ return ""; ++#undef test_ret ++#else ++ return "??"; ++#endif ++} ++#endif ++ ++/* ---------------------------------------------------------------------- */ ++ ++static void au_hfsn_free_group(struct fsnotify_group *group) ++{ ++ struct au_br_hfsnotify *hfsn = group->private; ++ ++ /* AuDbg("here\n"); */ ++ au_kfree_try_rcu(hfsn); ++} ++ ++static int au_hfsn_handle_event(struct fsnotify_group *group, ++ struct inode *inode, ++ u32 mask, const void *data, int data_type, ++ const struct qstr *file_name, u32 cookie, ++ struct fsnotify_iter_info *iter_info) ++{ ++ int err; ++ struct au_hnotify *hnotify; ++ struct inode *h_dir, *h_inode; ++ struct fsnotify_mark *inode_mark; ++ ++ AuDebugOn(data_type != FSNOTIFY_EVENT_INODE); ++ ++ err = 0; ++ /* if FS_UNMOUNT happens, there must be another bug */ ++ AuDebugOn(mask & FS_UNMOUNT); ++ if (mask & (FS_IN_IGNORED | FS_UNMOUNT)) ++ goto out; ++ ++ h_dir = inode; ++ h_inode = NULL; ++#ifdef AuDbgHnotify ++ au_debug_on(); ++ if (1 || h_child_qstr.len != sizeof(AUFS_XINO_FNAME) - 1 ++ || strncmp(h_child_qstr.name, AUFS_XINO_FNAME, h_child_qstr.len)) { ++ AuDbg("i%lu, mask 0x%x %s, hcname %.*s, hi%lu\n", ++ h_dir->i_ino, mask, au_hfsn_name(mask), ++ AuLNPair(&h_child_qstr), h_inode ? h_inode->i_ino : 0); ++ /* WARN_ON(1); */ ++ } ++ au_debug_off(); ++#endif ++ ++ inode_mark = fsnotify_iter_inode_mark(iter_info); ++ AuDebugOn(!inode_mark); ++ hnotify = container_of(inode_mark, struct au_hnotify, hn_mark); ++ err = au_hnotify(h_dir, hnotify, mask, file_name, h_inode); ++ ++out: ++ return err; ++} ++ ++static struct fsnotify_ops au_hfsn_ops = { ++ .handle_event = au_hfsn_handle_event, ++ .free_group_priv = au_hfsn_free_group, ++ .free_mark = au_hfsn_free_mark ++}; ++ ++/* ---------------------------------------------------------------------- */ ++ ++static void au_hfsn_fin_br(struct au_branch *br) ++{ ++ struct au_br_hfsnotify *hfsn; ++ ++ hfsn = br->br_hfsn; ++ if (hfsn) { ++ lockdep_off(); ++ fsnotify_put_group(hfsn->hfsn_group); ++ lockdep_on(); ++ } ++} ++ ++static int au_hfsn_init_br(struct au_branch *br, int perm) ++{ ++ int err; ++ struct fsnotify_group *group; ++ struct au_br_hfsnotify *hfsn; ++ ++ err = 0; ++ br->br_hfsn = NULL; ++ if (!au_br_hnotifyable(perm)) ++ goto out; ++ ++ err = -ENOMEM; ++ hfsn = kmalloc(sizeof(*hfsn), GFP_NOFS); ++ if (unlikely(!hfsn)) ++ goto out; ++ ++ err = 0; ++ group = fsnotify_alloc_group(&au_hfsn_ops); ++ if (IS_ERR(group)) { ++ err = PTR_ERR(group); ++ pr_err("fsnotify_alloc_group() failed, %d\n", err); ++ goto out_hfsn; ++ } ++ ++ group->private = hfsn; ++ hfsn->hfsn_group = group; ++ br->br_hfsn = hfsn; ++ goto out; /* success */ ++ ++out_hfsn: ++ au_kfree_try_rcu(hfsn); ++out: ++ return err; ++} ++ ++static int au_hfsn_reset_br(unsigned int udba, struct au_branch *br, int perm) ++{ ++ int err; ++ ++ err = 0; ++ if (!br->br_hfsn) ++ err = au_hfsn_init_br(br, perm); ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static void au_hfsn_fin(void) ++{ ++ AuDbg("au_hfsn_ifree %lld\n", (long long)atomic64_read(&au_hfsn_ifree)); ++ wait_event(au_hfsn_wq, !atomic64_read(&au_hfsn_ifree)); ++} ++ ++const struct au_hnotify_op au_hnotify_op = { ++ .ctl = au_hfsn_ctl, ++ .alloc = au_hfsn_alloc, ++ .free = au_hfsn_free, ++ ++ .fin = au_hfsn_fin, ++ ++ .reset_br = au_hfsn_reset_br, ++ .fin_br = au_hfsn_fin_br, ++ .init_br = au_hfsn_init_br ++}; +diff -Nurp linux-5.4/fs/aufs/hfsplus.c linux-5.4-aufs/fs/aufs/hfsplus.c +--- linux-5.4/fs/aufs/hfsplus.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/hfsplus.c 2019-11-28 01:25:59.065925618 +0200 +@@ -0,0 +1,47 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2010-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * special support for filesystems which acquires an inode mutex ++ * at final closing a file, eg, hfsplus. ++ * ++ * This trick is very simple and stupid, just to open the file before really ++ * necessary open to tell hfsplus that this is not the final closing. ++ * The caller should call au_h_open_pre() after acquiring the inode mutex, ++ * and au_h_open_post() after releasing it. ++ */ ++ ++#include "aufs.h" ++ ++struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex, ++ int force_wr) ++{ ++ struct file *h_file; ++ struct dentry *h_dentry; ++ ++ h_dentry = au_h_dptr(dentry, bindex); ++ AuDebugOn(!h_dentry); ++ AuDebugOn(d_is_negative(h_dentry)); ++ ++ h_file = NULL; ++ if (au_test_hfsplus(h_dentry->d_sb) ++ && d_is_reg(h_dentry)) ++ h_file = au_h_open(dentry, bindex, ++ O_RDONLY | O_NOATIME | O_LARGEFILE, ++ /*file*/NULL, force_wr); ++ return h_file; ++} ++ ++void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex, ++ struct file *h_file) ++{ ++ struct au_branch *br; ++ ++ if (h_file) { ++ fput(h_file); ++ br = au_sbr(dentry->d_sb, bindex); ++ au_lcnt_dec(&br->br_nfiles); ++ } ++} +diff -Nurp linux-5.4/fs/aufs/hnotify.c linux-5.4-aufs/fs/aufs/hnotify.c +--- linux-5.4/fs/aufs/hnotify.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/hnotify.c 2019-11-28 01:25:59.065925618 +0200 +@@ -0,0 +1,708 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * abstraction to notify the direct changes on lower directories ++ */ ++ ++/* #include */ ++#include "aufs.h" ++ ++int au_hn_alloc(struct au_hinode *hinode, struct inode *inode) ++{ ++ int err; ++ struct au_hnotify *hn; ++ ++ err = -ENOMEM; ++ hn = au_cache_alloc_hnotify(); ++ if (hn) { ++ hn->hn_aufs_inode = inode; ++ hinode->hi_notify = hn; ++ err = au_hnotify_op.alloc(hinode); ++ AuTraceErr(err); ++ if (unlikely(err)) { ++ hinode->hi_notify = NULL; ++ au_cache_free_hnotify(hn); ++ /* ++ * The upper dir was removed by udba, but the same named ++ * dir left. In this case, aufs assigns a new inode ++ * number and set the monitor again. ++ * For the lower dir, the old monitor is still left. ++ */ ++ if (err == -EEXIST) ++ err = 0; ++ } ++ } ++ ++ AuTraceErr(err); ++ return err; ++} ++ ++void au_hn_free(struct au_hinode *hinode) ++{ ++ struct au_hnotify *hn; ++ ++ hn = hinode->hi_notify; ++ if (hn) { ++ hinode->hi_notify = NULL; ++ if (au_hnotify_op.free(hinode, hn)) ++ au_cache_free_hnotify(hn); ++ } ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++void au_hn_ctl(struct au_hinode *hinode, int do_set) ++{ ++ if (hinode->hi_notify) ++ au_hnotify_op.ctl(hinode, do_set); ++} ++ ++void au_hn_reset(struct inode *inode, unsigned int flags) ++{ ++ aufs_bindex_t bindex, bbot; ++ struct inode *hi; ++ struct dentry *iwhdentry; ++ ++ bbot = au_ibbot(inode); ++ for (bindex = au_ibtop(inode); bindex <= bbot; bindex++) { ++ hi = au_h_iptr(inode, bindex); ++ if (!hi) ++ continue; ++ ++ /* inode_lock_nested(hi, AuLsc_I_CHILD); */ ++ iwhdentry = au_hi_wh(inode, bindex); ++ if (iwhdentry) ++ dget(iwhdentry); ++ au_igrab(hi); ++ au_set_h_iptr(inode, bindex, NULL, 0); ++ au_set_h_iptr(inode, bindex, au_igrab(hi), ++ flags & ~AuHi_XINO); ++ iput(hi); ++ dput(iwhdentry); ++ /* inode_unlock(hi); */ ++ } ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int hn_xino(struct inode *inode, struct inode *h_inode) ++{ ++ int err; ++ aufs_bindex_t bindex, bbot, bfound, btop; ++ struct inode *h_i; ++ ++ err = 0; ++ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) { ++ pr_warn("branch root dir was changed\n"); ++ goto out; ++ } ++ ++ bfound = -1; ++ bbot = au_ibbot(inode); ++ btop = au_ibtop(inode); ++#if 0 /* reserved for future use */ ++ if (bindex == bbot) { ++ /* keep this ino in rename case */ ++ goto out; ++ } ++#endif ++ for (bindex = btop; bindex <= bbot; bindex++) ++ if (au_h_iptr(inode, bindex) == h_inode) { ++ bfound = bindex; ++ break; ++ } ++ if (bfound < 0) ++ goto out; ++ ++ for (bindex = btop; bindex <= bbot; bindex++) { ++ h_i = au_h_iptr(inode, bindex); ++ if (!h_i) ++ continue; ++ ++ err = au_xino_write(inode->i_sb, bindex, h_i->i_ino, /*ino*/0); ++ /* ignore this error */ ++ /* bad action? */ ++ } ++ ++ /* children inode number will be broken */ ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++static int hn_gen_tree(struct dentry *dentry) ++{ ++ int err, i, j, ndentry; ++ struct au_dcsub_pages dpages; ++ struct au_dpage *dpage; ++ struct dentry **dentries; ++ ++ err = au_dpages_init(&dpages, GFP_NOFS); ++ if (unlikely(err)) ++ goto out; ++ err = au_dcsub_pages(&dpages, dentry, NULL, NULL); ++ if (unlikely(err)) ++ goto out_dpages; ++ ++ for (i = 0; i < dpages.ndpage; i++) { ++ dpage = dpages.dpages + i; ++ dentries = dpage->dentries; ++ ndentry = dpage->ndentry; ++ for (j = 0; j < ndentry; j++) { ++ struct dentry *d; ++ ++ d = dentries[j]; ++ if (IS_ROOT(d)) ++ continue; ++ ++ au_digen_dec(d); ++ if (d_really_is_positive(d)) ++ /* todo: reset children xino? ++ cached children only? */ ++ au_iigen_dec(d_inode(d)); ++ } ++ } ++ ++out_dpages: ++ au_dpages_free(&dpages); ++ ++#if 0 ++ /* discard children */ ++ dentry_unhash(dentry); ++ dput(dentry); ++#endif ++out: ++ return err; ++} ++ ++/* ++ * return 0 if processed. ++ */ ++static int hn_gen_by_inode(char *name, unsigned int nlen, struct inode *inode, ++ const unsigned int isdir) ++{ ++ int err; ++ struct dentry *d; ++ struct qstr *dname; ++ ++ err = 1; ++ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) { ++ pr_warn("branch root dir was changed\n"); ++ err = 0; ++ goto out; ++ } ++ ++ if (!isdir) { ++ AuDebugOn(!name); ++ au_iigen_dec(inode); ++ spin_lock(&inode->i_lock); ++ hlist_for_each_entry(d, &inode->i_dentry, d_u.d_alias) { ++ spin_lock(&d->d_lock); ++ dname = &d->d_name; ++ if (dname->len != nlen ++ && memcmp(dname->name, name, nlen)) { ++ spin_unlock(&d->d_lock); ++ continue; ++ } ++ err = 0; ++ au_digen_dec(d); ++ spin_unlock(&d->d_lock); ++ break; ++ } ++ spin_unlock(&inode->i_lock); ++ } else { ++ au_fset_si(au_sbi(inode->i_sb), FAILED_REFRESH_DIR); ++ d = d_find_any_alias(inode); ++ if (!d) { ++ au_iigen_dec(inode); ++ goto out; ++ } ++ ++ spin_lock(&d->d_lock); ++ dname = &d->d_name; ++ if (dname->len == nlen && !memcmp(dname->name, name, nlen)) { ++ spin_unlock(&d->d_lock); ++ err = hn_gen_tree(d); ++ spin_lock(&d->d_lock); ++ } ++ spin_unlock(&d->d_lock); ++ dput(d); ++ } ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++static int hn_gen_by_name(struct dentry *dentry, const unsigned int isdir) ++{ ++ int err; ++ ++ if (IS_ROOT(dentry)) { ++ pr_warn("branch root dir was changed\n"); ++ return 0; ++ } ++ ++ err = 0; ++ if (!isdir) { ++ au_digen_dec(dentry); ++ if (d_really_is_positive(dentry)) ++ au_iigen_dec(d_inode(dentry)); ++ } else { ++ au_fset_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIR); ++ if (d_really_is_positive(dentry)) ++ err = hn_gen_tree(dentry); ++ } ++ ++ AuTraceErr(err); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* hnotify job flags */ ++#define AuHnJob_XINO0 1 ++#define AuHnJob_GEN (1 << 1) ++#define AuHnJob_DIRENT (1 << 2) ++#define AuHnJob_ISDIR (1 << 3) ++#define AuHnJob_TRYXINO0 (1 << 4) ++#define AuHnJob_MNTPNT (1 << 5) ++#define au_ftest_hnjob(flags, name) ((flags) & AuHnJob_##name) ++#define au_fset_hnjob(flags, name) \ ++ do { (flags) |= AuHnJob_##name; } while (0) ++#define au_fclr_hnjob(flags, name) \ ++ do { (flags) &= ~AuHnJob_##name; } while (0) ++ ++enum { ++ AuHn_CHILD, ++ AuHn_PARENT, ++ AuHnLast ++}; ++ ++struct au_hnotify_args { ++ struct inode *h_dir, *dir, *h_child_inode; ++ u32 mask; ++ unsigned int flags[AuHnLast]; ++ unsigned int h_child_nlen; ++ char h_child_name[]; ++}; ++ ++struct hn_job_args { ++ unsigned int flags; ++ struct inode *inode, *h_inode, *dir, *h_dir; ++ struct dentry *dentry; ++ char *h_name; ++ int h_nlen; ++}; ++ ++static int hn_job(struct hn_job_args *a) ++{ ++ const unsigned int isdir = au_ftest_hnjob(a->flags, ISDIR); ++ int e; ++ ++ /* reset xino */ ++ if (au_ftest_hnjob(a->flags, XINO0) && a->inode) ++ hn_xino(a->inode, a->h_inode); /* ignore this error */ ++ ++ if (au_ftest_hnjob(a->flags, TRYXINO0) ++ && a->inode ++ && a->h_inode) { ++ inode_lock_shared_nested(a->h_inode, AuLsc_I_CHILD); ++ if (!a->h_inode->i_nlink ++ && !(a->h_inode->i_state & I_LINKABLE)) ++ hn_xino(a->inode, a->h_inode); /* ignore this error */ ++ inode_unlock_shared(a->h_inode); ++ } ++ ++ /* make the generation obsolete */ ++ if (au_ftest_hnjob(a->flags, GEN)) { ++ e = -1; ++ if (a->inode) ++ e = hn_gen_by_inode(a->h_name, a->h_nlen, a->inode, ++ isdir); ++ if (e && a->dentry) ++ hn_gen_by_name(a->dentry, isdir); ++ /* ignore this error */ ++ } ++ ++ /* make dir entries obsolete */ ++ if (au_ftest_hnjob(a->flags, DIRENT) && a->inode) { ++ struct au_vdir *vdir; ++ ++ vdir = au_ivdir(a->inode); ++ if (vdir) ++ vdir->vd_jiffy = 0; ++ /* IMustLock(a->inode); */ ++ /* inode_inc_iversion(a->inode); */ ++ } ++ ++ /* can do nothing but warn */ ++ if (au_ftest_hnjob(a->flags, MNTPNT) ++ && a->dentry ++ && d_mountpoint(a->dentry)) ++ pr_warn("mount-point %pd is removed or renamed\n", a->dentry); ++ ++ return 0; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static struct dentry *lookup_wlock_by_name(char *name, unsigned int nlen, ++ struct inode *dir) ++{ ++ struct dentry *dentry, *d, *parent; ++ struct qstr *dname; ++ ++ parent = d_find_any_alias(dir); ++ if (!parent) ++ return NULL; ++ ++ dentry = NULL; ++ spin_lock(&parent->d_lock); ++ list_for_each_entry(d, &parent->d_subdirs, d_child) { ++ /* AuDbg("%pd\n", d); */ ++ spin_lock_nested(&d->d_lock, DENTRY_D_LOCK_NESTED); ++ dname = &d->d_name; ++ if (dname->len != nlen || memcmp(dname->name, name, nlen)) ++ goto cont_unlock; ++ if (au_di(d)) ++ au_digen_dec(d); ++ else ++ goto cont_unlock; ++ if (au_dcount(d) > 0) { ++ dentry = dget_dlock(d); ++ spin_unlock(&d->d_lock); ++ break; ++ } ++ ++cont_unlock: ++ spin_unlock(&d->d_lock); ++ } ++ spin_unlock(&parent->d_lock); ++ dput(parent); ++ ++ if (dentry) ++ di_write_lock_child(dentry); ++ ++ return dentry; ++} ++ ++static struct inode *lookup_wlock_by_ino(struct super_block *sb, ++ aufs_bindex_t bindex, ino_t h_ino) ++{ ++ struct inode *inode; ++ ino_t ino; ++ int err; ++ ++ inode = NULL; ++ err = au_xino_read(sb, bindex, h_ino, &ino); ++ if (!err && ino) ++ inode = ilookup(sb, ino); ++ if (!inode) ++ goto out; ++ ++ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) { ++ pr_warn("wrong root branch\n"); ++ iput(inode); ++ inode = NULL; ++ goto out; ++ } ++ ++ ii_write_lock_child(inode); ++ ++out: ++ return inode; ++} ++ ++static void au_hn_bh(void *_args) ++{ ++ struct au_hnotify_args *a = _args; ++ struct super_block *sb; ++ aufs_bindex_t bindex, bbot, bfound; ++ unsigned char xino, try_iput; ++ int err; ++ struct inode *inode; ++ ino_t h_ino; ++ struct hn_job_args args; ++ struct dentry *dentry; ++ struct au_sbinfo *sbinfo; ++ ++ AuDebugOn(!_args); ++ AuDebugOn(!a->h_dir); ++ AuDebugOn(!a->dir); ++ AuDebugOn(!a->mask); ++ AuDbg("mask 0x%x, i%lu, hi%lu, hci%lu\n", ++ a->mask, a->dir->i_ino, a->h_dir->i_ino, ++ a->h_child_inode ? a->h_child_inode->i_ino : 0); ++ ++ inode = NULL; ++ dentry = NULL; ++ /* ++ * do not lock a->dir->i_mutex here ++ * because of d_revalidate() may cause a deadlock. ++ */ ++ sb = a->dir->i_sb; ++ AuDebugOn(!sb); ++ sbinfo = au_sbi(sb); ++ AuDebugOn(!sbinfo); ++ si_write_lock(sb, AuLock_NOPLMW); ++ ++ if (au_opt_test(sbinfo->si_mntflags, DIRREN)) ++ switch (a->mask & FS_EVENTS_POSS_ON_CHILD) { ++ case FS_MOVED_FROM: ++ case FS_MOVED_TO: ++ AuWarn1("DIRREN with UDBA may not work correctly " ++ "for the direct rename(2)\n"); ++ } ++ ++ ii_read_lock_parent(a->dir); ++ bfound = -1; ++ bbot = au_ibbot(a->dir); ++ for (bindex = au_ibtop(a->dir); bindex <= bbot; bindex++) ++ if (au_h_iptr(a->dir, bindex) == a->h_dir) { ++ bfound = bindex; ++ break; ++ } ++ ii_read_unlock(a->dir); ++ if (unlikely(bfound < 0)) ++ goto out; ++ ++ xino = !!au_opt_test(au_mntflags(sb), XINO); ++ h_ino = 0; ++ if (a->h_child_inode) ++ h_ino = a->h_child_inode->i_ino; ++ ++ if (a->h_child_nlen ++ && (au_ftest_hnjob(a->flags[AuHn_CHILD], GEN) ++ || au_ftest_hnjob(a->flags[AuHn_CHILD], MNTPNT))) ++ dentry = lookup_wlock_by_name(a->h_child_name, a->h_child_nlen, ++ a->dir); ++ try_iput = 0; ++ if (dentry && d_really_is_positive(dentry)) ++ inode = d_inode(dentry); ++ if (xino && !inode && h_ino ++ && (au_ftest_hnjob(a->flags[AuHn_CHILD], XINO0) ++ || au_ftest_hnjob(a->flags[AuHn_CHILD], TRYXINO0) ++ || au_ftest_hnjob(a->flags[AuHn_CHILD], GEN))) { ++ inode = lookup_wlock_by_ino(sb, bfound, h_ino); ++ try_iput = 1; ++ } ++ ++ args.flags = a->flags[AuHn_CHILD]; ++ args.dentry = dentry; ++ args.inode = inode; ++ args.h_inode = a->h_child_inode; ++ args.dir = a->dir; ++ args.h_dir = a->h_dir; ++ args.h_name = a->h_child_name; ++ args.h_nlen = a->h_child_nlen; ++ err = hn_job(&args); ++ if (dentry) { ++ if (au_di(dentry)) ++ di_write_unlock(dentry); ++ dput(dentry); ++ } ++ if (inode && try_iput) { ++ ii_write_unlock(inode); ++ iput(inode); ++ } ++ ++ ii_write_lock_parent(a->dir); ++ args.flags = a->flags[AuHn_PARENT]; ++ args.dentry = NULL; ++ args.inode = a->dir; ++ args.h_inode = a->h_dir; ++ args.dir = NULL; ++ args.h_dir = NULL; ++ args.h_name = NULL; ++ args.h_nlen = 0; ++ err = hn_job(&args); ++ ii_write_unlock(a->dir); ++ ++out: ++ iput(a->h_child_inode); ++ iput(a->h_dir); ++ iput(a->dir); ++ si_write_unlock(sb); ++ au_nwt_done(&sbinfo->si_nowait); ++ au_kfree_rcu(a); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask, ++ const struct qstr *h_child_qstr, struct inode *h_child_inode) ++{ ++ int err, len; ++ unsigned int flags[AuHnLast], f; ++ unsigned char isdir, isroot, wh; ++ struct inode *dir; ++ struct au_hnotify_args *args; ++ char *p, *h_child_name; ++ ++ err = 0; ++ AuDebugOn(!hnotify || !hnotify->hn_aufs_inode); ++ dir = igrab(hnotify->hn_aufs_inode); ++ if (!dir) ++ goto out; ++ ++ isroot = (dir->i_ino == AUFS_ROOT_INO); ++ wh = 0; ++ h_child_name = (void *)h_child_qstr->name; ++ len = h_child_qstr->len; ++ if (h_child_name) { ++ if (len > AUFS_WH_PFX_LEN ++ && !memcmp(h_child_name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) { ++ h_child_name += AUFS_WH_PFX_LEN; ++ len -= AUFS_WH_PFX_LEN; ++ wh = 1; ++ } ++ } ++ ++ isdir = 0; ++ if (h_child_inode) ++ isdir = !!S_ISDIR(h_child_inode->i_mode); ++ flags[AuHn_PARENT] = AuHnJob_ISDIR; ++ flags[AuHn_CHILD] = 0; ++ if (isdir) ++ flags[AuHn_CHILD] = AuHnJob_ISDIR; ++ au_fset_hnjob(flags[AuHn_PARENT], DIRENT); ++ au_fset_hnjob(flags[AuHn_CHILD], GEN); ++ switch (mask & ALL_FSNOTIFY_DIRENT_EVENTS) { ++ case FS_MOVED_FROM: ++ case FS_MOVED_TO: ++ au_fset_hnjob(flags[AuHn_CHILD], XINO0); ++ au_fset_hnjob(flags[AuHn_CHILD], MNTPNT); ++ /*FALLTHROUGH*/ ++ case FS_CREATE: ++ AuDebugOn(!h_child_name); ++ break; ++ ++ case FS_DELETE: ++ /* ++ * aufs never be able to get this child inode. ++ * revalidation should be in d_revalidate() ++ * by checking i_nlink, i_generation or d_unhashed(). ++ */ ++ AuDebugOn(!h_child_name); ++ au_fset_hnjob(flags[AuHn_CHILD], TRYXINO0); ++ au_fset_hnjob(flags[AuHn_CHILD], MNTPNT); ++ break; ++ ++ default: ++ AuDebugOn(1); ++ } ++ ++ if (wh) ++ h_child_inode = NULL; ++ ++ err = -ENOMEM; ++ /* iput() and kfree() will be called in au_hnotify() */ ++ args = kmalloc(sizeof(*args) + len + 1, GFP_NOFS); ++ if (unlikely(!args)) { ++ AuErr1("no memory\n"); ++ iput(dir); ++ goto out; ++ } ++ args->flags[AuHn_PARENT] = flags[AuHn_PARENT]; ++ args->flags[AuHn_CHILD] = flags[AuHn_CHILD]; ++ args->mask = mask; ++ args->dir = dir; ++ args->h_dir = igrab(h_dir); ++ if (h_child_inode) ++ h_child_inode = igrab(h_child_inode); /* can be NULL */ ++ args->h_child_inode = h_child_inode; ++ args->h_child_nlen = len; ++ if (len) { ++ p = (void *)args; ++ p += sizeof(*args); ++ memcpy(p, h_child_name, len); ++ p[len] = 0; ++ } ++ ++ /* NFS fires the event for silly-renamed one from kworker */ ++ f = 0; ++ if (!dir->i_nlink ++ || (au_test_nfs(h_dir->i_sb) && (mask & FS_DELETE))) ++ f = AuWkq_NEST; ++ err = au_wkq_nowait(au_hn_bh, args, dir->i_sb, f); ++ if (unlikely(err)) { ++ pr_err("wkq %d\n", err); ++ iput(args->h_child_inode); ++ iput(args->h_dir); ++ iput(args->dir); ++ au_kfree_rcu(args); ++ } ++ ++out: ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++int au_hnotify_reset_br(unsigned int udba, struct au_branch *br, int perm) ++{ ++ int err; ++ ++ AuDebugOn(!(udba & AuOptMask_UDBA)); ++ ++ err = 0; ++ if (au_hnotify_op.reset_br) ++ err = au_hnotify_op.reset_br(udba, br, perm); ++ ++ return err; ++} ++ ++int au_hnotify_init_br(struct au_branch *br, int perm) ++{ ++ int err; ++ ++ err = 0; ++ if (au_hnotify_op.init_br) ++ err = au_hnotify_op.init_br(br, perm); ++ ++ return err; ++} ++ ++void au_hnotify_fin_br(struct au_branch *br) ++{ ++ if (au_hnotify_op.fin_br) ++ au_hnotify_op.fin_br(br); ++} ++ ++static void au_hn_destroy_cache(void) ++{ ++ kmem_cache_destroy(au_cache[AuCache_HNOTIFY]); ++ au_cache[AuCache_HNOTIFY] = NULL; ++} ++ ++int __init au_hnotify_init(void) ++{ ++ int err; ++ ++ err = -ENOMEM; ++ au_cache[AuCache_HNOTIFY] = AuCache(au_hnotify); ++ if (au_cache[AuCache_HNOTIFY]) { ++ err = 0; ++ if (au_hnotify_op.init) ++ err = au_hnotify_op.init(); ++ if (unlikely(err)) ++ au_hn_destroy_cache(); ++ } ++ AuTraceErr(err); ++ return err; ++} ++ ++void au_hnotify_fin(void) ++{ ++ if (au_hnotify_op.fin) ++ au_hnotify_op.fin(); ++ ++ /* cf. au_cache_fin() */ ++ if (au_cache[AuCache_HNOTIFY]) ++ au_hn_destroy_cache(); ++} +diff -Nurp linux-5.4/fs/aufs/iinfo.c linux-5.4-aufs/fs/aufs/iinfo.c +--- linux-5.4/fs/aufs/iinfo.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/iinfo.c 2019-11-28 01:25:59.066925618 +0200 +@@ -0,0 +1,273 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * inode private data ++ */ ++ ++#include "aufs.h" ++ ++struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex) ++{ ++ struct inode *h_inode; ++ struct au_hinode *hinode; ++ ++ IiMustAnyLock(inode); ++ ++ hinode = au_hinode(au_ii(inode), bindex); ++ h_inode = hinode->hi_inode; ++ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0); ++ return h_inode; ++} ++ ++/* todo: hard/soft set? */ ++void au_hiput(struct au_hinode *hinode) ++{ ++ au_hn_free(hinode); ++ dput(hinode->hi_whdentry); ++ iput(hinode->hi_inode); ++} ++ ++unsigned int au_hi_flags(struct inode *inode, int isdir) ++{ ++ unsigned int flags; ++ const unsigned int mnt_flags = au_mntflags(inode->i_sb); ++ ++ flags = 0; ++ if (au_opt_test(mnt_flags, XINO)) ++ au_fset_hi(flags, XINO); ++ if (isdir && au_opt_test(mnt_flags, UDBA_HNOTIFY)) ++ au_fset_hi(flags, HNOTIFY); ++ return flags; ++} ++ ++void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex, ++ struct inode *h_inode, unsigned int flags) ++{ ++ struct au_hinode *hinode; ++ struct inode *hi; ++ struct au_iinfo *iinfo = au_ii(inode); ++ ++ IiMustWriteLock(inode); ++ ++ hinode = au_hinode(iinfo, bindex); ++ hi = hinode->hi_inode; ++ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0); ++ ++ if (hi) ++ au_hiput(hinode); ++ hinode->hi_inode = h_inode; ++ if (h_inode) { ++ int err; ++ struct super_block *sb = inode->i_sb; ++ struct au_branch *br; ++ ++ AuDebugOn(inode->i_mode ++ && (h_inode->i_mode & S_IFMT) ++ != (inode->i_mode & S_IFMT)); ++ if (bindex == iinfo->ii_btop) ++ au_cpup_igen(inode, h_inode); ++ br = au_sbr(sb, bindex); ++ hinode->hi_id = br->br_id; ++ if (au_ftest_hi(flags, XINO)) { ++ err = au_xino_write(sb, bindex, h_inode->i_ino, ++ inode->i_ino); ++ if (unlikely(err)) ++ AuIOErr1("failed au_xino_write() %d\n", err); ++ } ++ ++ if (au_ftest_hi(flags, HNOTIFY) ++ && au_br_hnotifyable(br->br_perm)) { ++ err = au_hn_alloc(hinode, inode); ++ if (unlikely(err)) ++ AuIOErr1("au_hn_alloc() %d\n", err); ++ } ++ } ++} ++ ++void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex, ++ struct dentry *h_wh) ++{ ++ struct au_hinode *hinode; ++ ++ IiMustWriteLock(inode); ++ ++ hinode = au_hinode(au_ii(inode), bindex); ++ AuDebugOn(hinode->hi_whdentry); ++ hinode->hi_whdentry = h_wh; ++} ++ ++void au_update_iigen(struct inode *inode, int half) ++{ ++ struct au_iinfo *iinfo; ++ struct au_iigen *iigen; ++ unsigned int sigen; ++ ++ sigen = au_sigen(inode->i_sb); ++ iinfo = au_ii(inode); ++ iigen = &iinfo->ii_generation; ++ spin_lock(&iigen->ig_spin); ++ iigen->ig_generation = sigen; ++ if (half) ++ au_ig_fset(iigen->ig_flags, HALF_REFRESHED); ++ else ++ au_ig_fclr(iigen->ig_flags, HALF_REFRESHED); ++ spin_unlock(&iigen->ig_spin); ++} ++ ++/* it may be called at remount time, too */ ++void au_update_ibrange(struct inode *inode, int do_put_zero) ++{ ++ struct au_iinfo *iinfo; ++ aufs_bindex_t bindex, bbot; ++ ++ AuDebugOn(au_is_bad_inode(inode)); ++ IiMustWriteLock(inode); ++ ++ iinfo = au_ii(inode); ++ if (do_put_zero && iinfo->ii_btop >= 0) { ++ for (bindex = iinfo->ii_btop; bindex <= iinfo->ii_bbot; ++ bindex++) { ++ struct inode *h_i; ++ ++ h_i = au_hinode(iinfo, bindex)->hi_inode; ++ if (h_i ++ && !h_i->i_nlink ++ && !(h_i->i_state & I_LINKABLE)) ++ au_set_h_iptr(inode, bindex, NULL, 0); ++ } ++ } ++ ++ iinfo->ii_btop = -1; ++ iinfo->ii_bbot = -1; ++ bbot = au_sbbot(inode->i_sb); ++ for (bindex = 0; bindex <= bbot; bindex++) ++ if (au_hinode(iinfo, bindex)->hi_inode) { ++ iinfo->ii_btop = bindex; ++ break; ++ } ++ if (iinfo->ii_btop >= 0) ++ for (bindex = bbot; bindex >= iinfo->ii_btop; bindex--) ++ if (au_hinode(iinfo, bindex)->hi_inode) { ++ iinfo->ii_bbot = bindex; ++ break; ++ } ++ AuDebugOn(iinfo->ii_btop > iinfo->ii_bbot); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++void au_icntnr_init_once(void *_c) ++{ ++ struct au_icntnr *c = _c; ++ struct au_iinfo *iinfo = &c->iinfo; ++ ++ spin_lock_init(&iinfo->ii_generation.ig_spin); ++ au_rw_init(&iinfo->ii_rwsem); ++ inode_init_once(&c->vfs_inode); ++} ++ ++void au_hinode_init(struct au_hinode *hinode) ++{ ++ hinode->hi_inode = NULL; ++ hinode->hi_id = -1; ++ au_hn_init(hinode); ++ hinode->hi_whdentry = NULL; ++} ++ ++int au_iinfo_init(struct inode *inode) ++{ ++ struct au_iinfo *iinfo; ++ struct super_block *sb; ++ struct au_hinode *hi; ++ int nbr, i; ++ ++ sb = inode->i_sb; ++ iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo); ++ nbr = au_sbbot(sb) + 1; ++ if (unlikely(nbr <= 0)) ++ nbr = 1; ++ hi = kmalloc_array(nbr, sizeof(*iinfo->ii_hinode), GFP_NOFS); ++ if (hi) { ++ au_lcnt_inc(&au_sbi(sb)->si_ninodes); ++ ++ iinfo->ii_hinode = hi; ++ for (i = 0; i < nbr; i++, hi++) ++ au_hinode_init(hi); ++ ++ iinfo->ii_generation.ig_generation = au_sigen(sb); ++ iinfo->ii_btop = -1; ++ iinfo->ii_bbot = -1; ++ iinfo->ii_vdir = NULL; ++ return 0; ++ } ++ return -ENOMEM; ++} ++ ++int au_hinode_realloc(struct au_iinfo *iinfo, int nbr, int may_shrink) ++{ ++ int err, i; ++ struct au_hinode *hip; ++ ++ AuRwMustWriteLock(&iinfo->ii_rwsem); ++ ++ err = -ENOMEM; ++ hip = au_krealloc(iinfo->ii_hinode, sizeof(*hip) * nbr, GFP_NOFS, ++ may_shrink); ++ if (hip) { ++ iinfo->ii_hinode = hip; ++ i = iinfo->ii_bbot + 1; ++ hip += i; ++ for (; i < nbr; i++, hip++) ++ au_hinode_init(hip); ++ err = 0; ++ } ++ ++ return err; ++} ++ ++void au_iinfo_fin(struct inode *inode) ++{ ++ struct au_iinfo *iinfo; ++ struct au_hinode *hi; ++ struct super_block *sb; ++ aufs_bindex_t bindex, bbot; ++ const unsigned char unlinked = !inode->i_nlink; ++ ++ AuDebugOn(au_is_bad_inode(inode)); ++ ++ sb = inode->i_sb; ++ au_lcnt_dec(&au_sbi(sb)->si_ninodes); ++ if (si_pid_test(sb)) ++ au_xino_delete_inode(inode, unlinked); ++ else { ++ /* ++ * it is safe to hide the dependency between sbinfo and ++ * sb->s_umount. ++ */ ++ lockdep_off(); ++ si_noflush_read_lock(sb); ++ au_xino_delete_inode(inode, unlinked); ++ si_read_unlock(sb); ++ lockdep_on(); ++ } ++ ++ iinfo = au_ii(inode); ++ if (iinfo->ii_vdir) ++ au_vdir_free(iinfo->ii_vdir); ++ ++ bindex = iinfo->ii_btop; ++ if (bindex >= 0) { ++ hi = au_hinode(iinfo, bindex); ++ bbot = iinfo->ii_bbot; ++ while (bindex++ <= bbot) { ++ if (hi->hi_inode) ++ au_hiput(hi); ++ hi++; ++ } ++ } ++ au_kfree_rcu(iinfo->ii_hinode); ++ AuRwDestroy(&iinfo->ii_rwsem); ++} +diff -Nurp linux-5.4/fs/aufs/inode.c linux-5.4-aufs/fs/aufs/inode.c +--- linux-5.4/fs/aufs/inode.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/inode.c 2019-11-28 01:25:59.066925618 +0200 +@@ -0,0 +1,516 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * inode functions ++ */ ++ ++#include ++#include "aufs.h" ++ ++struct inode *au_igrab(struct inode *inode) ++{ ++ if (inode) { ++ AuDebugOn(!atomic_read(&inode->i_count)); ++ ihold(inode); ++ } ++ return inode; ++} ++ ++static void au_refresh_hinode_attr(struct inode *inode, int do_version) ++{ ++ au_cpup_attr_all(inode, /*force*/0); ++ au_update_iigen(inode, /*half*/1); ++ if (do_version) ++ inode_inc_iversion(inode); ++} ++ ++static int au_ii_refresh(struct inode *inode, int *update) ++{ ++ int err, e, nbr; ++ umode_t type; ++ aufs_bindex_t bindex, new_bindex; ++ struct super_block *sb; ++ struct au_iinfo *iinfo; ++ struct au_hinode *p, *q, tmp; ++ ++ AuDebugOn(au_is_bad_inode(inode)); ++ IiMustWriteLock(inode); ++ ++ *update = 0; ++ sb = inode->i_sb; ++ nbr = au_sbbot(sb) + 1; ++ type = inode->i_mode & S_IFMT; ++ iinfo = au_ii(inode); ++ err = au_hinode_realloc(iinfo, nbr, /*may_shrink*/0); ++ if (unlikely(err)) ++ goto out; ++ ++ AuDebugOn(iinfo->ii_btop < 0); ++ p = au_hinode(iinfo, iinfo->ii_btop); ++ for (bindex = iinfo->ii_btop; bindex <= iinfo->ii_bbot; ++ bindex++, p++) { ++ if (!p->hi_inode) ++ continue; ++ ++ AuDebugOn(type != (p->hi_inode->i_mode & S_IFMT)); ++ new_bindex = au_br_index(sb, p->hi_id); ++ if (new_bindex == bindex) ++ continue; ++ ++ if (new_bindex < 0) { ++ *update = 1; ++ au_hiput(p); ++ p->hi_inode = NULL; ++ continue; ++ } ++ ++ if (new_bindex < iinfo->ii_btop) ++ iinfo->ii_btop = new_bindex; ++ if (iinfo->ii_bbot < new_bindex) ++ iinfo->ii_bbot = new_bindex; ++ /* swap two lower inode, and loop again */ ++ q = au_hinode(iinfo, new_bindex); ++ tmp = *q; ++ *q = *p; ++ *p = tmp; ++ if (tmp.hi_inode) { ++ bindex--; ++ p--; ++ } ++ } ++ au_update_ibrange(inode, /*do_put_zero*/0); ++ au_hinode_realloc(iinfo, nbr, /*may_shrink*/1); /* harmless if err */ ++ e = au_dy_irefresh(inode); ++ if (unlikely(e && !err)) ++ err = e; ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++void au_refresh_iop(struct inode *inode, int force_getattr) ++{ ++ int type; ++ struct au_sbinfo *sbi = au_sbi(inode->i_sb); ++ const struct inode_operations *iop ++ = force_getattr ? aufs_iop : sbi->si_iop_array; ++ ++ if (inode->i_op == iop) ++ return; ++ ++ switch (inode->i_mode & S_IFMT) { ++ case S_IFDIR: ++ type = AuIop_DIR; ++ break; ++ case S_IFLNK: ++ type = AuIop_SYMLINK; ++ break; ++ default: ++ type = AuIop_OTHER; ++ break; ++ } ++ ++ inode->i_op = iop + type; ++ /* unnecessary smp_wmb() */ ++} ++ ++int au_refresh_hinode_self(struct inode *inode) ++{ ++ int err, update; ++ ++ err = au_ii_refresh(inode, &update); ++ if (!err) ++ au_refresh_hinode_attr(inode, update && S_ISDIR(inode->i_mode)); ++ ++ AuTraceErr(err); ++ return err; ++} ++ ++int au_refresh_hinode(struct inode *inode, struct dentry *dentry) ++{ ++ int err, e, update; ++ unsigned int flags; ++ umode_t mode; ++ aufs_bindex_t bindex, bbot; ++ unsigned char isdir; ++ struct au_hinode *p; ++ struct au_iinfo *iinfo; ++ ++ err = au_ii_refresh(inode, &update); ++ if (unlikely(err)) ++ goto out; ++ ++ update = 0; ++ iinfo = au_ii(inode); ++ p = au_hinode(iinfo, iinfo->ii_btop); ++ mode = (inode->i_mode & S_IFMT); ++ isdir = S_ISDIR(mode); ++ flags = au_hi_flags(inode, isdir); ++ bbot = au_dbbot(dentry); ++ for (bindex = au_dbtop(dentry); bindex <= bbot; bindex++) { ++ struct inode *h_i, *h_inode; ++ struct dentry *h_d; ++ ++ h_d = au_h_dptr(dentry, bindex); ++ if (!h_d || d_is_negative(h_d)) ++ continue; ++ ++ h_inode = d_inode(h_d); ++ AuDebugOn(mode != (h_inode->i_mode & S_IFMT)); ++ if (iinfo->ii_btop <= bindex && bindex <= iinfo->ii_bbot) { ++ h_i = au_h_iptr(inode, bindex); ++ if (h_i) { ++ if (h_i == h_inode) ++ continue; ++ err = -EIO; ++ break; ++ } ++ } ++ if (bindex < iinfo->ii_btop) ++ iinfo->ii_btop = bindex; ++ if (iinfo->ii_bbot < bindex) ++ iinfo->ii_bbot = bindex; ++ au_set_h_iptr(inode, bindex, au_igrab(h_inode), flags); ++ update = 1; ++ } ++ au_update_ibrange(inode, /*do_put_zero*/0); ++ e = au_dy_irefresh(inode); ++ if (unlikely(e && !err)) ++ err = e; ++ if (!err) ++ au_refresh_hinode_attr(inode, update && isdir); ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++static int set_inode(struct inode *inode, struct dentry *dentry) ++{ ++ int err; ++ unsigned int flags; ++ umode_t mode; ++ aufs_bindex_t bindex, btop, btail; ++ unsigned char isdir; ++ struct dentry *h_dentry; ++ struct inode *h_inode; ++ struct au_iinfo *iinfo; ++ struct inode_operations *iop; ++ ++ IiMustWriteLock(inode); ++ ++ err = 0; ++ isdir = 0; ++ iop = au_sbi(inode->i_sb)->si_iop_array; ++ btop = au_dbtop(dentry); ++ h_dentry = au_h_dptr(dentry, btop); ++ h_inode = d_inode(h_dentry); ++ mode = h_inode->i_mode; ++ switch (mode & S_IFMT) { ++ case S_IFREG: ++ btail = au_dbtail(dentry); ++ inode->i_op = iop + AuIop_OTHER; ++ inode->i_fop = &aufs_file_fop; ++ err = au_dy_iaop(inode, btop, h_inode); ++ if (unlikely(err)) ++ goto out; ++ break; ++ case S_IFDIR: ++ isdir = 1; ++ btail = au_dbtaildir(dentry); ++ inode->i_op = iop + AuIop_DIR; ++ inode->i_fop = &aufs_dir_fop; ++ break; ++ case S_IFLNK: ++ btail = au_dbtail(dentry); ++ inode->i_op = iop + AuIop_SYMLINK; ++ break; ++ case S_IFBLK: ++ case S_IFCHR: ++ case S_IFIFO: ++ case S_IFSOCK: ++ btail = au_dbtail(dentry); ++ inode->i_op = iop + AuIop_OTHER; ++ init_special_inode(inode, mode, h_inode->i_rdev); ++ break; ++ default: ++ AuIOErr("Unknown file type 0%o\n", mode); ++ err = -EIO; ++ goto out; ++ } ++ ++ /* do not set hnotify for whiteouted dirs (SHWH mode) */ ++ flags = au_hi_flags(inode, isdir); ++ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH) ++ && au_ftest_hi(flags, HNOTIFY) ++ && dentry->d_name.len > AUFS_WH_PFX_LEN ++ && !memcmp(dentry->d_name.name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) ++ au_fclr_hi(flags, HNOTIFY); ++ iinfo = au_ii(inode); ++ iinfo->ii_btop = btop; ++ iinfo->ii_bbot = btail; ++ for (bindex = btop; bindex <= btail; bindex++) { ++ h_dentry = au_h_dptr(dentry, bindex); ++ if (h_dentry) ++ au_set_h_iptr(inode, bindex, ++ au_igrab(d_inode(h_dentry)), flags); ++ } ++ au_cpup_attr_all(inode, /*force*/1); ++ /* ++ * to force calling aufs_get_acl() every time, ++ * do not call cache_no_acl() for aufs inode. ++ */ ++ ++out: ++ return err; ++} ++ ++/* ++ * successful returns with iinfo write_locked ++ * minus: errno ++ * zero: success, matched ++ * plus: no error, but unmatched ++ */ ++static int reval_inode(struct inode *inode, struct dentry *dentry) ++{ ++ int err; ++ unsigned int gen, igflags; ++ aufs_bindex_t bindex, bbot; ++ struct inode *h_inode, *h_dinode; ++ struct dentry *h_dentry; ++ ++ /* ++ * before this function, if aufs got any iinfo lock, it must be only ++ * one, the parent dir. ++ * it can happen by UDBA and the obsoleted inode number. ++ */ ++ err = -EIO; ++ if (unlikely(inode->i_ino == parent_ino(dentry))) ++ goto out; ++ ++ err = 1; ++ ii_write_lock_new_child(inode); ++ h_dentry = au_h_dptr(dentry, au_dbtop(dentry)); ++ h_dinode = d_inode(h_dentry); ++ bbot = au_ibbot(inode); ++ for (bindex = au_ibtop(inode); bindex <= bbot; bindex++) { ++ h_inode = au_h_iptr(inode, bindex); ++ if (!h_inode || h_inode != h_dinode) ++ continue; ++ ++ err = 0; ++ gen = au_iigen(inode, &igflags); ++ if (gen == au_digen(dentry) ++ && !au_ig_ftest(igflags, HALF_REFRESHED)) ++ break; ++ ++ /* fully refresh inode using dentry */ ++ err = au_refresh_hinode(inode, dentry); ++ if (!err) ++ au_update_iigen(inode, /*half*/0); ++ break; ++ } ++ ++ if (unlikely(err)) ++ ii_write_unlock(inode); ++out: ++ return err; ++} ++ ++int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, ++ unsigned int d_type, ino_t *ino) ++{ ++ int err, idx; ++ const int isnondir = d_type != DT_DIR; ++ ++ /* prevent hardlinked inode number from race condition */ ++ if (isnondir) { ++ err = au_xinondir_enter(sb, bindex, h_ino, &idx); ++ if (unlikely(err)) ++ goto out; ++ } ++ ++ err = au_xino_read(sb, bindex, h_ino, ino); ++ if (unlikely(err)) ++ goto out_xinondir; ++ ++ if (!*ino) { ++ err = -EIO; ++ *ino = au_xino_new_ino(sb); ++ if (unlikely(!*ino)) ++ goto out_xinondir; ++ err = au_xino_write(sb, bindex, h_ino, *ino); ++ if (unlikely(err)) ++ goto out_xinondir; ++ } ++ ++out_xinondir: ++ if (isnondir && idx >= 0) ++ au_xinondir_leave(sb, bindex, h_ino, idx); ++out: ++ return err; ++} ++ ++/* successful returns with iinfo write_locked */ ++/* todo: return with unlocked? */ ++struct inode *au_new_inode(struct dentry *dentry, int must_new) ++{ ++ struct inode *inode, *h_inode; ++ struct dentry *h_dentry; ++ struct super_block *sb; ++ ino_t h_ino, ino; ++ int err, idx, hlinked; ++ aufs_bindex_t btop; ++ ++ sb = dentry->d_sb; ++ btop = au_dbtop(dentry); ++ h_dentry = au_h_dptr(dentry, btop); ++ h_inode = d_inode(h_dentry); ++ h_ino = h_inode->i_ino; ++ hlinked = !d_is_dir(h_dentry) && h_inode->i_nlink > 1; ++ ++new_ino: ++ /* ++ * stop 'race'-ing between hardlinks under different ++ * parents. ++ */ ++ if (hlinked) { ++ err = au_xinondir_enter(sb, btop, h_ino, &idx); ++ inode = ERR_PTR(err); ++ if (unlikely(err)) ++ goto out; ++ } ++ ++ err = au_xino_read(sb, btop, h_ino, &ino); ++ inode = ERR_PTR(err); ++ if (unlikely(err)) ++ goto out_xinondir; ++ ++ if (!ino) { ++ ino = au_xino_new_ino(sb); ++ if (unlikely(!ino)) { ++ inode = ERR_PTR(-EIO); ++ goto out_xinondir; ++ } ++ } ++ ++ AuDbg("i%lu\n", (unsigned long)ino); ++ inode = au_iget_locked(sb, ino); ++ err = PTR_ERR(inode); ++ if (IS_ERR(inode)) ++ goto out_xinondir; ++ ++ AuDbg("%lx, new %d\n", inode->i_state, !!(inode->i_state & I_NEW)); ++ if (inode->i_state & I_NEW) { ++ ii_write_lock_new_child(inode); ++ err = set_inode(inode, dentry); ++ if (!err) { ++ unlock_new_inode(inode); ++ goto out_xinondir; /* success */ ++ } ++ ++ /* ++ * iget_failed() calls iput(), but we need to call ++ * ii_write_unlock() after iget_failed(). so dirty hack for ++ * i_count. ++ */ ++ atomic_inc(&inode->i_count); ++ iget_failed(inode); ++ ii_write_unlock(inode); ++ au_xino_write(sb, btop, h_ino, /*ino*/0); ++ /* ignore this error */ ++ goto out_iput; ++ } else if (!must_new && !IS_DEADDIR(inode) && inode->i_nlink) { ++ /* ++ * horrible race condition between lookup, readdir and copyup ++ * (or something). ++ */ ++ if (hlinked && idx >= 0) ++ au_xinondir_leave(sb, btop, h_ino, idx); ++ err = reval_inode(inode, dentry); ++ if (unlikely(err < 0)) { ++ hlinked = 0; ++ goto out_iput; ++ } ++ if (!err) ++ goto out; /* success */ ++ else if (hlinked && idx >= 0) { ++ err = au_xinondir_enter(sb, btop, h_ino, &idx); ++ if (unlikely(err)) { ++ iput(inode); ++ inode = ERR_PTR(err); ++ goto out; ++ } ++ } ++ } ++ ++ if (unlikely(au_test_fs_unique_ino(h_inode))) ++ AuWarn1("Warning: Un-notified UDBA or repeatedly renamed dir," ++ " b%d, %s, %pd, hi%lu, i%lu.\n", ++ btop, au_sbtype(h_dentry->d_sb), dentry, ++ (unsigned long)h_ino, (unsigned long)ino); ++ ino = 0; ++ err = au_xino_write(sb, btop, h_ino, /*ino*/0); ++ if (!err) { ++ iput(inode); ++ if (hlinked && idx >= 0) ++ au_xinondir_leave(sb, btop, h_ino, idx); ++ goto new_ino; ++ } ++ ++out_iput: ++ iput(inode); ++ inode = ERR_PTR(err); ++out_xinondir: ++ if (hlinked && idx >= 0) ++ au_xinondir_leave(sb, btop, h_ino, idx); ++out: ++ return inode; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++int au_test_ro(struct super_block *sb, aufs_bindex_t bindex, ++ struct inode *inode) ++{ ++ int err; ++ struct inode *hi; ++ ++ err = au_br_rdonly(au_sbr(sb, bindex)); ++ ++ /* pseudo-link after flushed may happen out of bounds */ ++ if (!err ++ && inode ++ && au_ibtop(inode) <= bindex ++ && bindex <= au_ibbot(inode)) { ++ /* ++ * permission check is unnecessary since vfsub routine ++ * will be called later ++ */ ++ hi = au_h_iptr(inode, bindex); ++ if (hi) ++ err = IS_IMMUTABLE(hi) ? -EROFS : 0; ++ } ++ ++ return err; ++} ++ ++int au_test_h_perm(struct inode *h_inode, int mask) ++{ ++ if (uid_eq(current_fsuid(), GLOBAL_ROOT_UID)) ++ return 0; ++ return inode_permission(h_inode, mask); ++} ++ ++int au_test_h_perm_sio(struct inode *h_inode, int mask) ++{ ++ if (au_test_nfs(h_inode->i_sb) ++ && (mask & MAY_WRITE) ++ && S_ISDIR(h_inode->i_mode)) ++ mask |= MAY_READ; /* force permission check */ ++ return au_test_h_perm(h_inode, mask); ++} +diff -Nurp linux-5.4/fs/aufs/inode.h linux-5.4-aufs/fs/aufs/inode.h +--- linux-5.4/fs/aufs/inode.h 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/inode.h 2019-11-28 01:25:59.066925618 +0200 +@@ -0,0 +1,685 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * inode operations ++ */ ++ ++#ifndef __AUFS_INODE_H__ ++#define __AUFS_INODE_H__ ++ ++#ifdef __KERNEL__ ++ ++#include ++#include "rwsem.h" ++ ++struct vfsmount; ++ ++struct au_hnotify { ++#ifdef CONFIG_AUFS_HNOTIFY ++#ifdef CONFIG_AUFS_HFSNOTIFY ++ /* never use fsnotify_add_vfsmount_mark() */ ++ struct fsnotify_mark hn_mark; ++#endif ++ struct inode *hn_aufs_inode; /* no get/put */ ++ struct rcu_head rcu; ++#endif ++} ____cacheline_aligned_in_smp; ++ ++struct au_hinode { ++ struct inode *hi_inode; ++ aufs_bindex_t hi_id; ++#ifdef CONFIG_AUFS_HNOTIFY ++ struct au_hnotify *hi_notify; ++#endif ++ ++ /* reference to the copied-up whiteout with get/put */ ++ struct dentry *hi_whdentry; ++}; ++ ++/* ig_flags */ ++#define AuIG_HALF_REFRESHED 1 ++#define au_ig_ftest(flags, name) ((flags) & AuIG_##name) ++#define au_ig_fset(flags, name) \ ++ do { (flags) |= AuIG_##name; } while (0) ++#define au_ig_fclr(flags, name) \ ++ do { (flags) &= ~AuIG_##name; } while (0) ++ ++struct au_iigen { ++ spinlock_t ig_spin; ++ __u32 ig_generation, ig_flags; ++}; ++ ++struct au_vdir; ++struct au_iinfo { ++ struct au_iigen ii_generation; ++ struct super_block *ii_hsb1; /* no get/put */ ++ ++ struct au_rwsem ii_rwsem; ++ aufs_bindex_t ii_btop, ii_bbot; ++ __u32 ii_higen; ++ struct au_hinode *ii_hinode; ++ struct au_vdir *ii_vdir; ++}; ++ ++struct au_icntnr { ++ struct au_iinfo iinfo; ++ struct inode vfs_inode; ++ struct hlist_bl_node plink; ++ struct rcu_head rcu; ++} ____cacheline_aligned_in_smp; ++ ++/* au_pin flags */ ++#define AuPin_DI_LOCKED 1 ++#define AuPin_MNT_WRITE (1 << 1) ++#define au_ftest_pin(flags, name) ((flags) & AuPin_##name) ++#define au_fset_pin(flags, name) \ ++ do { (flags) |= AuPin_##name; } while (0) ++#define au_fclr_pin(flags, name) \ ++ do { (flags) &= ~AuPin_##name; } while (0) ++ ++struct au_pin { ++ /* input */ ++ struct dentry *dentry; ++ unsigned int udba; ++ unsigned char lsc_di, lsc_hi, flags; ++ aufs_bindex_t bindex; ++ ++ /* output */ ++ struct dentry *parent; ++ struct au_hinode *hdir; ++ struct vfsmount *h_mnt; ++ ++ /* temporary unlock/relock for copyup */ ++ struct dentry *h_dentry, *h_parent; ++ struct au_branch *br; ++ struct task_struct *task; ++}; ++ ++void au_pin_hdir_unlock(struct au_pin *p); ++int au_pin_hdir_lock(struct au_pin *p); ++int au_pin_hdir_relock(struct au_pin *p); ++void au_pin_hdir_acquire_nest(struct au_pin *p); ++void au_pin_hdir_release(struct au_pin *p); ++ ++/* ---------------------------------------------------------------------- */ ++ ++static inline struct au_iinfo *au_ii(struct inode *inode) ++{ ++ BUG_ON(is_bad_inode(inode)); ++ return &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* inode.c */ ++struct inode *au_igrab(struct inode *inode); ++void au_refresh_iop(struct inode *inode, int force_getattr); ++int au_refresh_hinode_self(struct inode *inode); ++int au_refresh_hinode(struct inode *inode, struct dentry *dentry); ++int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, ++ unsigned int d_type, ino_t *ino); ++struct inode *au_new_inode(struct dentry *dentry, int must_new); ++int au_test_ro(struct super_block *sb, aufs_bindex_t bindex, ++ struct inode *inode); ++int au_test_h_perm(struct inode *h_inode, int mask); ++int au_test_h_perm_sio(struct inode *h_inode, int mask); ++ ++static inline int au_wh_ino(struct super_block *sb, aufs_bindex_t bindex, ++ ino_t h_ino, unsigned int d_type, ino_t *ino) ++{ ++#ifdef CONFIG_AUFS_SHWH ++ return au_ino(sb, bindex, h_ino, d_type, ino); ++#else ++ return 0; ++#endif ++} ++ ++/* i_op.c */ ++enum { ++ AuIop_SYMLINK, ++ AuIop_DIR, ++ AuIop_OTHER, ++ AuIop_Last ++}; ++extern struct inode_operations aufs_iop[AuIop_Last], ++ aufs_iop_nogetattr[AuIop_Last]; ++ ++/* au_wr_dir flags */ ++#define AuWrDir_ADD_ENTRY 1 ++#define AuWrDir_ISDIR (1 << 1) ++#define AuWrDir_TMPFILE (1 << 2) ++#define au_ftest_wrdir(flags, name) ((flags) & AuWrDir_##name) ++#define au_fset_wrdir(flags, name) \ ++ do { (flags) |= AuWrDir_##name; } while (0) ++#define au_fclr_wrdir(flags, name) \ ++ do { (flags) &= ~AuWrDir_##name; } while (0) ++ ++struct au_wr_dir_args { ++ aufs_bindex_t force_btgt; ++ unsigned char flags; ++}; ++int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry, ++ struct au_wr_dir_args *args); ++ ++struct dentry *au_pinned_h_parent(struct au_pin *pin); ++void au_pin_init(struct au_pin *pin, struct dentry *dentry, ++ aufs_bindex_t bindex, int lsc_di, int lsc_hi, ++ unsigned int udba, unsigned char flags); ++int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex, ++ unsigned int udba, unsigned char flags) __must_check; ++int au_do_pin(struct au_pin *pin) __must_check; ++void au_unpin(struct au_pin *pin); ++int au_reval_for_attr(struct dentry *dentry, unsigned int sigen); ++ ++#define AuIcpup_DID_CPUP 1 ++#define au_ftest_icpup(flags, name) ((flags) & AuIcpup_##name) ++#define au_fset_icpup(flags, name) \ ++ do { (flags) |= AuIcpup_##name; } while (0) ++#define au_fclr_icpup(flags, name) \ ++ do { (flags) &= ~AuIcpup_##name; } while (0) ++ ++struct au_icpup_args { ++ unsigned char flags; ++ unsigned char pin_flags; ++ aufs_bindex_t btgt; ++ unsigned int udba; ++ struct au_pin pin; ++ struct path h_path; ++ struct inode *h_inode; ++}; ++ ++int au_pin_and_icpup(struct dentry *dentry, struct iattr *ia, ++ struct au_icpup_args *a); ++ ++int au_h_path_getattr(struct dentry *dentry, int force, struct path *h_path, ++ int locked); ++ ++/* i_op_add.c */ ++int au_may_add(struct dentry *dentry, aufs_bindex_t bindex, ++ struct dentry *h_parent, int isdir); ++int aufs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, ++ dev_t dev); ++int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname); ++int aufs_create(struct inode *dir, struct dentry *dentry, umode_t mode, ++ bool want_excl); ++struct vfsub_aopen_args; ++int au_aopen_or_create(struct inode *dir, struct dentry *dentry, ++ struct vfsub_aopen_args *args); ++int aufs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode); ++int aufs_link(struct dentry *src_dentry, struct inode *dir, ++ struct dentry *dentry); ++int aufs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode); ++ ++/* i_op_del.c */ ++int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup); ++int au_may_del(struct dentry *dentry, aufs_bindex_t bindex, ++ struct dentry *h_parent, int isdir); ++int aufs_unlink(struct inode *dir, struct dentry *dentry); ++int aufs_rmdir(struct inode *dir, struct dentry *dentry); ++ ++/* i_op_ren.c */ ++int au_wbr(struct dentry *dentry, aufs_bindex_t btgt); ++int aufs_rename(struct inode *src_dir, struct dentry *src_dentry, ++ struct inode *dir, struct dentry *dentry, ++ unsigned int flags); ++ ++/* iinfo.c */ ++struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex); ++void au_hiput(struct au_hinode *hinode); ++void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex, ++ struct dentry *h_wh); ++unsigned int au_hi_flags(struct inode *inode, int isdir); ++ ++/* hinode flags */ ++#define AuHi_XINO 1 ++#define AuHi_HNOTIFY (1 << 1) ++#define au_ftest_hi(flags, name) ((flags) & AuHi_##name) ++#define au_fset_hi(flags, name) \ ++ do { (flags) |= AuHi_##name; } while (0) ++#define au_fclr_hi(flags, name) \ ++ do { (flags) &= ~AuHi_##name; } while (0) ++ ++#ifndef CONFIG_AUFS_HNOTIFY ++#undef AuHi_HNOTIFY ++#define AuHi_HNOTIFY 0 ++#endif ++ ++void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex, ++ struct inode *h_inode, unsigned int flags); ++ ++void au_update_iigen(struct inode *inode, int half); ++void au_update_ibrange(struct inode *inode, int do_put_zero); ++ ++void au_icntnr_init_once(void *_c); ++void au_hinode_init(struct au_hinode *hinode); ++int au_iinfo_init(struct inode *inode); ++void au_iinfo_fin(struct inode *inode); ++int au_hinode_realloc(struct au_iinfo *iinfo, int nbr, int may_shrink); ++ ++#ifdef CONFIG_PROC_FS ++/* plink.c */ ++int au_plink_maint(struct super_block *sb, int flags); ++struct au_sbinfo; ++void au_plink_maint_leave(struct au_sbinfo *sbinfo); ++int au_plink_maint_enter(struct super_block *sb); ++#ifdef CONFIG_AUFS_DEBUG ++void au_plink_list(struct super_block *sb); ++#else ++AuStubVoid(au_plink_list, struct super_block *sb) ++#endif ++int au_plink_test(struct inode *inode); ++struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex); ++void au_plink_append(struct inode *inode, aufs_bindex_t bindex, ++ struct dentry *h_dentry); ++void au_plink_put(struct super_block *sb, int verbose); ++void au_plink_clean(struct super_block *sb, int verbose); ++void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id); ++#else ++AuStubInt0(au_plink_maint, struct super_block *sb, int flags); ++AuStubVoid(au_plink_maint_leave, struct au_sbinfo *sbinfo); ++AuStubInt0(au_plink_maint_enter, struct super_block *sb); ++AuStubVoid(au_plink_list, struct super_block *sb); ++AuStubInt0(au_plink_test, struct inode *inode); ++AuStub(struct dentry *, au_plink_lkup, return NULL, ++ struct inode *inode, aufs_bindex_t bindex); ++AuStubVoid(au_plink_append, struct inode *inode, aufs_bindex_t bindex, ++ struct dentry *h_dentry); ++AuStubVoid(au_plink_put, struct super_block *sb, int verbose); ++AuStubVoid(au_plink_clean, struct super_block *sb, int verbose); ++AuStubVoid(au_plink_half_refresh, struct super_block *sb, aufs_bindex_t br_id); ++#endif /* CONFIG_PROC_FS */ ++ ++#ifdef CONFIG_AUFS_XATTR ++/* xattr.c */ ++int au_cpup_xattr(struct dentry *h_dst, struct dentry *h_src, int ignore_flags, ++ unsigned int verbose); ++ssize_t aufs_listxattr(struct dentry *dentry, char *list, size_t size); ++void au_xattr_init(struct super_block *sb); ++#else ++AuStubInt0(au_cpup_xattr, struct dentry *h_dst, struct dentry *h_src, ++ int ignore_flags, unsigned int verbose); ++AuStubVoid(au_xattr_init, struct super_block *sb); ++#endif ++ ++#ifdef CONFIG_FS_POSIX_ACL ++struct posix_acl *aufs_get_acl(struct inode *inode, int type); ++int aufs_set_acl(struct inode *inode, struct posix_acl *acl, int type); ++#endif ++ ++#if IS_ENABLED(CONFIG_AUFS_XATTR) || IS_ENABLED(CONFIG_FS_POSIX_ACL) ++enum { ++ AU_XATTR_SET, ++ AU_ACL_SET ++}; ++ ++struct au_sxattr { ++ int type; ++ union { ++ struct { ++ const char *name; ++ const void *value; ++ size_t size; ++ int flags; ++ } set; ++ struct { ++ struct posix_acl *acl; ++ int type; ++ } acl_set; ++ } u; ++}; ++ssize_t au_sxattr(struct dentry *dentry, struct inode *inode, ++ struct au_sxattr *arg); ++#endif ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* lock subclass for iinfo */ ++enum { ++ AuLsc_II_CHILD, /* child first */ ++ AuLsc_II_CHILD2, /* rename(2), link(2), and cpup at hnotify */ ++ AuLsc_II_CHILD3, /* copyup dirs */ ++ AuLsc_II_PARENT, /* see AuLsc_I_PARENT in vfsub.h */ ++ AuLsc_II_PARENT2, ++ AuLsc_II_PARENT3, /* copyup dirs */ ++ AuLsc_II_NEW_CHILD ++}; ++ ++/* ++ * ii_read_lock_child, ii_write_lock_child, ++ * ii_read_lock_child2, ii_write_lock_child2, ++ * ii_read_lock_child3, ii_write_lock_child3, ++ * ii_read_lock_parent, ii_write_lock_parent, ++ * ii_read_lock_parent2, ii_write_lock_parent2, ++ * ii_read_lock_parent3, ii_write_lock_parent3, ++ * ii_read_lock_new_child, ii_write_lock_new_child, ++ */ ++#define AuReadLockFunc(name, lsc) \ ++static inline void ii_read_lock_##name(struct inode *i) \ ++{ \ ++ au_rw_read_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \ ++} ++ ++#define AuWriteLockFunc(name, lsc) \ ++static inline void ii_write_lock_##name(struct inode *i) \ ++{ \ ++ au_rw_write_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \ ++} ++ ++#define AuRWLockFuncs(name, lsc) \ ++ AuReadLockFunc(name, lsc) \ ++ AuWriteLockFunc(name, lsc) ++ ++AuRWLockFuncs(child, CHILD); ++AuRWLockFuncs(child2, CHILD2); ++AuRWLockFuncs(child3, CHILD3); ++AuRWLockFuncs(parent, PARENT); ++AuRWLockFuncs(parent2, PARENT2); ++AuRWLockFuncs(parent3, PARENT3); ++AuRWLockFuncs(new_child, NEW_CHILD); ++ ++#undef AuReadLockFunc ++#undef AuWriteLockFunc ++#undef AuRWLockFuncs ++ ++#define ii_read_unlock(i) au_rw_read_unlock(&au_ii(i)->ii_rwsem) ++#define ii_write_unlock(i) au_rw_write_unlock(&au_ii(i)->ii_rwsem) ++#define ii_downgrade_lock(i) au_rw_dgrade_lock(&au_ii(i)->ii_rwsem) ++ ++#define IiMustNoWaiters(i) AuRwMustNoWaiters(&au_ii(i)->ii_rwsem) ++#define IiMustAnyLock(i) AuRwMustAnyLock(&au_ii(i)->ii_rwsem) ++#define IiMustWriteLock(i) AuRwMustWriteLock(&au_ii(i)->ii_rwsem) ++ ++/* ---------------------------------------------------------------------- */ ++ ++static inline void au_icntnr_init(struct au_icntnr *c) ++{ ++#ifdef CONFIG_AUFS_DEBUG ++ c->vfs_inode.i_mode = 0; ++#endif ++} ++ ++static inline unsigned int au_iigen(struct inode *inode, unsigned int *igflags) ++{ ++ unsigned int gen; ++ struct au_iinfo *iinfo; ++ struct au_iigen *iigen; ++ ++ iinfo = au_ii(inode); ++ iigen = &iinfo->ii_generation; ++ spin_lock(&iigen->ig_spin); ++ if (igflags) ++ *igflags = iigen->ig_flags; ++ gen = iigen->ig_generation; ++ spin_unlock(&iigen->ig_spin); ++ ++ return gen; ++} ++ ++/* tiny test for inode number */ ++/* tmpfs generation is too rough */ ++static inline int au_test_higen(struct inode *inode, struct inode *h_inode) ++{ ++ struct au_iinfo *iinfo; ++ ++ iinfo = au_ii(inode); ++ AuRwMustAnyLock(&iinfo->ii_rwsem); ++ return !(iinfo->ii_hsb1 == h_inode->i_sb ++ && iinfo->ii_higen == h_inode->i_generation); ++} ++ ++static inline void au_iigen_dec(struct inode *inode) ++{ ++ struct au_iinfo *iinfo; ++ struct au_iigen *iigen; ++ ++ iinfo = au_ii(inode); ++ iigen = &iinfo->ii_generation; ++ spin_lock(&iigen->ig_spin); ++ iigen->ig_generation--; ++ spin_unlock(&iigen->ig_spin); ++} ++ ++static inline int au_iigen_test(struct inode *inode, unsigned int sigen) ++{ ++ int err; ++ ++ err = 0; ++ if (unlikely(inode && au_iigen(inode, NULL) != sigen)) ++ err = -EIO; ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static inline struct au_hinode *au_hinode(struct au_iinfo *iinfo, ++ aufs_bindex_t bindex) ++{ ++ return iinfo->ii_hinode + bindex; ++} ++ ++static inline int au_is_bad_inode(struct inode *inode) ++{ ++ return !!(is_bad_inode(inode) || !au_hinode(au_ii(inode), 0)); ++} ++ ++static inline aufs_bindex_t au_ii_br_id(struct inode *inode, ++ aufs_bindex_t bindex) ++{ ++ IiMustAnyLock(inode); ++ return au_hinode(au_ii(inode), bindex)->hi_id; ++} ++ ++static inline aufs_bindex_t au_ibtop(struct inode *inode) ++{ ++ IiMustAnyLock(inode); ++ return au_ii(inode)->ii_btop; ++} ++ ++static inline aufs_bindex_t au_ibbot(struct inode *inode) ++{ ++ IiMustAnyLock(inode); ++ return au_ii(inode)->ii_bbot; ++} ++ ++static inline struct au_vdir *au_ivdir(struct inode *inode) ++{ ++ IiMustAnyLock(inode); ++ return au_ii(inode)->ii_vdir; ++} ++ ++static inline struct dentry *au_hi_wh(struct inode *inode, aufs_bindex_t bindex) ++{ ++ IiMustAnyLock(inode); ++ return au_hinode(au_ii(inode), bindex)->hi_whdentry; ++} ++ ++static inline void au_set_ibtop(struct inode *inode, aufs_bindex_t bindex) ++{ ++ IiMustWriteLock(inode); ++ au_ii(inode)->ii_btop = bindex; ++} ++ ++static inline void au_set_ibbot(struct inode *inode, aufs_bindex_t bindex) ++{ ++ IiMustWriteLock(inode); ++ au_ii(inode)->ii_bbot = bindex; ++} ++ ++static inline void au_set_ivdir(struct inode *inode, struct au_vdir *vdir) ++{ ++ IiMustWriteLock(inode); ++ au_ii(inode)->ii_vdir = vdir; ++} ++ ++static inline struct au_hinode *au_hi(struct inode *inode, aufs_bindex_t bindex) ++{ ++ IiMustAnyLock(inode); ++ return au_hinode(au_ii(inode), bindex); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static inline struct dentry *au_pinned_parent(struct au_pin *pin) ++{ ++ if (pin) ++ return pin->parent; ++ return NULL; ++} ++ ++static inline struct inode *au_pinned_h_dir(struct au_pin *pin) ++{ ++ if (pin && pin->hdir) ++ return pin->hdir->hi_inode; ++ return NULL; ++} ++ ++static inline struct au_hinode *au_pinned_hdir(struct au_pin *pin) ++{ ++ if (pin) ++ return pin->hdir; ++ return NULL; ++} ++ ++static inline void au_pin_set_dentry(struct au_pin *pin, struct dentry *dentry) ++{ ++ if (pin) ++ pin->dentry = dentry; ++} ++ ++static inline void au_pin_set_parent_lflag(struct au_pin *pin, ++ unsigned char lflag) ++{ ++ if (pin) { ++ if (lflag) ++ au_fset_pin(pin->flags, DI_LOCKED); ++ else ++ au_fclr_pin(pin->flags, DI_LOCKED); ++ } ++} ++ ++#if 0 /* reserved */ ++static inline void au_pin_set_parent(struct au_pin *pin, struct dentry *parent) ++{ ++ if (pin) { ++ dput(pin->parent); ++ pin->parent = dget(parent); ++ } ++} ++#endif ++ ++/* ---------------------------------------------------------------------- */ ++ ++struct au_branch; ++#ifdef CONFIG_AUFS_HNOTIFY ++struct au_hnotify_op { ++ void (*ctl)(struct au_hinode *hinode, int do_set); ++ int (*alloc)(struct au_hinode *hinode); ++ ++ /* ++ * if it returns true, the the caller should free hinode->hi_notify, ++ * otherwise ->free() frees it. ++ */ ++ int (*free)(struct au_hinode *hinode, ++ struct au_hnotify *hn) __must_check; ++ ++ void (*fin)(void); ++ int (*init)(void); ++ ++ int (*reset_br)(unsigned int udba, struct au_branch *br, int perm); ++ void (*fin_br)(struct au_branch *br); ++ int (*init_br)(struct au_branch *br, int perm); ++}; ++ ++/* hnotify.c */ ++int au_hn_alloc(struct au_hinode *hinode, struct inode *inode); ++void au_hn_free(struct au_hinode *hinode); ++void au_hn_ctl(struct au_hinode *hinode, int do_set); ++void au_hn_reset(struct inode *inode, unsigned int flags); ++int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask, ++ const struct qstr *h_child_qstr, struct inode *h_child_inode); ++int au_hnotify_reset_br(unsigned int udba, struct au_branch *br, int perm); ++int au_hnotify_init_br(struct au_branch *br, int perm); ++void au_hnotify_fin_br(struct au_branch *br); ++int __init au_hnotify_init(void); ++void au_hnotify_fin(void); ++ ++/* hfsnotify.c */ ++extern const struct au_hnotify_op au_hnotify_op; ++ ++static inline ++void au_hn_init(struct au_hinode *hinode) ++{ ++ hinode->hi_notify = NULL; ++} ++ ++static inline struct au_hnotify *au_hn(struct au_hinode *hinode) ++{ ++ return hinode->hi_notify; ++} ++ ++#else ++AuStub(int, au_hn_alloc, return -EOPNOTSUPP, ++ struct au_hinode *hinode __maybe_unused, ++ struct inode *inode __maybe_unused) ++AuStub(struct au_hnotify *, au_hn, return NULL, struct au_hinode *hinode) ++AuStubVoid(au_hn_free, struct au_hinode *hinode __maybe_unused) ++AuStubVoid(au_hn_ctl, struct au_hinode *hinode __maybe_unused, ++ int do_set __maybe_unused) ++AuStubVoid(au_hn_reset, struct inode *inode __maybe_unused, ++ unsigned int flags __maybe_unused) ++AuStubInt0(au_hnotify_reset_br, unsigned int udba __maybe_unused, ++ struct au_branch *br __maybe_unused, ++ int perm __maybe_unused) ++AuStubInt0(au_hnotify_init_br, struct au_branch *br __maybe_unused, ++ int perm __maybe_unused) ++AuStubVoid(au_hnotify_fin_br, struct au_branch *br __maybe_unused) ++AuStubInt0(__init au_hnotify_init, void) ++AuStubVoid(au_hnotify_fin, void) ++AuStubVoid(au_hn_init, struct au_hinode *hinode __maybe_unused) ++#endif /* CONFIG_AUFS_HNOTIFY */ ++ ++static inline void au_hn_suspend(struct au_hinode *hdir) ++{ ++ au_hn_ctl(hdir, /*do_set*/0); ++} ++ ++static inline void au_hn_resume(struct au_hinode *hdir) ++{ ++ au_hn_ctl(hdir, /*do_set*/1); ++} ++ ++static inline void au_hn_inode_lock(struct au_hinode *hdir) ++{ ++ inode_lock(hdir->hi_inode); ++ au_hn_suspend(hdir); ++} ++ ++static inline void au_hn_inode_lock_nested(struct au_hinode *hdir, ++ unsigned int sc __maybe_unused) ++{ ++ inode_lock_nested(hdir->hi_inode, sc); ++ au_hn_suspend(hdir); ++} ++ ++#if 0 /* unused */ ++#include "vfsub.h" ++static inline void au_hn_inode_lock_shared_nested(struct au_hinode *hdir, ++ unsigned int sc) ++{ ++ inode_lock_shared_nested(hdir->hi_inode, sc); ++ au_hn_suspend(hdir); ++} ++#endif ++ ++static inline void au_hn_inode_unlock(struct au_hinode *hdir) ++{ ++ au_hn_resume(hdir); ++ inode_unlock(hdir->hi_inode); ++} ++ ++#endif /* __KERNEL__ */ ++#endif /* __AUFS_INODE_H__ */ +diff -Nurp linux-5.4/fs/aufs/ioctl.c linux-5.4-aufs/fs/aufs/ioctl.c +--- linux-5.4/fs/aufs/ioctl.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/ioctl.c 2019-11-28 01:25:59.066925618 +0200 +@@ -0,0 +1,207 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * ioctl ++ * plink-management and readdir in userspace. ++ * assist the pathconf(3) wrapper library. ++ * move-down ++ * File-based Hierarchical Storage Management. ++ */ ++ ++#include ++#include ++#include "aufs.h" ++ ++static int au_wbr_fd(struct path *path, struct aufs_wbr_fd __user *arg) ++{ ++ int err, fd; ++ aufs_bindex_t wbi, bindex, bbot; ++ struct file *h_file; ++ struct super_block *sb; ++ struct dentry *root; ++ struct au_branch *br; ++ struct aufs_wbr_fd wbrfd = { ++ .oflags = au_dir_roflags, ++ .brid = -1 ++ }; ++ const int valid = O_RDONLY | O_NONBLOCK | O_LARGEFILE | O_DIRECTORY ++ | O_NOATIME | O_CLOEXEC; ++ ++ AuDebugOn(wbrfd.oflags & ~valid); ++ ++ if (arg) { ++ err = copy_from_user(&wbrfd, arg, sizeof(wbrfd)); ++ if (unlikely(err)) { ++ err = -EFAULT; ++ goto out; ++ } ++ ++ err = -EINVAL; ++ AuDbg("wbrfd{0%o, %d}\n", wbrfd.oflags, wbrfd.brid); ++ wbrfd.oflags |= au_dir_roflags; ++ AuDbg("0%o\n", wbrfd.oflags); ++ if (unlikely(wbrfd.oflags & ~valid)) ++ goto out; ++ } ++ ++ fd = get_unused_fd_flags(0); ++ err = fd; ++ if (unlikely(fd < 0)) ++ goto out; ++ ++ h_file = ERR_PTR(-EINVAL); ++ wbi = 0; ++ br = NULL; ++ sb = path->dentry->d_sb; ++ root = sb->s_root; ++ aufs_read_lock(root, AuLock_IR); ++ bbot = au_sbbot(sb); ++ if (wbrfd.brid >= 0) { ++ wbi = au_br_index(sb, wbrfd.brid); ++ if (unlikely(wbi < 0 || wbi > bbot)) ++ goto out_unlock; ++ } ++ ++ h_file = ERR_PTR(-ENOENT); ++ br = au_sbr(sb, wbi); ++ if (!au_br_writable(br->br_perm)) { ++ if (arg) ++ goto out_unlock; ++ ++ bindex = wbi + 1; ++ wbi = -1; ++ for (; bindex <= bbot; bindex++) { ++ br = au_sbr(sb, bindex); ++ if (au_br_writable(br->br_perm)) { ++ wbi = bindex; ++ br = au_sbr(sb, wbi); ++ break; ++ } ++ } ++ } ++ AuDbg("wbi %d\n", wbi); ++ if (wbi >= 0) ++ h_file = au_h_open(root, wbi, wbrfd.oflags, NULL, ++ /*force_wr*/0); ++ ++out_unlock: ++ aufs_read_unlock(root, AuLock_IR); ++ err = PTR_ERR(h_file); ++ if (IS_ERR(h_file)) ++ goto out_fd; ++ ++ au_lcnt_dec(&br->br_nfiles); /* cf. au_h_open() */ ++ fd_install(fd, h_file); ++ err = fd; ++ goto out; /* success */ ++ ++out_fd: ++ put_unused_fd(fd); ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg) ++{ ++ long err; ++ struct dentry *dentry; ++ ++ switch (cmd) { ++ case AUFS_CTL_RDU: ++ case AUFS_CTL_RDU_INO: ++ err = au_rdu_ioctl(file, cmd, arg); ++ break; ++ ++ case AUFS_CTL_WBR_FD: ++ err = au_wbr_fd(&file->f_path, (void __user *)arg); ++ break; ++ ++ case AUFS_CTL_IBUSY: ++ err = au_ibusy_ioctl(file, arg); ++ break; ++ ++ case AUFS_CTL_BRINFO: ++ err = au_brinfo_ioctl(file, arg); ++ break; ++ ++ case AUFS_CTL_FHSM_FD: ++ dentry = file->f_path.dentry; ++ if (IS_ROOT(dentry)) ++ err = au_fhsm_fd(dentry->d_sb, arg); ++ else ++ err = -ENOTTY; ++ break; ++ ++ default: ++ /* do not call the lower */ ++ AuDbg("0x%x\n", cmd); ++ err = -ENOTTY; ++ } ++ ++ AuTraceErr(err); ++ return err; ++} ++ ++long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg) ++{ ++ long err; ++ ++ switch (cmd) { ++ case AUFS_CTL_MVDOWN: ++ err = au_mvdown(file->f_path.dentry, (void __user *)arg); ++ break; ++ ++ case AUFS_CTL_WBR_FD: ++ err = au_wbr_fd(&file->f_path, (void __user *)arg); ++ break; ++ ++ default: ++ /* do not call the lower */ ++ AuDbg("0x%x\n", cmd); ++ err = -ENOTTY; ++ } ++ ++ AuTraceErr(err); ++ return err; ++} ++ ++#ifdef CONFIG_COMPAT ++long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd, ++ unsigned long arg) ++{ ++ long err; ++ ++ switch (cmd) { ++ case AUFS_CTL_RDU: ++ case AUFS_CTL_RDU_INO: ++ err = au_rdu_compat_ioctl(file, cmd, arg); ++ break; ++ ++ case AUFS_CTL_IBUSY: ++ err = au_ibusy_compat_ioctl(file, arg); ++ break; ++ ++ case AUFS_CTL_BRINFO: ++ err = au_brinfo_compat_ioctl(file, arg); ++ break; ++ ++ default: ++ err = aufs_ioctl_dir(file, cmd, arg); ++ } ++ ++ AuTraceErr(err); ++ return err; ++} ++ ++long aufs_compat_ioctl_nondir(struct file *file, unsigned int cmd, ++ unsigned long arg) ++{ ++ return aufs_ioctl_nondir(file, cmd, (unsigned long)compat_ptr(arg)); ++} ++#endif +diff -Nurp linux-5.4/fs/aufs/i_op_add.c linux-5.4-aufs/fs/aufs/i_op_add.c +--- linux-5.4/fs/aufs/i_op_add.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/i_op_add.c 2019-11-28 01:25:59.065925618 +0200 +@@ -0,0 +1,923 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * inode operations (add entry) ++ */ ++ ++#include ++#include "aufs.h" ++ ++/* ++ * final procedure of adding a new entry, except link(2). ++ * remove whiteout, instantiate, copyup the parent dir's times and size ++ * and update version. ++ * if it failed, re-create the removed whiteout. ++ */ ++static int epilog(struct inode *dir, aufs_bindex_t bindex, ++ struct dentry *wh_dentry, struct dentry *dentry) ++{ ++ int err, rerr; ++ aufs_bindex_t bwh; ++ struct path h_path; ++ struct super_block *sb; ++ struct inode *inode, *h_dir; ++ struct dentry *wh; ++ ++ bwh = -1; ++ sb = dir->i_sb; ++ if (wh_dentry) { ++ h_dir = d_inode(wh_dentry->d_parent); /* dir inode is locked */ ++ IMustLock(h_dir); ++ AuDebugOn(au_h_iptr(dir, bindex) != h_dir); ++ bwh = au_dbwh(dentry); ++ h_path.dentry = wh_dentry; ++ h_path.mnt = au_sbr_mnt(sb, bindex); ++ err = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path, ++ dentry); ++ if (unlikely(err)) ++ goto out; ++ } ++ ++ inode = au_new_inode(dentry, /*must_new*/1); ++ if (!IS_ERR(inode)) { ++ d_instantiate(dentry, inode); ++ dir = d_inode(dentry->d_parent); /* dir inode is locked */ ++ IMustLock(dir); ++ au_dir_ts(dir, bindex); ++ inode_inc_iversion(dir); ++ au_fhsm_wrote(sb, bindex, /*force*/0); ++ return 0; /* success */ ++ } ++ ++ err = PTR_ERR(inode); ++ if (!wh_dentry) ++ goto out; ++ ++ /* revert */ ++ /* dir inode is locked */ ++ wh = au_wh_create(dentry, bwh, wh_dentry->d_parent); ++ rerr = PTR_ERR(wh); ++ if (IS_ERR(wh)) { ++ AuIOErr("%pd reverting whiteout failed(%d, %d)\n", ++ dentry, err, rerr); ++ err = -EIO; ++ } else ++ dput(wh); ++ ++out: ++ return err; ++} ++ ++static int au_d_may_add(struct dentry *dentry) ++{ ++ int err; ++ ++ err = 0; ++ if (unlikely(d_unhashed(dentry))) ++ err = -ENOENT; ++ if (unlikely(d_really_is_positive(dentry))) ++ err = -EEXIST; ++ return err; ++} ++ ++/* ++ * simple tests for the adding inode operations. ++ * following the checks in vfs, plus the parent-child relationship. ++ */ ++int au_may_add(struct dentry *dentry, aufs_bindex_t bindex, ++ struct dentry *h_parent, int isdir) ++{ ++ int err; ++ umode_t h_mode; ++ struct dentry *h_dentry; ++ struct inode *h_inode; ++ ++ err = -ENAMETOOLONG; ++ if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN)) ++ goto out; ++ ++ h_dentry = au_h_dptr(dentry, bindex); ++ if (d_really_is_negative(dentry)) { ++ err = -EEXIST; ++ if (unlikely(d_is_positive(h_dentry))) ++ goto out; ++ } else { ++ /* rename(2) case */ ++ err = -EIO; ++ if (unlikely(d_is_negative(h_dentry))) ++ goto out; ++ h_inode = d_inode(h_dentry); ++ if (unlikely(!h_inode->i_nlink)) ++ goto out; ++ ++ h_mode = h_inode->i_mode; ++ if (!isdir) { ++ err = -EISDIR; ++ if (unlikely(S_ISDIR(h_mode))) ++ goto out; ++ } else if (unlikely(!S_ISDIR(h_mode))) { ++ err = -ENOTDIR; ++ goto out; ++ } ++ } ++ ++ err = 0; ++ /* expected parent dir is locked */ ++ if (unlikely(h_parent != h_dentry->d_parent)) ++ err = -EIO; ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++/* ++ * initial procedure of adding a new entry. ++ * prepare writable branch and the parent dir, lock it, ++ * and lookup whiteout for the new entry. ++ */ ++static struct dentry* ++lock_hdir_lkup_wh(struct dentry *dentry, struct au_dtime *dt, ++ struct dentry *src_dentry, struct au_pin *pin, ++ struct au_wr_dir_args *wr_dir_args) ++{ ++ struct dentry *wh_dentry, *h_parent; ++ struct super_block *sb; ++ struct au_branch *br; ++ int err; ++ unsigned int udba; ++ aufs_bindex_t bcpup; ++ ++ AuDbg("%pd\n", dentry); ++ ++ err = au_wr_dir(dentry, src_dentry, wr_dir_args); ++ bcpup = err; ++ wh_dentry = ERR_PTR(err); ++ if (unlikely(err < 0)) ++ goto out; ++ ++ sb = dentry->d_sb; ++ udba = au_opt_udba(sb); ++ err = au_pin(pin, dentry, bcpup, udba, ++ AuPin_DI_LOCKED | AuPin_MNT_WRITE); ++ wh_dentry = ERR_PTR(err); ++ if (unlikely(err)) ++ goto out; ++ ++ h_parent = au_pinned_h_parent(pin); ++ if (udba != AuOpt_UDBA_NONE ++ && au_dbtop(dentry) == bcpup) ++ err = au_may_add(dentry, bcpup, h_parent, ++ au_ftest_wrdir(wr_dir_args->flags, ISDIR)); ++ else if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN)) ++ err = -ENAMETOOLONG; ++ wh_dentry = ERR_PTR(err); ++ if (unlikely(err)) ++ goto out_unpin; ++ ++ br = au_sbr(sb, bcpup); ++ if (dt) { ++ struct path tmp = { ++ .dentry = h_parent, ++ .mnt = au_br_mnt(br) ++ }; ++ au_dtime_store(dt, au_pinned_parent(pin), &tmp); ++ } ++ ++ wh_dentry = NULL; ++ if (bcpup != au_dbwh(dentry)) ++ goto out; /* success */ ++ ++ /* ++ * ENAMETOOLONG here means that if we allowed create such name, then it ++ * would not be able to removed in the future. So we don't allow such ++ * name here and we don't handle ENAMETOOLONG differently here. ++ */ ++ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, br); ++ ++out_unpin: ++ if (IS_ERR(wh_dentry)) ++ au_unpin(pin); ++out: ++ return wh_dentry; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++enum { Mknod, Symlink, Creat }; ++struct simple_arg { ++ int type; ++ union { ++ struct { ++ umode_t mode; ++ bool want_excl; ++ bool try_aopen; ++ struct vfsub_aopen_args *aopen; ++ } c; ++ struct { ++ const char *symname; ++ } s; ++ struct { ++ umode_t mode; ++ dev_t dev; ++ } m; ++ } u; ++}; ++ ++static int add_simple(struct inode *dir, struct dentry *dentry, ++ struct simple_arg *arg) ++{ ++ int err, rerr; ++ aufs_bindex_t btop; ++ unsigned char created; ++ const unsigned char try_aopen ++ = (arg->type == Creat && arg->u.c.try_aopen); ++ struct vfsub_aopen_args *aopen = arg->u.c.aopen; ++ struct dentry *wh_dentry, *parent; ++ struct inode *h_dir; ++ struct super_block *sb; ++ struct au_branch *br; ++ /* to reduce stack size */ ++ struct { ++ struct au_dtime dt; ++ struct au_pin pin; ++ struct path h_path; ++ struct au_wr_dir_args wr_dir_args; ++ } *a; ++ ++ AuDbg("%pd\n", dentry); ++ IMustLock(dir); ++ ++ err = -ENOMEM; ++ a = kmalloc(sizeof(*a), GFP_NOFS); ++ if (unlikely(!a)) ++ goto out; ++ a->wr_dir_args.force_btgt = -1; ++ a->wr_dir_args.flags = AuWrDir_ADD_ENTRY; ++ ++ parent = dentry->d_parent; /* dir inode is locked */ ++ if (!try_aopen) { ++ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN); ++ if (unlikely(err)) ++ goto out_free; ++ } ++ err = au_d_may_add(dentry); ++ if (unlikely(err)) ++ goto out_unlock; ++ if (!try_aopen) ++ di_write_lock_parent(parent); ++ wh_dentry = lock_hdir_lkup_wh(dentry, &a->dt, /*src_dentry*/NULL, ++ &a->pin, &a->wr_dir_args); ++ err = PTR_ERR(wh_dentry); ++ if (IS_ERR(wh_dentry)) ++ goto out_parent; ++ ++ btop = au_dbtop(dentry); ++ sb = dentry->d_sb; ++ br = au_sbr(sb, btop); ++ a->h_path.dentry = au_h_dptr(dentry, btop); ++ a->h_path.mnt = au_br_mnt(br); ++ h_dir = au_pinned_h_dir(&a->pin); ++ switch (arg->type) { ++ case Creat: ++ if (!try_aopen || !h_dir->i_op->atomic_open) { ++ err = vfsub_create(h_dir, &a->h_path, arg->u.c.mode, ++ arg->u.c.want_excl); ++ created = !err; ++ if (!err && try_aopen) ++ aopen->file->f_mode |= FMODE_CREATED; ++ } else { ++ aopen->br = br; ++ err = vfsub_atomic_open(h_dir, a->h_path.dentry, aopen); ++ AuDbg("err %d\n", err); ++ AuDbgFile(aopen->file); ++ created = err >= 0 ++ && !!(aopen->file->f_mode & FMODE_CREATED); ++ } ++ break; ++ case Symlink: ++ err = vfsub_symlink(h_dir, &a->h_path, arg->u.s.symname); ++ created = !err; ++ break; ++ case Mknod: ++ err = vfsub_mknod(h_dir, &a->h_path, arg->u.m.mode, ++ arg->u.m.dev); ++ created = !err; ++ break; ++ default: ++ BUG(); ++ } ++ if (unlikely(err < 0)) ++ goto out_unpin; ++ ++ err = epilog(dir, btop, wh_dentry, dentry); ++ if (!err) ++ goto out_unpin; /* success */ ++ ++ /* revert */ ++ if (created /* && d_is_positive(a->h_path.dentry) */) { ++ /* no delegation since it is just created */ ++ rerr = vfsub_unlink(h_dir, &a->h_path, /*delegated*/NULL, ++ /*force*/0); ++ if (rerr) { ++ AuIOErr("%pd revert failure(%d, %d)\n", ++ dentry, err, rerr); ++ err = -EIO; ++ } ++ au_dtime_revert(&a->dt); ++ } ++ if (try_aopen && h_dir->i_op->atomic_open ++ && (aopen->file->f_mode & FMODE_OPENED)) ++ /* aopen->file is still opened */ ++ au_lcnt_dec(&aopen->br->br_nfiles); ++ ++out_unpin: ++ au_unpin(&a->pin); ++ dput(wh_dentry); ++out_parent: ++ if (!try_aopen) ++ di_write_unlock(parent); ++out_unlock: ++ if (unlikely(err)) { ++ au_update_dbtop(dentry); ++ d_drop(dentry); ++ } ++ if (!try_aopen) ++ aufs_read_unlock(dentry, AuLock_DW); ++out_free: ++ au_kfree_rcu(a); ++out: ++ return err; ++} ++ ++int aufs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, ++ dev_t dev) ++{ ++ struct simple_arg arg = { ++ .type = Mknod, ++ .u.m = { ++ .mode = mode, ++ .dev = dev ++ } ++ }; ++ return add_simple(dir, dentry, &arg); ++} ++ ++int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) ++{ ++ struct simple_arg arg = { ++ .type = Symlink, ++ .u.s.symname = symname ++ }; ++ return add_simple(dir, dentry, &arg); ++} ++ ++int aufs_create(struct inode *dir, struct dentry *dentry, umode_t mode, ++ bool want_excl) ++{ ++ struct simple_arg arg = { ++ .type = Creat, ++ .u.c = { ++ .mode = mode, ++ .want_excl = want_excl ++ } ++ }; ++ return add_simple(dir, dentry, &arg); ++} ++ ++int au_aopen_or_create(struct inode *dir, struct dentry *dentry, ++ struct vfsub_aopen_args *aopen_args) ++{ ++ struct simple_arg arg = { ++ .type = Creat, ++ .u.c = { ++ .mode = aopen_args->create_mode, ++ .want_excl = aopen_args->open_flag & O_EXCL, ++ .try_aopen = true, ++ .aopen = aopen_args ++ } ++ }; ++ return add_simple(dir, dentry, &arg); ++} ++ ++int aufs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode) ++{ ++ int err; ++ aufs_bindex_t bindex; ++ struct super_block *sb; ++ struct dentry *parent, *h_parent, *h_dentry; ++ struct inode *h_dir, *inode; ++ struct vfsmount *h_mnt; ++ struct au_wr_dir_args wr_dir_args = { ++ .force_btgt = -1, ++ .flags = AuWrDir_TMPFILE ++ }; ++ ++ /* copy-up may happen */ ++ inode_lock(dir); ++ ++ sb = dir->i_sb; ++ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM); ++ if (unlikely(err)) ++ goto out; ++ ++ err = au_di_init(dentry); ++ if (unlikely(err)) ++ goto out_si; ++ ++ err = -EBUSY; ++ parent = d_find_any_alias(dir); ++ AuDebugOn(!parent); ++ di_write_lock_parent(parent); ++ if (unlikely(d_inode(parent) != dir)) ++ goto out_parent; ++ ++ err = au_digen_test(parent, au_sigen(sb)); ++ if (unlikely(err)) ++ goto out_parent; ++ ++ bindex = au_dbtop(parent); ++ au_set_dbtop(dentry, bindex); ++ au_set_dbbot(dentry, bindex); ++ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args); ++ bindex = err; ++ if (unlikely(err < 0)) ++ goto out_parent; ++ ++ err = -EOPNOTSUPP; ++ h_dir = au_h_iptr(dir, bindex); ++ if (unlikely(!h_dir->i_op->tmpfile)) ++ goto out_parent; ++ ++ h_mnt = au_sbr_mnt(sb, bindex); ++ err = vfsub_mnt_want_write(h_mnt); ++ if (unlikely(err)) ++ goto out_parent; ++ ++ h_parent = au_h_dptr(parent, bindex); ++ h_dentry = vfs_tmpfile(h_parent, mode, /*open_flag*/0); ++ if (IS_ERR(h_dentry)) { ++ err = PTR_ERR(h_dentry); ++ goto out_mnt; ++ } ++ ++ au_set_dbtop(dentry, bindex); ++ au_set_dbbot(dentry, bindex); ++ au_set_h_dptr(dentry, bindex, dget(h_dentry)); ++ inode = au_new_inode(dentry, /*must_new*/1); ++ if (IS_ERR(inode)) { ++ err = PTR_ERR(inode); ++ au_set_h_dptr(dentry, bindex, NULL); ++ au_set_dbtop(dentry, -1); ++ au_set_dbbot(dentry, -1); ++ } else { ++ if (!inode->i_nlink) ++ set_nlink(inode, 1); ++ d_tmpfile(dentry, inode); ++ au_di(dentry)->di_tmpfile = 1; ++ ++ /* update without i_mutex */ ++ if (au_ibtop(dir) == au_dbtop(dentry)) ++ au_cpup_attr_timesizes(dir); ++ } ++ dput(h_dentry); ++ ++out_mnt: ++ vfsub_mnt_drop_write(h_mnt); ++out_parent: ++ di_write_unlock(parent); ++ dput(parent); ++ di_write_unlock(dentry); ++ if (unlikely(err)) { ++ au_di_fin(dentry); ++ dentry->d_fsdata = NULL; ++ } ++out_si: ++ si_read_unlock(sb); ++out: ++ inode_unlock(dir); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++struct au_link_args { ++ aufs_bindex_t bdst, bsrc; ++ struct au_pin pin; ++ struct path h_path; ++ struct dentry *src_parent, *parent; ++}; ++ ++static int au_cpup_before_link(struct dentry *src_dentry, ++ struct au_link_args *a) ++{ ++ int err; ++ struct dentry *h_src_dentry; ++ struct au_cp_generic cpg = { ++ .dentry = src_dentry, ++ .bdst = a->bdst, ++ .bsrc = a->bsrc, ++ .len = -1, ++ .pin = &a->pin, ++ .flags = AuCpup_DTIME | AuCpup_HOPEN /* | AuCpup_KEEPLINO */ ++ }; ++ ++ di_read_lock_parent(a->src_parent, AuLock_IR); ++ err = au_test_and_cpup_dirs(src_dentry, a->bdst); ++ if (unlikely(err)) ++ goto out; ++ ++ h_src_dentry = au_h_dptr(src_dentry, a->bsrc); ++ err = au_pin(&a->pin, src_dentry, a->bdst, ++ au_opt_udba(src_dentry->d_sb), ++ AuPin_DI_LOCKED | AuPin_MNT_WRITE); ++ if (unlikely(err)) ++ goto out; ++ ++ err = au_sio_cpup_simple(&cpg); ++ au_unpin(&a->pin); ++ ++out: ++ di_read_unlock(a->src_parent, AuLock_IR); ++ return err; ++} ++ ++static int au_cpup_or_link(struct dentry *src_dentry, struct dentry *dentry, ++ struct au_link_args *a) ++{ ++ int err; ++ unsigned char plink; ++ aufs_bindex_t bbot; ++ struct dentry *h_src_dentry; ++ struct inode *h_inode, *inode, *delegated; ++ struct super_block *sb; ++ struct file *h_file; ++ ++ plink = 0; ++ h_inode = NULL; ++ sb = src_dentry->d_sb; ++ inode = d_inode(src_dentry); ++ if (au_ibtop(inode) <= a->bdst) ++ h_inode = au_h_iptr(inode, a->bdst); ++ if (!h_inode || !h_inode->i_nlink) { ++ /* copyup src_dentry as the name of dentry. */ ++ bbot = au_dbbot(dentry); ++ if (bbot < a->bsrc) ++ au_set_dbbot(dentry, a->bsrc); ++ au_set_h_dptr(dentry, a->bsrc, ++ dget(au_h_dptr(src_dentry, a->bsrc))); ++ dget(a->h_path.dentry); ++ au_set_h_dptr(dentry, a->bdst, NULL); ++ AuDbg("temporary d_inode...\n"); ++ spin_lock(&dentry->d_lock); ++ dentry->d_inode = d_inode(src_dentry); /* tmp */ ++ spin_unlock(&dentry->d_lock); ++ h_file = au_h_open_pre(dentry, a->bsrc, /*force_wr*/0); ++ if (IS_ERR(h_file)) ++ err = PTR_ERR(h_file); ++ else { ++ struct au_cp_generic cpg = { ++ .dentry = dentry, ++ .bdst = a->bdst, ++ .bsrc = -1, ++ .len = -1, ++ .pin = &a->pin, ++ .flags = AuCpup_KEEPLINO ++ }; ++ err = au_sio_cpup_simple(&cpg); ++ au_h_open_post(dentry, a->bsrc, h_file); ++ if (!err) { ++ dput(a->h_path.dentry); ++ a->h_path.dentry = au_h_dptr(dentry, a->bdst); ++ } else ++ au_set_h_dptr(dentry, a->bdst, ++ a->h_path.dentry); ++ } ++ spin_lock(&dentry->d_lock); ++ dentry->d_inode = NULL; /* restore */ ++ spin_unlock(&dentry->d_lock); ++ AuDbg("temporary d_inode...done\n"); ++ au_set_h_dptr(dentry, a->bsrc, NULL); ++ au_set_dbbot(dentry, bbot); ++ } else { ++ /* the inode of src_dentry already exists on a.bdst branch */ ++ h_src_dentry = d_find_alias(h_inode); ++ if (!h_src_dentry && au_plink_test(inode)) { ++ plink = 1; ++ h_src_dentry = au_plink_lkup(inode, a->bdst); ++ err = PTR_ERR(h_src_dentry); ++ if (IS_ERR(h_src_dentry)) ++ goto out; ++ ++ if (unlikely(d_is_negative(h_src_dentry))) { ++ dput(h_src_dentry); ++ h_src_dentry = NULL; ++ } ++ ++ } ++ if (h_src_dentry) { ++ delegated = NULL; ++ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin), ++ &a->h_path, &delegated); ++ if (unlikely(err == -EWOULDBLOCK)) { ++ pr_warn("cannot retry for NFSv4 delegation" ++ " for an internal link\n"); ++ iput(delegated); ++ } ++ dput(h_src_dentry); ++ } else { ++ AuIOErr("no dentry found for hi%lu on b%d\n", ++ h_inode->i_ino, a->bdst); ++ err = -EIO; ++ } ++ } ++ ++ if (!err && !plink) ++ au_plink_append(inode, a->bdst, a->h_path.dentry); ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++int aufs_link(struct dentry *src_dentry, struct inode *dir, ++ struct dentry *dentry) ++{ ++ int err, rerr; ++ struct au_dtime dt; ++ struct au_link_args *a; ++ struct dentry *wh_dentry, *h_src_dentry; ++ struct inode *inode, *delegated; ++ struct super_block *sb; ++ struct au_wr_dir_args wr_dir_args = { ++ /* .force_btgt = -1, */ ++ .flags = AuWrDir_ADD_ENTRY ++ }; ++ ++ IMustLock(dir); ++ inode = d_inode(src_dentry); ++ IMustLock(inode); ++ ++ err = -ENOMEM; ++ a = kzalloc(sizeof(*a), GFP_NOFS); ++ if (unlikely(!a)) ++ goto out; ++ ++ a->parent = dentry->d_parent; /* dir inode is locked */ ++ err = aufs_read_and_write_lock2(dentry, src_dentry, ++ AuLock_NOPLM | AuLock_GEN); ++ if (unlikely(err)) ++ goto out_kfree; ++ err = au_d_linkable(src_dentry); ++ if (unlikely(err)) ++ goto out_unlock; ++ err = au_d_may_add(dentry); ++ if (unlikely(err)) ++ goto out_unlock; ++ ++ a->src_parent = dget_parent(src_dentry); ++ wr_dir_args.force_btgt = au_ibtop(inode); ++ ++ di_write_lock_parent(a->parent); ++ wr_dir_args.force_btgt = au_wbr(dentry, wr_dir_args.force_btgt); ++ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, src_dentry, &a->pin, ++ &wr_dir_args); ++ err = PTR_ERR(wh_dentry); ++ if (IS_ERR(wh_dentry)) ++ goto out_parent; ++ ++ err = 0; ++ sb = dentry->d_sb; ++ a->bdst = au_dbtop(dentry); ++ a->h_path.dentry = au_h_dptr(dentry, a->bdst); ++ a->h_path.mnt = au_sbr_mnt(sb, a->bdst); ++ a->bsrc = au_ibtop(inode); ++ h_src_dentry = au_h_d_alias(src_dentry, a->bsrc); ++ if (!h_src_dentry && au_di(src_dentry)->di_tmpfile) ++ h_src_dentry = dget(au_hi_wh(inode, a->bsrc)); ++ if (!h_src_dentry) { ++ a->bsrc = au_dbtop(src_dentry); ++ h_src_dentry = au_h_d_alias(src_dentry, a->bsrc); ++ AuDebugOn(!h_src_dentry); ++ } else if (IS_ERR(h_src_dentry)) { ++ err = PTR_ERR(h_src_dentry); ++ goto out_parent; ++ } ++ ++ /* ++ * aufs doesn't touch the credential so ++ * security_dentry_create_files_as() is unnecessary. ++ */ ++ if (au_opt_test(au_mntflags(sb), PLINK)) { ++ if (a->bdst < a->bsrc ++ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */) ++ err = au_cpup_or_link(src_dentry, dentry, a); ++ else { ++ delegated = NULL; ++ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin), ++ &a->h_path, &delegated); ++ if (unlikely(err == -EWOULDBLOCK)) { ++ pr_warn("cannot retry for NFSv4 delegation" ++ " for an internal link\n"); ++ iput(delegated); ++ } ++ } ++ dput(h_src_dentry); ++ } else { ++ /* ++ * copyup src_dentry to the branch we process, ++ * and then link(2) to it. ++ */ ++ dput(h_src_dentry); ++ if (a->bdst < a->bsrc ++ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */) { ++ au_unpin(&a->pin); ++ di_write_unlock(a->parent); ++ err = au_cpup_before_link(src_dentry, a); ++ di_write_lock_parent(a->parent); ++ if (!err) ++ err = au_pin(&a->pin, dentry, a->bdst, ++ au_opt_udba(sb), ++ AuPin_DI_LOCKED | AuPin_MNT_WRITE); ++ if (unlikely(err)) ++ goto out_wh; ++ } ++ if (!err) { ++ h_src_dentry = au_h_dptr(src_dentry, a->bdst); ++ err = -ENOENT; ++ if (h_src_dentry && d_is_positive(h_src_dentry)) { ++ delegated = NULL; ++ err = vfsub_link(h_src_dentry, ++ au_pinned_h_dir(&a->pin), ++ &a->h_path, &delegated); ++ if (unlikely(err == -EWOULDBLOCK)) { ++ pr_warn("cannot retry" ++ " for NFSv4 delegation" ++ " for an internal link\n"); ++ iput(delegated); ++ } ++ } ++ } ++ } ++ if (unlikely(err)) ++ goto out_unpin; ++ ++ if (wh_dentry) { ++ a->h_path.dentry = wh_dentry; ++ err = au_wh_unlink_dentry(au_pinned_h_dir(&a->pin), &a->h_path, ++ dentry); ++ if (unlikely(err)) ++ goto out_revert; ++ } ++ ++ au_dir_ts(dir, a->bdst); ++ inode_inc_iversion(dir); ++ inc_nlink(inode); ++ inode->i_ctime = dir->i_ctime; ++ d_instantiate(dentry, au_igrab(inode)); ++ if (d_unhashed(a->h_path.dentry)) ++ /* some filesystem calls d_drop() */ ++ d_drop(dentry); ++ /* some filesystems consume an inode even hardlink */ ++ au_fhsm_wrote(sb, a->bdst, /*force*/0); ++ goto out_unpin; /* success */ ++ ++out_revert: ++ /* no delegation since it is just created */ ++ rerr = vfsub_unlink(au_pinned_h_dir(&a->pin), &a->h_path, ++ /*delegated*/NULL, /*force*/0); ++ if (unlikely(rerr)) { ++ AuIOErr("%pd reverting failed(%d, %d)\n", dentry, err, rerr); ++ err = -EIO; ++ } ++ au_dtime_revert(&dt); ++out_unpin: ++ au_unpin(&a->pin); ++out_wh: ++ dput(wh_dentry); ++out_parent: ++ di_write_unlock(a->parent); ++ dput(a->src_parent); ++out_unlock: ++ if (unlikely(err)) { ++ au_update_dbtop(dentry); ++ d_drop(dentry); ++ } ++ aufs_read_and_write_unlock2(dentry, src_dentry); ++out_kfree: ++ au_kfree_rcu(a); ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++int aufs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) ++{ ++ int err, rerr; ++ aufs_bindex_t bindex; ++ unsigned char diropq; ++ struct path h_path; ++ struct dentry *wh_dentry, *parent, *opq_dentry; ++ struct inode *h_inode; ++ struct super_block *sb; ++ struct { ++ struct au_pin pin; ++ struct au_dtime dt; ++ } *a; /* reduce the stack usage */ ++ struct au_wr_dir_args wr_dir_args = { ++ .force_btgt = -1, ++ .flags = AuWrDir_ADD_ENTRY | AuWrDir_ISDIR ++ }; ++ ++ IMustLock(dir); ++ ++ err = -ENOMEM; ++ a = kmalloc(sizeof(*a), GFP_NOFS); ++ if (unlikely(!a)) ++ goto out; ++ ++ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN); ++ if (unlikely(err)) ++ goto out_free; ++ err = au_d_may_add(dentry); ++ if (unlikely(err)) ++ goto out_unlock; ++ ++ parent = dentry->d_parent; /* dir inode is locked */ ++ di_write_lock_parent(parent); ++ wh_dentry = lock_hdir_lkup_wh(dentry, &a->dt, /*src_dentry*/NULL, ++ &a->pin, &wr_dir_args); ++ err = PTR_ERR(wh_dentry); ++ if (IS_ERR(wh_dentry)) ++ goto out_parent; ++ ++ sb = dentry->d_sb; ++ bindex = au_dbtop(dentry); ++ h_path.dentry = au_h_dptr(dentry, bindex); ++ h_path.mnt = au_sbr_mnt(sb, bindex); ++ err = vfsub_mkdir(au_pinned_h_dir(&a->pin), &h_path, mode); ++ if (unlikely(err)) ++ goto out_unpin; ++ ++ /* make the dir opaque */ ++ diropq = 0; ++ h_inode = d_inode(h_path.dentry); ++ if (wh_dentry ++ || au_opt_test(au_mntflags(sb), ALWAYS_DIROPQ)) { ++ inode_lock_nested(h_inode, AuLsc_I_CHILD); ++ opq_dentry = au_diropq_create(dentry, bindex); ++ inode_unlock(h_inode); ++ err = PTR_ERR(opq_dentry); ++ if (IS_ERR(opq_dentry)) ++ goto out_dir; ++ dput(opq_dentry); ++ diropq = 1; ++ } ++ ++ err = epilog(dir, bindex, wh_dentry, dentry); ++ if (!err) { ++ inc_nlink(dir); ++ goto out_unpin; /* success */ ++ } ++ ++ /* revert */ ++ if (diropq) { ++ AuLabel(revert opq); ++ inode_lock_nested(h_inode, AuLsc_I_CHILD); ++ rerr = au_diropq_remove(dentry, bindex); ++ inode_unlock(h_inode); ++ if (rerr) { ++ AuIOErr("%pd reverting diropq failed(%d, %d)\n", ++ dentry, err, rerr); ++ err = -EIO; ++ } ++ } ++ ++out_dir: ++ AuLabel(revert dir); ++ rerr = vfsub_rmdir(au_pinned_h_dir(&a->pin), &h_path); ++ if (rerr) { ++ AuIOErr("%pd reverting dir failed(%d, %d)\n", ++ dentry, err, rerr); ++ err = -EIO; ++ } ++ au_dtime_revert(&a->dt); ++out_unpin: ++ au_unpin(&a->pin); ++ dput(wh_dentry); ++out_parent: ++ di_write_unlock(parent); ++out_unlock: ++ if (unlikely(err)) { ++ au_update_dbtop(dentry); ++ d_drop(dentry); ++ } ++ aufs_read_unlock(dentry, AuLock_DW); ++out_free: ++ au_kfree_rcu(a); ++out: ++ return err; ++} +diff -Nurp linux-5.4/fs/aufs/i_op.c linux-5.4-aufs/fs/aufs/i_op.c +--- linux-5.4/fs/aufs/i_op.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/i_op.c 2019-11-28 01:25:59.065925618 +0200 +@@ -0,0 +1,1492 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * inode operations (except add/del/rename) ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include "aufs.h" ++ ++static int h_permission(struct inode *h_inode, int mask, ++ struct path *h_path, int brperm) ++{ ++ int err; ++ const unsigned char write_mask = !!(mask & (MAY_WRITE | MAY_APPEND)); ++ ++ err = -EPERM; ++ if (write_mask && IS_IMMUTABLE(h_inode)) ++ goto out; ++ ++ err = -EACCES; ++ if (((mask & MAY_EXEC) ++ && S_ISREG(h_inode->i_mode) ++ && (path_noexec(h_path) ++ || !(h_inode->i_mode & 0111)))) ++ goto out; ++ ++ /* ++ * - skip the lower fs test in the case of write to ro branch. ++ * - nfs dir permission write check is optimized, but a policy for ++ * link/rename requires a real check. ++ * - nfs always sets SB_POSIXACL regardless its mount option 'noacl.' ++ * in this case, generic_permission() returns -EOPNOTSUPP. ++ */ ++ if ((write_mask && !au_br_writable(brperm)) ++ || (au_test_nfs(h_inode->i_sb) && S_ISDIR(h_inode->i_mode) ++ && write_mask && !(mask & MAY_READ)) ++ || !h_inode->i_op->permission) { ++ /* AuLabel(generic_permission); */ ++ /* AuDbg("get_acl %ps\n", h_inode->i_op->get_acl); */ ++ err = generic_permission(h_inode, mask); ++ if (err == -EOPNOTSUPP && au_test_nfs_noacl(h_inode)) ++ err = h_inode->i_op->permission(h_inode, mask); ++ AuTraceErr(err); ++ } else { ++ /* AuLabel(h_inode->permission); */ ++ err = h_inode->i_op->permission(h_inode, mask); ++ AuTraceErr(err); ++ } ++ ++ if (!err) ++ err = devcgroup_inode_permission(h_inode, mask); ++ if (!err) ++ err = security_inode_permission(h_inode, mask); ++ ++#if 0 ++ if (!err) { ++ /* todo: do we need to call ima_path_check()? */ ++ struct path h_path = { ++ .dentry = ++ .mnt = h_mnt ++ }; ++ err = ima_path_check(&h_path, ++ mask & (MAY_READ | MAY_WRITE | MAY_EXEC), ++ IMA_COUNT_LEAVE); ++ } ++#endif ++ ++out: ++ return err; ++} ++ ++static int aufs_permission(struct inode *inode, int mask) ++{ ++ int err; ++ aufs_bindex_t bindex, bbot; ++ const unsigned char isdir = !!S_ISDIR(inode->i_mode), ++ write_mask = !!(mask & (MAY_WRITE | MAY_APPEND)); ++ struct inode *h_inode; ++ struct super_block *sb; ++ struct au_branch *br; ++ ++ /* todo: support rcu-walk? */ ++ if (mask & MAY_NOT_BLOCK) ++ return -ECHILD; ++ ++ sb = inode->i_sb; ++ si_read_lock(sb, AuLock_FLUSH); ++ ii_read_lock_child(inode); ++#if 0 ++ err = au_iigen_test(inode, au_sigen(sb)); ++ if (unlikely(err)) ++ goto out; ++#endif ++ ++ if (!isdir ++ || write_mask ++ || au_opt_test(au_mntflags(sb), DIRPERM1)) { ++ err = au_busy_or_stale(); ++ h_inode = au_h_iptr(inode, au_ibtop(inode)); ++ if (unlikely(!h_inode ++ || (h_inode->i_mode & S_IFMT) ++ != (inode->i_mode & S_IFMT))) ++ goto out; ++ ++ err = 0; ++ bindex = au_ibtop(inode); ++ br = au_sbr(sb, bindex); ++ err = h_permission(h_inode, mask, &br->br_path, br->br_perm); ++ if (write_mask ++ && !err ++ && !special_file(h_inode->i_mode)) { ++ /* test whether the upper writable branch exists */ ++ err = -EROFS; ++ for (; bindex >= 0; bindex--) ++ if (!au_br_rdonly(au_sbr(sb, bindex))) { ++ err = 0; ++ break; ++ } ++ } ++ goto out; ++ } ++ ++ /* non-write to dir */ ++ err = 0; ++ bbot = au_ibbot(inode); ++ for (bindex = au_ibtop(inode); !err && bindex <= bbot; bindex++) { ++ h_inode = au_h_iptr(inode, bindex); ++ if (h_inode) { ++ err = au_busy_or_stale(); ++ if (unlikely(!S_ISDIR(h_inode->i_mode))) ++ break; ++ ++ br = au_sbr(sb, bindex); ++ err = h_permission(h_inode, mask, &br->br_path, ++ br->br_perm); ++ } ++ } ++ ++out: ++ ii_read_unlock(inode); ++ si_read_unlock(sb); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static struct dentry *aufs_lookup(struct inode *dir, struct dentry *dentry, ++ unsigned int flags) ++{ ++ struct dentry *ret, *parent; ++ struct inode *inode; ++ struct super_block *sb; ++ int err, npositive; ++ ++ IMustLock(dir); ++ ++ /* todo: support rcu-walk? */ ++ ret = ERR_PTR(-ECHILD); ++ if (flags & LOOKUP_RCU) ++ goto out; ++ ++ ret = ERR_PTR(-ENAMETOOLONG); ++ if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN)) ++ goto out; ++ ++ sb = dir->i_sb; ++ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM); ++ ret = ERR_PTR(err); ++ if (unlikely(err)) ++ goto out; ++ ++ err = au_di_init(dentry); ++ ret = ERR_PTR(err); ++ if (unlikely(err)) ++ goto out_si; ++ ++ inode = NULL; ++ npositive = 0; /* suppress a warning */ ++ parent = dentry->d_parent; /* dir inode is locked */ ++ di_read_lock_parent(parent, AuLock_IR); ++ err = au_alive_dir(parent); ++ if (!err) ++ err = au_digen_test(parent, au_sigen(sb)); ++ if (!err) { ++ /* regardless LOOKUP_CREATE, always ALLOW_NEG */ ++ npositive = au_lkup_dentry(dentry, au_dbtop(parent), ++ AuLkup_ALLOW_NEG); ++ err = npositive; ++ } ++ di_read_unlock(parent, AuLock_IR); ++ ret = ERR_PTR(err); ++ if (unlikely(err < 0)) ++ goto out_unlock; ++ ++ if (npositive) { ++ inode = au_new_inode(dentry, /*must_new*/0); ++ if (IS_ERR(inode)) { ++ ret = (void *)inode; ++ inode = NULL; ++ goto out_unlock; ++ } ++ } ++ ++ if (inode) ++ atomic_inc(&inode->i_count); ++ ret = d_splice_alias(inode, dentry); ++#if 0 ++ if (unlikely(d_need_lookup(dentry))) { ++ spin_lock(&dentry->d_lock); ++ dentry->d_flags &= ~DCACHE_NEED_LOOKUP; ++ spin_unlock(&dentry->d_lock); ++ } else ++#endif ++ if (inode) { ++ if (!IS_ERR(ret)) { ++ iput(inode); ++ if (ret && ret != dentry) ++ ii_write_unlock(inode); ++ } else { ++ ii_write_unlock(inode); ++ iput(inode); ++ inode = NULL; ++ } ++ } ++ ++out_unlock: ++ di_write_unlock(dentry); ++out_si: ++ si_read_unlock(sb); ++out: ++ return ret; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * very dirty and complicated aufs ->atomic_open(). ++ * aufs_atomic_open() ++ * + au_aopen_or_create() ++ * + add_simple() ++ * + vfsub_atomic_open() ++ * + branch fs ->atomic_open() ++ * may call the actual 'open' for h_file ++ * + inc br_nfiles only if opened ++ * + au_aopen_no_open() or au_aopen_do_open() ++ * ++ * au_aopen_do_open() ++ * + finish_open() ++ * + au_do_aopen() ++ * + au_do_open() the body of all 'open' ++ * + au_do_open_nondir() ++ * set the passed h_file ++ * ++ * au_aopen_no_open() ++ * + finish_no_open() ++ */ ++ ++struct aopen_node { ++ struct hlist_bl_node hblist; ++ struct file *file, *h_file; ++}; ++ ++static int au_do_aopen(struct inode *inode, struct file *file) ++{ ++ struct hlist_bl_head *aopen; ++ struct hlist_bl_node *pos; ++ struct aopen_node *node; ++ struct au_do_open_args args = { ++ .aopen = 1, ++ .open = au_do_open_nondir ++ }; ++ ++ aopen = &au_sbi(inode->i_sb)->si_aopen; ++ hlist_bl_lock(aopen); ++ hlist_bl_for_each_entry(node, pos, aopen, hblist) ++ if (node->file == file) { ++ args.h_file = node->h_file; ++ break; ++ } ++ hlist_bl_unlock(aopen); ++ /* AuDebugOn(!args.h_file); */ ++ ++ return au_do_open(file, &args); ++} ++ ++static int au_aopen_do_open(struct file *file, struct dentry *dentry, ++ struct aopen_node *aopen_node) ++{ ++ int err; ++ struct hlist_bl_head *aopen; ++ ++ AuLabel(here); ++ aopen = &au_sbi(dentry->d_sb)->si_aopen; ++ au_hbl_add(&aopen_node->hblist, aopen); ++ err = finish_open(file, dentry, au_do_aopen); ++ au_hbl_del(&aopen_node->hblist, aopen); ++ /* AuDbgFile(file); */ ++ AuDbg("%pd%s%s\n", dentry, ++ (file->f_mode & FMODE_CREATED) ? " created" : "", ++ (file->f_mode & FMODE_OPENED) ? " opened" : ""); ++ ++ AuTraceErr(err); ++ return err; ++} ++ ++static int au_aopen_no_open(struct file *file, struct dentry *dentry) ++{ ++ int err; ++ ++ AuLabel(here); ++ dget(dentry); ++ err = finish_no_open(file, dentry); ++ ++ AuTraceErr(err); ++ return err; ++} ++ ++static int aufs_atomic_open(struct inode *dir, struct dentry *dentry, ++ struct file *file, unsigned int open_flag, ++ umode_t create_mode) ++{ ++ int err, did_open; ++ unsigned int lkup_flags; ++ aufs_bindex_t bindex; ++ struct super_block *sb; ++ struct dentry *parent, *d; ++ struct vfsub_aopen_args args = { ++ .open_flag = open_flag, ++ .create_mode = create_mode ++ }; ++ struct aopen_node aopen_node = { ++ .file = file ++ }; ++ ++ IMustLock(dir); ++ AuDbg("open_flag 0%o\n", open_flag); ++ AuDbgDentry(dentry); ++ ++ err = 0; ++ if (!au_di(dentry)) { ++ lkup_flags = LOOKUP_OPEN; ++ if (open_flag & O_CREAT) ++ lkup_flags |= LOOKUP_CREATE; ++ d = aufs_lookup(dir, dentry, lkup_flags); ++ if (IS_ERR(d)) { ++ err = PTR_ERR(d); ++ AuTraceErr(err); ++ goto out; ++ } else if (d) { ++ /* ++ * obsoleted dentry found. ++ * another error will be returned later. ++ */ ++ d_drop(d); ++ AuDbgDentry(d); ++ dput(d); ++ } ++ AuDbgDentry(dentry); ++ } ++ ++ if (d_is_positive(dentry) ++ || d_unhashed(dentry) ++ || d_unlinked(dentry) ++ || !(open_flag & O_CREAT)) { ++ err = au_aopen_no_open(file, dentry); ++ goto out; /* success */ ++ } ++ ++ err = aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH | AuLock_GEN); ++ if (unlikely(err)) ++ goto out; ++ ++ sb = dentry->d_sb; ++ parent = dentry->d_parent; /* dir is locked */ ++ di_write_lock_parent(parent); ++ err = au_lkup_dentry(dentry, /*btop*/0, AuLkup_ALLOW_NEG); ++ if (unlikely(err < 0)) ++ goto out_parent; ++ ++ AuDbgDentry(dentry); ++ if (d_is_positive(dentry)) { ++ err = au_aopen_no_open(file, dentry); ++ goto out_parent; /* success */ ++ } ++ ++ args.file = alloc_empty_file(file->f_flags, current_cred()); ++ err = PTR_ERR(args.file); ++ if (IS_ERR(args.file)) ++ goto out_parent; ++ ++ bindex = au_dbtop(dentry); ++ err = au_aopen_or_create(dir, dentry, &args); ++ AuTraceErr(err); ++ AuDbgFile(args.file); ++ file->f_mode = args.file->f_mode & ~FMODE_OPENED; ++ did_open = !!(args.file->f_mode & FMODE_OPENED); ++ if (!did_open) { ++ fput(args.file); ++ args.file = NULL; ++ } ++ di_write_unlock(parent); ++ di_write_unlock(dentry); ++ if (unlikely(err < 0)) { ++ if (args.file) ++ fput(args.file); ++ goto out_sb; ++ } ++ ++ if (!did_open) ++ err = au_aopen_no_open(file, dentry); ++ else { ++ aopen_node.h_file = args.file; ++ err = au_aopen_do_open(file, dentry, &aopen_node); ++ } ++ if (unlikely(err < 0)) { ++ if (args.file) ++ fput(args.file); ++ if (did_open) ++ au_lcnt_dec(&args.br->br_nfiles); ++ } ++ goto out_sb; /* success */ ++ ++out_parent: ++ di_write_unlock(parent); ++ di_write_unlock(dentry); ++out_sb: ++ si_read_unlock(sb); ++out: ++ AuTraceErr(err); ++ AuDbgFile(file); ++ return err; ++} ++ ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int au_wr_dir_cpup(struct dentry *dentry, struct dentry *parent, ++ const unsigned char add_entry, aufs_bindex_t bcpup, ++ aufs_bindex_t btop) ++{ ++ int err; ++ struct dentry *h_parent; ++ struct inode *h_dir; ++ ++ if (add_entry) ++ IMustLock(d_inode(parent)); ++ else ++ di_write_lock_parent(parent); ++ ++ err = 0; ++ if (!au_h_dptr(parent, bcpup)) { ++ if (btop > bcpup) ++ err = au_cpup_dirs(dentry, bcpup); ++ else if (btop < bcpup) ++ err = au_cpdown_dirs(dentry, bcpup); ++ else ++ BUG(); ++ } ++ if (!err && add_entry && !au_ftest_wrdir(add_entry, TMPFILE)) { ++ h_parent = au_h_dptr(parent, bcpup); ++ h_dir = d_inode(h_parent); ++ inode_lock_shared_nested(h_dir, AuLsc_I_PARENT); ++ err = au_lkup_neg(dentry, bcpup, /*wh*/0); ++ /* todo: no unlock here */ ++ inode_unlock_shared(h_dir); ++ ++ AuDbg("bcpup %d\n", bcpup); ++ if (!err) { ++ if (d_really_is_negative(dentry)) ++ au_set_h_dptr(dentry, btop, NULL); ++ au_update_dbrange(dentry, /*do_put_zero*/0); ++ } ++ } ++ ++ if (!add_entry) ++ di_write_unlock(parent); ++ if (!err) ++ err = bcpup; /* success */ ++ ++ AuTraceErr(err); ++ return err; ++} ++ ++/* ++ * decide the branch and the parent dir where we will create a new entry. ++ * returns new bindex or an error. ++ * copyup the parent dir if needed. ++ */ ++int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry, ++ struct au_wr_dir_args *args) ++{ ++ int err; ++ unsigned int flags; ++ aufs_bindex_t bcpup, btop, src_btop; ++ const unsigned char add_entry ++ = au_ftest_wrdir(args->flags, ADD_ENTRY) ++ | au_ftest_wrdir(args->flags, TMPFILE); ++ struct super_block *sb; ++ struct dentry *parent; ++ struct au_sbinfo *sbinfo; ++ ++ sb = dentry->d_sb; ++ sbinfo = au_sbi(sb); ++ parent = dget_parent(dentry); ++ btop = au_dbtop(dentry); ++ bcpup = btop; ++ if (args->force_btgt < 0) { ++ if (src_dentry) { ++ src_btop = au_dbtop(src_dentry); ++ if (src_btop < btop) ++ bcpup = src_btop; ++ } else if (add_entry) { ++ flags = 0; ++ if (au_ftest_wrdir(args->flags, ISDIR)) ++ au_fset_wbr(flags, DIR); ++ err = AuWbrCreate(sbinfo, dentry, flags); ++ bcpup = err; ++ } ++ ++ if (bcpup < 0 || au_test_ro(sb, bcpup, d_inode(dentry))) { ++ if (add_entry) ++ err = AuWbrCopyup(sbinfo, dentry); ++ else { ++ if (!IS_ROOT(dentry)) { ++ di_read_lock_parent(parent, !AuLock_IR); ++ err = AuWbrCopyup(sbinfo, dentry); ++ di_read_unlock(parent, !AuLock_IR); ++ } else ++ err = AuWbrCopyup(sbinfo, dentry); ++ } ++ bcpup = err; ++ if (unlikely(err < 0)) ++ goto out; ++ } ++ } else { ++ bcpup = args->force_btgt; ++ AuDebugOn(au_test_ro(sb, bcpup, d_inode(dentry))); ++ } ++ ++ AuDbg("btop %d, bcpup %d\n", btop, bcpup); ++ err = bcpup; ++ if (bcpup == btop) ++ goto out; /* success */ ++ ++ /* copyup the new parent into the branch we process */ ++ err = au_wr_dir_cpup(dentry, parent, add_entry, bcpup, btop); ++ if (err >= 0) { ++ if (d_really_is_negative(dentry)) { ++ au_set_h_dptr(dentry, btop, NULL); ++ au_set_dbtop(dentry, bcpup); ++ au_set_dbbot(dentry, bcpup); ++ } ++ AuDebugOn(add_entry ++ && !au_ftest_wrdir(args->flags, TMPFILE) ++ && !au_h_dptr(dentry, bcpup)); ++ } ++ ++out: ++ dput(parent); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++void au_pin_hdir_unlock(struct au_pin *p) ++{ ++ if (p->hdir) ++ au_hn_inode_unlock(p->hdir); ++} ++ ++int au_pin_hdir_lock(struct au_pin *p) ++{ ++ int err; ++ ++ err = 0; ++ if (!p->hdir) ++ goto out; ++ ++ /* even if an error happens later, keep this lock */ ++ au_hn_inode_lock_nested(p->hdir, p->lsc_hi); ++ ++ err = -EBUSY; ++ if (unlikely(p->hdir->hi_inode != d_inode(p->h_parent))) ++ goto out; ++ ++ err = 0; ++ if (p->h_dentry) ++ err = au_h_verify(p->h_dentry, p->udba, p->hdir->hi_inode, ++ p->h_parent, p->br); ++ ++out: ++ return err; ++} ++ ++int au_pin_hdir_relock(struct au_pin *p) ++{ ++ int err, i; ++ struct inode *h_i; ++ struct dentry *h_d[] = { ++ p->h_dentry, ++ p->h_parent ++ }; ++ ++ err = au_pin_hdir_lock(p); ++ if (unlikely(err)) ++ goto out; ++ ++ for (i = 0; !err && i < sizeof(h_d)/sizeof(*h_d); i++) { ++ if (!h_d[i]) ++ continue; ++ if (d_is_positive(h_d[i])) { ++ h_i = d_inode(h_d[i]); ++ err = !h_i->i_nlink; ++ } ++ } ++ ++out: ++ return err; ++} ++ ++static void au_pin_hdir_set_owner(struct au_pin *p, struct task_struct *task) ++{ ++ atomic_long_set(&p->hdir->hi_inode->i_rwsem.owner, (long)task); ++} ++ ++void au_pin_hdir_acquire_nest(struct au_pin *p) ++{ ++ if (p->hdir) { ++ rwsem_acquire_nest(&p->hdir->hi_inode->i_rwsem.dep_map, ++ p->lsc_hi, 0, NULL, _RET_IP_); ++ au_pin_hdir_set_owner(p, current); ++ } ++} ++ ++void au_pin_hdir_release(struct au_pin *p) ++{ ++ if (p->hdir) { ++ au_pin_hdir_set_owner(p, p->task); ++ rwsem_release(&p->hdir->hi_inode->i_rwsem.dep_map, 1, _RET_IP_); ++ } ++} ++ ++struct dentry *au_pinned_h_parent(struct au_pin *pin) ++{ ++ if (pin && pin->parent) ++ return au_h_dptr(pin->parent, pin->bindex); ++ return NULL; ++} ++ ++void au_unpin(struct au_pin *p) ++{ ++ if (p->hdir) ++ au_pin_hdir_unlock(p); ++ if (p->h_mnt && au_ftest_pin(p->flags, MNT_WRITE)) ++ vfsub_mnt_drop_write(p->h_mnt); ++ if (!p->hdir) ++ return; ++ ++ if (!au_ftest_pin(p->flags, DI_LOCKED)) ++ di_read_unlock(p->parent, AuLock_IR); ++ iput(p->hdir->hi_inode); ++ dput(p->parent); ++ p->parent = NULL; ++ p->hdir = NULL; ++ p->h_mnt = NULL; ++ /* do not clear p->task */ ++} ++ ++int au_do_pin(struct au_pin *p) ++{ ++ int err; ++ struct super_block *sb; ++ struct inode *h_dir; ++ ++ err = 0; ++ sb = p->dentry->d_sb; ++ p->br = au_sbr(sb, p->bindex); ++ if (IS_ROOT(p->dentry)) { ++ if (au_ftest_pin(p->flags, MNT_WRITE)) { ++ p->h_mnt = au_br_mnt(p->br); ++ err = vfsub_mnt_want_write(p->h_mnt); ++ if (unlikely(err)) { ++ au_fclr_pin(p->flags, MNT_WRITE); ++ goto out_err; ++ } ++ } ++ goto out; ++ } ++ ++ p->h_dentry = NULL; ++ if (p->bindex <= au_dbbot(p->dentry)) ++ p->h_dentry = au_h_dptr(p->dentry, p->bindex); ++ ++ p->parent = dget_parent(p->dentry); ++ if (!au_ftest_pin(p->flags, DI_LOCKED)) ++ di_read_lock(p->parent, AuLock_IR, p->lsc_di); ++ ++ h_dir = NULL; ++ p->h_parent = au_h_dptr(p->parent, p->bindex); ++ p->hdir = au_hi(d_inode(p->parent), p->bindex); ++ if (p->hdir) ++ h_dir = p->hdir->hi_inode; ++ ++ /* ++ * udba case, or ++ * if DI_LOCKED is not set, then p->parent may be different ++ * and h_parent can be NULL. ++ */ ++ if (unlikely(!p->hdir || !h_dir || !p->h_parent)) { ++ err = -EBUSY; ++ if (!au_ftest_pin(p->flags, DI_LOCKED)) ++ di_read_unlock(p->parent, AuLock_IR); ++ dput(p->parent); ++ p->parent = NULL; ++ goto out_err; ++ } ++ ++ if (au_ftest_pin(p->flags, MNT_WRITE)) { ++ p->h_mnt = au_br_mnt(p->br); ++ err = vfsub_mnt_want_write(p->h_mnt); ++ if (unlikely(err)) { ++ au_fclr_pin(p->flags, MNT_WRITE); ++ if (!au_ftest_pin(p->flags, DI_LOCKED)) ++ di_read_unlock(p->parent, AuLock_IR); ++ dput(p->parent); ++ p->parent = NULL; ++ goto out_err; ++ } ++ } ++ ++ au_igrab(h_dir); ++ err = au_pin_hdir_lock(p); ++ if (!err) ++ goto out; /* success */ ++ ++ au_unpin(p); ++ ++out_err: ++ pr_err("err %d\n", err); ++ err = au_busy_or_stale(); ++out: ++ return err; ++} ++ ++void au_pin_init(struct au_pin *p, struct dentry *dentry, ++ aufs_bindex_t bindex, int lsc_di, int lsc_hi, ++ unsigned int udba, unsigned char flags) ++{ ++ p->dentry = dentry; ++ p->udba = udba; ++ p->lsc_di = lsc_di; ++ p->lsc_hi = lsc_hi; ++ p->flags = flags; ++ p->bindex = bindex; ++ ++ p->parent = NULL; ++ p->hdir = NULL; ++ p->h_mnt = NULL; ++ ++ p->h_dentry = NULL; ++ p->h_parent = NULL; ++ p->br = NULL; ++ p->task = current; ++} ++ ++int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex, ++ unsigned int udba, unsigned char flags) ++{ ++ au_pin_init(pin, dentry, bindex, AuLsc_DI_PARENT, AuLsc_I_PARENT2, ++ udba, flags); ++ return au_do_pin(pin); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * ->setattr() and ->getattr() are called in various cases. ++ * chmod, stat: dentry is revalidated. ++ * fchmod, fstat: file and dentry are not revalidated, additionally they may be ++ * unhashed. ++ * for ->setattr(), ia->ia_file is passed from ftruncate only. ++ */ ++/* todo: consolidate with do_refresh() and simple_reval_dpath() */ ++int au_reval_for_attr(struct dentry *dentry, unsigned int sigen) ++{ ++ int err; ++ struct dentry *parent; ++ ++ err = 0; ++ if (au_digen_test(dentry, sigen)) { ++ parent = dget_parent(dentry); ++ di_read_lock_parent(parent, AuLock_IR); ++ err = au_refresh_dentry(dentry, parent); ++ di_read_unlock(parent, AuLock_IR); ++ dput(parent); ++ } ++ ++ AuTraceErr(err); ++ return err; ++} ++ ++int au_pin_and_icpup(struct dentry *dentry, struct iattr *ia, ++ struct au_icpup_args *a) ++{ ++ int err; ++ loff_t sz; ++ aufs_bindex_t btop, ibtop; ++ struct dentry *hi_wh, *parent; ++ struct inode *inode; ++ struct au_wr_dir_args wr_dir_args = { ++ .force_btgt = -1, ++ .flags = 0 ++ }; ++ ++ if (d_is_dir(dentry)) ++ au_fset_wrdir(wr_dir_args.flags, ISDIR); ++ /* plink or hi_wh() case */ ++ btop = au_dbtop(dentry); ++ inode = d_inode(dentry); ++ ibtop = au_ibtop(inode); ++ if (btop != ibtop && !au_test_ro(inode->i_sb, ibtop, inode)) ++ wr_dir_args.force_btgt = ibtop; ++ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args); ++ if (unlikely(err < 0)) ++ goto out; ++ a->btgt = err; ++ if (err != btop) ++ au_fset_icpup(a->flags, DID_CPUP); ++ ++ err = 0; ++ a->pin_flags = AuPin_MNT_WRITE; ++ parent = NULL; ++ if (!IS_ROOT(dentry)) { ++ au_fset_pin(a->pin_flags, DI_LOCKED); ++ parent = dget_parent(dentry); ++ di_write_lock_parent(parent); ++ } ++ ++ err = au_pin(&a->pin, dentry, a->btgt, a->udba, a->pin_flags); ++ if (unlikely(err)) ++ goto out_parent; ++ ++ sz = -1; ++ a->h_path.dentry = au_h_dptr(dentry, btop); ++ a->h_inode = d_inode(a->h_path.dentry); ++ if (ia && (ia->ia_valid & ATTR_SIZE)) { ++ inode_lock_shared_nested(a->h_inode, AuLsc_I_CHILD); ++ if (ia->ia_size < i_size_read(a->h_inode)) ++ sz = ia->ia_size; ++ inode_unlock_shared(a->h_inode); ++ } ++ ++ hi_wh = NULL; ++ if (au_ftest_icpup(a->flags, DID_CPUP) && d_unlinked(dentry)) { ++ hi_wh = au_hi_wh(inode, a->btgt); ++ if (!hi_wh) { ++ struct au_cp_generic cpg = { ++ .dentry = dentry, ++ .bdst = a->btgt, ++ .bsrc = -1, ++ .len = sz, ++ .pin = &a->pin ++ }; ++ err = au_sio_cpup_wh(&cpg, /*file*/NULL); ++ if (unlikely(err)) ++ goto out_unlock; ++ hi_wh = au_hi_wh(inode, a->btgt); ++ /* todo: revalidate hi_wh? */ ++ } ++ } ++ ++ if (parent) { ++ au_pin_set_parent_lflag(&a->pin, /*lflag*/0); ++ di_downgrade_lock(parent, AuLock_IR); ++ dput(parent); ++ parent = NULL; ++ } ++ if (!au_ftest_icpup(a->flags, DID_CPUP)) ++ goto out; /* success */ ++ ++ if (!d_unhashed(dentry)) { ++ struct au_cp_generic cpg = { ++ .dentry = dentry, ++ .bdst = a->btgt, ++ .bsrc = btop, ++ .len = sz, ++ .pin = &a->pin, ++ .flags = AuCpup_DTIME | AuCpup_HOPEN ++ }; ++ err = au_sio_cpup_simple(&cpg); ++ if (!err) ++ a->h_path.dentry = au_h_dptr(dentry, a->btgt); ++ } else if (!hi_wh) ++ a->h_path.dentry = au_h_dptr(dentry, a->btgt); ++ else ++ a->h_path.dentry = hi_wh; /* do not dget here */ ++ ++out_unlock: ++ a->h_inode = d_inode(a->h_path.dentry); ++ if (!err) ++ goto out; /* success */ ++ au_unpin(&a->pin); ++out_parent: ++ if (parent) { ++ di_write_unlock(parent); ++ dput(parent); ++ } ++out: ++ if (!err) ++ inode_lock_nested(a->h_inode, AuLsc_I_CHILD); ++ return err; ++} ++ ++static int aufs_setattr(struct dentry *dentry, struct iattr *ia) ++{ ++ int err; ++ struct inode *inode, *delegated; ++ struct super_block *sb; ++ struct file *file; ++ struct au_icpup_args *a; ++ ++ inode = d_inode(dentry); ++ IMustLock(inode); ++ ++ err = setattr_prepare(dentry, ia); ++ if (unlikely(err)) ++ goto out; ++ ++ err = -ENOMEM; ++ a = kzalloc(sizeof(*a), GFP_NOFS); ++ if (unlikely(!a)) ++ goto out; ++ ++ if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID)) ++ ia->ia_valid &= ~ATTR_MODE; ++ ++ file = NULL; ++ sb = dentry->d_sb; ++ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM); ++ if (unlikely(err)) ++ goto out_kfree; ++ ++ if (ia->ia_valid & ATTR_FILE) { ++ /* currently ftruncate(2) only */ ++ AuDebugOn(!d_is_reg(dentry)); ++ file = ia->ia_file; ++ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1, ++ /*fi_lsc*/0); ++ if (unlikely(err)) ++ goto out_si; ++ ia->ia_file = au_hf_top(file); ++ a->udba = AuOpt_UDBA_NONE; ++ } else { ++ /* fchmod() doesn't pass ia_file */ ++ a->udba = au_opt_udba(sb); ++ di_write_lock_child(dentry); ++ /* no d_unlinked(), to set UDBA_NONE for root */ ++ if (d_unhashed(dentry)) ++ a->udba = AuOpt_UDBA_NONE; ++ if (a->udba != AuOpt_UDBA_NONE) { ++ AuDebugOn(IS_ROOT(dentry)); ++ err = au_reval_for_attr(dentry, au_sigen(sb)); ++ if (unlikely(err)) ++ goto out_dentry; ++ } ++ } ++ ++ err = au_pin_and_icpup(dentry, ia, a); ++ if (unlikely(err < 0)) ++ goto out_dentry; ++ if (au_ftest_icpup(a->flags, DID_CPUP)) { ++ ia->ia_file = NULL; ++ ia->ia_valid &= ~ATTR_FILE; ++ } ++ ++ a->h_path.mnt = au_sbr_mnt(sb, a->btgt); ++ if ((ia->ia_valid & (ATTR_MODE | ATTR_CTIME)) ++ == (ATTR_MODE | ATTR_CTIME)) { ++ err = security_path_chmod(&a->h_path, ia->ia_mode); ++ if (unlikely(err)) ++ goto out_unlock; ++ } else if ((ia->ia_valid & (ATTR_UID | ATTR_GID)) ++ && (ia->ia_valid & ATTR_CTIME)) { ++ err = security_path_chown(&a->h_path, ia->ia_uid, ia->ia_gid); ++ if (unlikely(err)) ++ goto out_unlock; ++ } ++ ++ if (ia->ia_valid & ATTR_SIZE) { ++ struct file *f; ++ ++ if (ia->ia_size < i_size_read(inode)) ++ /* unmap only */ ++ truncate_setsize(inode, ia->ia_size); ++ ++ f = NULL; ++ if (ia->ia_valid & ATTR_FILE) ++ f = ia->ia_file; ++ inode_unlock(a->h_inode); ++ err = vfsub_trunc(&a->h_path, ia->ia_size, ia->ia_valid, f); ++ inode_lock_nested(a->h_inode, AuLsc_I_CHILD); ++ } else { ++ delegated = NULL; ++ while (1) { ++ err = vfsub_notify_change(&a->h_path, ia, &delegated); ++ if (delegated) { ++ err = break_deleg_wait(&delegated); ++ if (!err) ++ continue; ++ } ++ break; ++ } ++ } ++ /* ++ * regardless aufs 'acl' option setting. ++ * why don't all acl-aware fs call this func from their ->setattr()? ++ */ ++ if (!err && (ia->ia_valid & ATTR_MODE)) ++ err = vfsub_acl_chmod(a->h_inode, ia->ia_mode); ++ if (!err) ++ au_cpup_attr_changeable(inode); ++ ++out_unlock: ++ inode_unlock(a->h_inode); ++ au_unpin(&a->pin); ++ if (unlikely(err)) ++ au_update_dbtop(dentry); ++out_dentry: ++ di_write_unlock(dentry); ++ if (file) { ++ fi_write_unlock(file); ++ ia->ia_file = file; ++ ia->ia_valid |= ATTR_FILE; ++ } ++out_si: ++ si_read_unlock(sb); ++out_kfree: ++ au_kfree_rcu(a); ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++#if IS_ENABLED(CONFIG_AUFS_XATTR) || IS_ENABLED(CONFIG_FS_POSIX_ACL) ++static int au_h_path_to_set_attr(struct dentry *dentry, ++ struct au_icpup_args *a, struct path *h_path) ++{ ++ int err; ++ struct super_block *sb; ++ ++ sb = dentry->d_sb; ++ a->udba = au_opt_udba(sb); ++ /* no d_unlinked(), to set UDBA_NONE for root */ ++ if (d_unhashed(dentry)) ++ a->udba = AuOpt_UDBA_NONE; ++ if (a->udba != AuOpt_UDBA_NONE) { ++ AuDebugOn(IS_ROOT(dentry)); ++ err = au_reval_for_attr(dentry, au_sigen(sb)); ++ if (unlikely(err)) ++ goto out; ++ } ++ err = au_pin_and_icpup(dentry, /*ia*/NULL, a); ++ if (unlikely(err < 0)) ++ goto out; ++ ++ h_path->dentry = a->h_path.dentry; ++ h_path->mnt = au_sbr_mnt(sb, a->btgt); ++ ++out: ++ return err; ++} ++ ++ssize_t au_sxattr(struct dentry *dentry, struct inode *inode, ++ struct au_sxattr *arg) ++{ ++ int err; ++ struct path h_path; ++ struct super_block *sb; ++ struct au_icpup_args *a; ++ struct inode *h_inode; ++ ++ IMustLock(inode); ++ ++ err = -ENOMEM; ++ a = kzalloc(sizeof(*a), GFP_NOFS); ++ if (unlikely(!a)) ++ goto out; ++ ++ sb = dentry->d_sb; ++ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM); ++ if (unlikely(err)) ++ goto out_kfree; ++ ++ h_path.dentry = NULL; /* silence gcc */ ++ di_write_lock_child(dentry); ++ err = au_h_path_to_set_attr(dentry, a, &h_path); ++ if (unlikely(err)) ++ goto out_di; ++ ++ inode_unlock(a->h_inode); ++ switch (arg->type) { ++ case AU_XATTR_SET: ++ AuDebugOn(d_is_negative(h_path.dentry)); ++ err = vfsub_setxattr(h_path.dentry, ++ arg->u.set.name, arg->u.set.value, ++ arg->u.set.size, arg->u.set.flags); ++ break; ++ case AU_ACL_SET: ++ err = -EOPNOTSUPP; ++ h_inode = d_inode(h_path.dentry); ++ if (h_inode->i_op->set_acl) ++ /* this will call posix_acl_update_mode */ ++ err = h_inode->i_op->set_acl(h_inode, ++ arg->u.acl_set.acl, ++ arg->u.acl_set.type); ++ break; ++ } ++ if (!err) ++ au_cpup_attr_timesizes(inode); ++ ++ au_unpin(&a->pin); ++ if (unlikely(err)) ++ au_update_dbtop(dentry); ++ ++out_di: ++ di_write_unlock(dentry); ++ si_read_unlock(sb); ++out_kfree: ++ au_kfree_rcu(a); ++out: ++ AuTraceErr(err); ++ return err; ++} ++#endif ++ ++static void au_refresh_iattr(struct inode *inode, struct kstat *st, ++ unsigned int nlink) ++{ ++ unsigned int n; ++ ++ inode->i_mode = st->mode; ++ /* don't i_[ug]id_write() here */ ++ inode->i_uid = st->uid; ++ inode->i_gid = st->gid; ++ inode->i_atime = st->atime; ++ inode->i_mtime = st->mtime; ++ inode->i_ctime = st->ctime; ++ ++ au_cpup_attr_nlink(inode, /*force*/0); ++ if (S_ISDIR(inode->i_mode)) { ++ n = inode->i_nlink; ++ n -= nlink; ++ n += st->nlink; ++ smp_mb(); /* for i_nlink */ ++ /* 0 can happen */ ++ set_nlink(inode, n); ++ } ++ ++ spin_lock(&inode->i_lock); ++ inode->i_blocks = st->blocks; ++ i_size_write(inode, st->size); ++ spin_unlock(&inode->i_lock); ++} ++ ++/* ++ * common routine for aufs_getattr() and au_getxattr(). ++ * returns zero or negative (an error). ++ * @dentry will be read-locked in success. ++ */ ++int au_h_path_getattr(struct dentry *dentry, int force, struct path *h_path, ++ int locked) ++{ ++ int err; ++ unsigned int mnt_flags, sigen; ++ unsigned char udba_none; ++ aufs_bindex_t bindex; ++ struct super_block *sb, *h_sb; ++ struct inode *inode; ++ ++ h_path->mnt = NULL; ++ h_path->dentry = NULL; ++ ++ err = 0; ++ sb = dentry->d_sb; ++ mnt_flags = au_mntflags(sb); ++ udba_none = !!au_opt_test(mnt_flags, UDBA_NONE); ++ ++ if (unlikely(locked)) ++ goto body; /* skip locking dinfo */ ++ ++ /* support fstat(2) */ ++ if (!d_unlinked(dentry) && !udba_none) { ++ sigen = au_sigen(sb); ++ err = au_digen_test(dentry, sigen); ++ if (!err) { ++ di_read_lock_child(dentry, AuLock_IR); ++ err = au_dbrange_test(dentry); ++ if (unlikely(err)) { ++ di_read_unlock(dentry, AuLock_IR); ++ goto out; ++ } ++ } else { ++ AuDebugOn(IS_ROOT(dentry)); ++ di_write_lock_child(dentry); ++ err = au_dbrange_test(dentry); ++ if (!err) ++ err = au_reval_for_attr(dentry, sigen); ++ if (!err) ++ di_downgrade_lock(dentry, AuLock_IR); ++ else { ++ di_write_unlock(dentry); ++ goto out; ++ } ++ } ++ } else ++ di_read_lock_child(dentry, AuLock_IR); ++ ++body: ++ inode = d_inode(dentry); ++ bindex = au_ibtop(inode); ++ h_path->mnt = au_sbr_mnt(sb, bindex); ++ h_sb = h_path->mnt->mnt_sb; ++ if (!force ++ && !au_test_fs_bad_iattr(h_sb) ++ && udba_none) ++ goto out; /* success */ ++ ++ if (au_dbtop(dentry) == bindex) ++ h_path->dentry = au_h_dptr(dentry, bindex); ++ else if (au_opt_test(mnt_flags, PLINK) && au_plink_test(inode)) { ++ h_path->dentry = au_plink_lkup(inode, bindex); ++ if (IS_ERR(h_path->dentry)) ++ /* pretending success */ ++ h_path->dentry = NULL; ++ else ++ dput(h_path->dentry); ++ } ++ ++out: ++ return err; ++} ++ ++static int aufs_getattr(const struct path *path, struct kstat *st, ++ u32 request, unsigned int query) ++{ ++ int err; ++ unsigned char positive; ++ struct path h_path; ++ struct dentry *dentry; ++ struct inode *inode; ++ struct super_block *sb; ++ ++ dentry = path->dentry; ++ inode = d_inode(dentry); ++ sb = dentry->d_sb; ++ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM); ++ if (unlikely(err)) ++ goto out; ++ err = au_h_path_getattr(dentry, /*force*/0, &h_path, /*locked*/0); ++ if (unlikely(err)) ++ goto out_si; ++ if (unlikely(!h_path.dentry)) ++ /* illegally overlapped or something */ ++ goto out_fill; /* pretending success */ ++ ++ positive = d_is_positive(h_path.dentry); ++ if (positive) ++ /* no vfsub version */ ++ err = vfs_getattr(&h_path, st, request, query); ++ if (!err) { ++ if (positive) ++ au_refresh_iattr(inode, st, ++ d_inode(h_path.dentry)->i_nlink); ++ goto out_fill; /* success */ ++ } ++ AuTraceErr(err); ++ goto out_di; ++ ++out_fill: ++ generic_fillattr(inode, st); ++out_di: ++ di_read_unlock(dentry, AuLock_IR); ++out_si: ++ si_read_unlock(sb); ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static const char *aufs_get_link(struct dentry *dentry, struct inode *inode, ++ struct delayed_call *done) ++{ ++ const char *ret; ++ struct dentry *h_dentry; ++ struct inode *h_inode; ++ int err; ++ aufs_bindex_t bindex; ++ ++ ret = NULL; /* suppress a warning */ ++ err = -ECHILD; ++ if (!dentry) ++ goto out; ++ ++ err = aufs_read_lock(dentry, AuLock_IR | AuLock_GEN); ++ if (unlikely(err)) ++ goto out; ++ ++ err = au_d_hashed_positive(dentry); ++ if (unlikely(err)) ++ goto out_unlock; ++ ++ err = -EINVAL; ++ inode = d_inode(dentry); ++ bindex = au_ibtop(inode); ++ h_inode = au_h_iptr(inode, bindex); ++ if (unlikely(!h_inode->i_op->get_link)) ++ goto out_unlock; ++ ++ err = -EBUSY; ++ h_dentry = NULL; ++ if (au_dbtop(dentry) <= bindex) { ++ h_dentry = au_h_dptr(dentry, bindex); ++ if (h_dentry) ++ dget(h_dentry); ++ } ++ if (!h_dentry) { ++ h_dentry = d_find_any_alias(h_inode); ++ if (IS_ERR(h_dentry)) { ++ err = PTR_ERR(h_dentry); ++ goto out_unlock; ++ } ++ } ++ if (unlikely(!h_dentry)) ++ goto out_unlock; ++ ++ err = 0; ++ AuDbg("%ps\n", h_inode->i_op->get_link); ++ AuDbgDentry(h_dentry); ++ ret = vfs_get_link(h_dentry, done); ++ dput(h_dentry); ++ if (IS_ERR(ret)) ++ err = PTR_ERR(ret); ++ ++out_unlock: ++ aufs_read_unlock(dentry, AuLock_IR); ++out: ++ if (unlikely(err)) ++ ret = ERR_PTR(err); ++ AuTraceErrPtr(ret); ++ return ret; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int au_is_special(struct inode *inode) ++{ ++ return (inode->i_mode & (S_IFBLK | S_IFCHR | S_IFIFO | S_IFSOCK)); ++} ++ ++static int aufs_update_time(struct inode *inode, struct timespec64 *ts, ++ int flags) ++{ ++ int err; ++ aufs_bindex_t bindex; ++ struct super_block *sb; ++ struct inode *h_inode; ++ struct vfsmount *h_mnt; ++ ++ sb = inode->i_sb; ++ WARN_ONCE((flags & S_ATIME) && !IS_NOATIME(inode), ++ "unexpected s_flags 0x%lx", sb->s_flags); ++ ++ /* mmap_sem might be acquired already, cf. aufs_mmap() */ ++ lockdep_off(); ++ si_read_lock(sb, AuLock_FLUSH); ++ ii_write_lock_child(inode); ++ ++ err = 0; ++ bindex = au_ibtop(inode); ++ h_inode = au_h_iptr(inode, bindex); ++ if (!au_test_ro(sb, bindex, inode)) { ++ h_mnt = au_sbr_mnt(sb, bindex); ++ err = vfsub_mnt_want_write(h_mnt); ++ if (!err) { ++ err = vfsub_update_time(h_inode, ts, flags); ++ vfsub_mnt_drop_write(h_mnt); ++ } ++ } else if (au_is_special(h_inode)) { ++ /* ++ * Never copy-up here. ++ * These special files may already be opened and used for ++ * communicating. If we copied it up, then the communication ++ * would be corrupted. ++ */ ++ AuWarn1("timestamps for i%lu are ignored " ++ "since it is on readonly branch (hi%lu).\n", ++ inode->i_ino, h_inode->i_ino); ++ } else if (flags & ~S_ATIME) { ++ err = -EIO; ++ AuIOErr1("unexpected flags 0x%x\n", flags); ++ AuDebugOn(1); ++ } ++ ++ if (!err) ++ au_cpup_attr_timesizes(inode); ++ ii_write_unlock(inode); ++ si_read_unlock(sb); ++ lockdep_on(); ++ ++ if (!err && (flags & S_VERSION)) ++ inode_inc_iversion(inode); ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* no getattr version will be set by module.c:aufs_init() */ ++struct inode_operations aufs_iop_nogetattr[AuIop_Last], ++ aufs_iop[] = { ++ [AuIop_SYMLINK] = { ++ .permission = aufs_permission, ++#ifdef CONFIG_FS_POSIX_ACL ++ .get_acl = aufs_get_acl, ++ .set_acl = aufs_set_acl, /* unsupport for symlink? */ ++#endif ++ ++ .setattr = aufs_setattr, ++ .getattr = aufs_getattr, ++ ++#ifdef CONFIG_AUFS_XATTR ++ .listxattr = aufs_listxattr, ++#endif ++ ++ .get_link = aufs_get_link, ++ ++ /* .update_time = aufs_update_time */ ++ }, ++ [AuIop_DIR] = { ++ .create = aufs_create, ++ .lookup = aufs_lookup, ++ .link = aufs_link, ++ .unlink = aufs_unlink, ++ .symlink = aufs_symlink, ++ .mkdir = aufs_mkdir, ++ .rmdir = aufs_rmdir, ++ .mknod = aufs_mknod, ++ .rename = aufs_rename, ++ ++ .permission = aufs_permission, ++#ifdef CONFIG_FS_POSIX_ACL ++ .get_acl = aufs_get_acl, ++ .set_acl = aufs_set_acl, ++#endif ++ ++ .setattr = aufs_setattr, ++ .getattr = aufs_getattr, ++ ++#ifdef CONFIG_AUFS_XATTR ++ .listxattr = aufs_listxattr, ++#endif ++ ++ .update_time = aufs_update_time, ++ .atomic_open = aufs_atomic_open, ++ .tmpfile = aufs_tmpfile ++ }, ++ [AuIop_OTHER] = { ++ .permission = aufs_permission, ++#ifdef CONFIG_FS_POSIX_ACL ++ .get_acl = aufs_get_acl, ++ .set_acl = aufs_set_acl, ++#endif ++ ++ .setattr = aufs_setattr, ++ .getattr = aufs_getattr, ++ ++#ifdef CONFIG_AUFS_XATTR ++ .listxattr = aufs_listxattr, ++#endif ++ ++ .update_time = aufs_update_time ++ } ++}; +diff -Nurp linux-5.4/fs/aufs/i_op_del.c linux-5.4-aufs/fs/aufs/i_op_del.c +--- linux-5.4/fs/aufs/i_op_del.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/i_op_del.c 2019-11-28 01:25:59.066925618 +0200 +@@ -0,0 +1,500 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * inode operations (del entry) ++ */ ++ ++#include ++#include "aufs.h" ++ ++/* ++ * decide if a new whiteout for @dentry is necessary or not. ++ * when it is necessary, prepare the parent dir for the upper branch whose ++ * branch index is @bcpup for creation. the actual creation of the whiteout will ++ * be done by caller. ++ * return value: ++ * 0: wh is unnecessary ++ * plus: wh is necessary ++ * minus: error ++ */ ++int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup) ++{ ++ int need_wh, err; ++ aufs_bindex_t btop; ++ struct super_block *sb; ++ ++ sb = dentry->d_sb; ++ btop = au_dbtop(dentry); ++ if (*bcpup < 0) { ++ *bcpup = btop; ++ if (au_test_ro(sb, btop, d_inode(dentry))) { ++ err = AuWbrCopyup(au_sbi(sb), dentry); ++ *bcpup = err; ++ if (unlikely(err < 0)) ++ goto out; ++ } ++ } else ++ AuDebugOn(btop < *bcpup ++ || au_test_ro(sb, *bcpup, d_inode(dentry))); ++ AuDbg("bcpup %d, btop %d\n", *bcpup, btop); ++ ++ if (*bcpup != btop) { ++ err = au_cpup_dirs(dentry, *bcpup); ++ if (unlikely(err)) ++ goto out; ++ need_wh = 1; ++ } else { ++ struct au_dinfo *dinfo, *tmp; ++ ++ need_wh = -ENOMEM; ++ dinfo = au_di(dentry); ++ tmp = au_di_alloc(sb, AuLsc_DI_TMP); ++ if (tmp) { ++ au_di_cp(tmp, dinfo); ++ au_di_swap(tmp, dinfo); ++ /* returns the number of positive dentries */ ++ need_wh = au_lkup_dentry(dentry, btop + 1, ++ /* AuLkup_IGNORE_PERM */ 0); ++ au_di_swap(tmp, dinfo); ++ au_rw_write_unlock(&tmp->di_rwsem); ++ au_di_free(tmp); ++ } ++ } ++ AuDbg("need_wh %d\n", need_wh); ++ err = need_wh; ++ ++out: ++ return err; ++} ++ ++/* ++ * simple tests for the del-entry operations. ++ * following the checks in vfs, plus the parent-child relationship. ++ */ ++int au_may_del(struct dentry *dentry, aufs_bindex_t bindex, ++ struct dentry *h_parent, int isdir) ++{ ++ int err; ++ umode_t h_mode; ++ struct dentry *h_dentry, *h_latest; ++ struct inode *h_inode; ++ ++ h_dentry = au_h_dptr(dentry, bindex); ++ if (d_really_is_positive(dentry)) { ++ err = -ENOENT; ++ if (unlikely(d_is_negative(h_dentry))) ++ goto out; ++ h_inode = d_inode(h_dentry); ++ if (unlikely(!h_inode->i_nlink)) ++ goto out; ++ ++ h_mode = h_inode->i_mode; ++ if (!isdir) { ++ err = -EISDIR; ++ if (unlikely(S_ISDIR(h_mode))) ++ goto out; ++ } else if (unlikely(!S_ISDIR(h_mode))) { ++ err = -ENOTDIR; ++ goto out; ++ } ++ } else { ++ /* rename(2) case */ ++ err = -EIO; ++ if (unlikely(d_is_positive(h_dentry))) ++ goto out; ++ } ++ ++ err = -ENOENT; ++ /* expected parent dir is locked */ ++ if (unlikely(h_parent != h_dentry->d_parent)) ++ goto out; ++ err = 0; ++ ++ /* ++ * rmdir a dir may break the consistency on some filesystem. ++ * let's try heavy test. ++ */ ++ err = -EACCES; ++ if (unlikely(!au_opt_test(au_mntflags(dentry->d_sb), DIRPERM1) ++ && au_test_h_perm(d_inode(h_parent), ++ MAY_EXEC | MAY_WRITE))) ++ goto out; ++ ++ h_latest = au_sio_lkup_one(&dentry->d_name, h_parent); ++ err = -EIO; ++ if (IS_ERR(h_latest)) ++ goto out; ++ if (h_latest == h_dentry) ++ err = 0; ++ dput(h_latest); ++ ++out: ++ return err; ++} ++ ++/* ++ * decide the branch where we operate for @dentry. the branch index will be set ++ * @rbcpup. after deciding it, 'pin' it and store the timestamps of the parent ++ * dir for reverting. ++ * when a new whiteout is necessary, create it. ++ */ ++static struct dentry* ++lock_hdir_create_wh(struct dentry *dentry, int isdir, aufs_bindex_t *rbcpup, ++ struct au_dtime *dt, struct au_pin *pin) ++{ ++ struct dentry *wh_dentry; ++ struct super_block *sb; ++ struct path h_path; ++ int err, need_wh; ++ unsigned int udba; ++ aufs_bindex_t bcpup; ++ ++ need_wh = au_wr_dir_need_wh(dentry, isdir, rbcpup); ++ wh_dentry = ERR_PTR(need_wh); ++ if (unlikely(need_wh < 0)) ++ goto out; ++ ++ sb = dentry->d_sb; ++ udba = au_opt_udba(sb); ++ bcpup = *rbcpup; ++ err = au_pin(pin, dentry, bcpup, udba, ++ AuPin_DI_LOCKED | AuPin_MNT_WRITE); ++ wh_dentry = ERR_PTR(err); ++ if (unlikely(err)) ++ goto out; ++ ++ h_path.dentry = au_pinned_h_parent(pin); ++ if (udba != AuOpt_UDBA_NONE ++ && au_dbtop(dentry) == bcpup) { ++ err = au_may_del(dentry, bcpup, h_path.dentry, isdir); ++ wh_dentry = ERR_PTR(err); ++ if (unlikely(err)) ++ goto out_unpin; ++ } ++ ++ h_path.mnt = au_sbr_mnt(sb, bcpup); ++ au_dtime_store(dt, au_pinned_parent(pin), &h_path); ++ wh_dentry = NULL; ++ if (!need_wh) ++ goto out; /* success, no need to create whiteout */ ++ ++ wh_dentry = au_wh_create(dentry, bcpup, h_path.dentry); ++ if (IS_ERR(wh_dentry)) ++ goto out_unpin; ++ ++ /* returns with the parent is locked and wh_dentry is dget-ed */ ++ goto out; /* success */ ++ ++out_unpin: ++ au_unpin(pin); ++out: ++ return wh_dentry; ++} ++ ++/* ++ * when removing a dir, rename it to a unique temporary whiteout-ed name first ++ * in order to be revertible and save time for removing many child whiteouts ++ * under the dir. ++ * returns 1 when there are too many child whiteout and caller should remove ++ * them asynchronously. returns 0 when the number of children is enough small to ++ * remove now or the branch fs is a remote fs. ++ * otherwise return an error. ++ */ ++static int renwh_and_rmdir(struct dentry *dentry, aufs_bindex_t bindex, ++ struct au_nhash *whlist, struct inode *dir) ++{ ++ int rmdir_later, err, dirwh; ++ struct dentry *h_dentry; ++ struct super_block *sb; ++ struct inode *inode; ++ ++ sb = dentry->d_sb; ++ SiMustAnyLock(sb); ++ h_dentry = au_h_dptr(dentry, bindex); ++ err = au_whtmp_ren(h_dentry, au_sbr(sb, bindex)); ++ if (unlikely(err)) ++ goto out; ++ ++ /* stop monitoring */ ++ inode = d_inode(dentry); ++ au_hn_free(au_hi(inode, bindex)); ++ ++ if (!au_test_fs_remote(h_dentry->d_sb)) { ++ dirwh = au_sbi(sb)->si_dirwh; ++ rmdir_later = (dirwh <= 1); ++ if (!rmdir_later) ++ rmdir_later = au_nhash_test_longer_wh(whlist, bindex, ++ dirwh); ++ if (rmdir_later) ++ return rmdir_later; ++ } ++ ++ err = au_whtmp_rmdir(dir, bindex, h_dentry, whlist); ++ if (unlikely(err)) { ++ AuIOErr("rmdir %pd, b%d failed, %d. ignored\n", ++ h_dentry, bindex, err); ++ err = 0; ++ } ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++/* ++ * final procedure for deleting a entry. ++ * maintain dentry and iattr. ++ */ ++static void epilog(struct inode *dir, struct dentry *dentry, ++ aufs_bindex_t bindex) ++{ ++ struct inode *inode; ++ ++ inode = d_inode(dentry); ++ d_drop(dentry); ++ inode->i_ctime = dir->i_ctime; ++ ++ au_dir_ts(dir, bindex); ++ inode_inc_iversion(dir); ++} ++ ++/* ++ * when an error happened, remove the created whiteout and revert everything. ++ */ ++static int do_revert(int err, struct inode *dir, aufs_bindex_t bindex, ++ aufs_bindex_t bwh, struct dentry *wh_dentry, ++ struct dentry *dentry, struct au_dtime *dt) ++{ ++ int rerr; ++ struct path h_path = { ++ .dentry = wh_dentry, ++ .mnt = au_sbr_mnt(dir->i_sb, bindex) ++ }; ++ ++ rerr = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path, dentry); ++ if (!rerr) { ++ au_set_dbwh(dentry, bwh); ++ au_dtime_revert(dt); ++ return 0; ++ } ++ ++ AuIOErr("%pd reverting whiteout failed(%d, %d)\n", dentry, err, rerr); ++ return -EIO; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++int aufs_unlink(struct inode *dir, struct dentry *dentry) ++{ ++ int err; ++ aufs_bindex_t bwh, bindex, btop; ++ struct inode *inode, *h_dir, *delegated; ++ struct dentry *parent, *wh_dentry; ++ /* to reduce stack size */ ++ struct { ++ struct au_dtime dt; ++ struct au_pin pin; ++ struct path h_path; ++ } *a; ++ ++ IMustLock(dir); ++ ++ err = -ENOMEM; ++ a = kmalloc(sizeof(*a), GFP_NOFS); ++ if (unlikely(!a)) ++ goto out; ++ ++ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN); ++ if (unlikely(err)) ++ goto out_free; ++ err = au_d_hashed_positive(dentry); ++ if (unlikely(err)) ++ goto out_unlock; ++ inode = d_inode(dentry); ++ IMustLock(inode); ++ err = -EISDIR; ++ if (unlikely(d_is_dir(dentry))) ++ goto out_unlock; /* possible? */ ++ ++ btop = au_dbtop(dentry); ++ bwh = au_dbwh(dentry); ++ bindex = -1; ++ parent = dentry->d_parent; /* dir inode is locked */ ++ di_write_lock_parent(parent); ++ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/0, &bindex, &a->dt, ++ &a->pin); ++ err = PTR_ERR(wh_dentry); ++ if (IS_ERR(wh_dentry)) ++ goto out_parent; ++ ++ a->h_path.mnt = au_sbr_mnt(dentry->d_sb, btop); ++ a->h_path.dentry = au_h_dptr(dentry, btop); ++ dget(a->h_path.dentry); ++ if (bindex == btop) { ++ h_dir = au_pinned_h_dir(&a->pin); ++ delegated = NULL; ++ err = vfsub_unlink(h_dir, &a->h_path, &delegated, /*force*/0); ++ if (unlikely(err == -EWOULDBLOCK)) { ++ pr_warn("cannot retry for NFSv4 delegation" ++ " for an internal unlink\n"); ++ iput(delegated); ++ } ++ } else { ++ /* dir inode is locked */ ++ h_dir = d_inode(wh_dentry->d_parent); ++ IMustLock(h_dir); ++ err = 0; ++ } ++ ++ if (!err) { ++ vfsub_drop_nlink(inode); ++ epilog(dir, dentry, bindex); ++ ++ /* update target timestamps */ ++ if (bindex == btop) { ++ vfsub_update_h_iattr(&a->h_path, /*did*/NULL); ++ /*ignore*/ ++ inode->i_ctime = d_inode(a->h_path.dentry)->i_ctime; ++ } else ++ /* todo: this timestamp may be reverted later */ ++ inode->i_ctime = h_dir->i_ctime; ++ goto out_unpin; /* success */ ++ } ++ ++ /* revert */ ++ if (wh_dentry) { ++ int rerr; ++ ++ rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry, ++ &a->dt); ++ if (rerr) ++ err = rerr; ++ } ++ ++out_unpin: ++ au_unpin(&a->pin); ++ dput(wh_dentry); ++ dput(a->h_path.dentry); ++out_parent: ++ di_write_unlock(parent); ++out_unlock: ++ aufs_read_unlock(dentry, AuLock_DW); ++out_free: ++ au_kfree_rcu(a); ++out: ++ return err; ++} ++ ++int aufs_rmdir(struct inode *dir, struct dentry *dentry) ++{ ++ int err, rmdir_later; ++ aufs_bindex_t bwh, bindex, btop; ++ struct inode *inode; ++ struct dentry *parent, *wh_dentry, *h_dentry; ++ struct au_whtmp_rmdir *args; ++ /* to reduce stack size */ ++ struct { ++ struct au_dtime dt; ++ struct au_pin pin; ++ } *a; ++ ++ IMustLock(dir); ++ ++ err = -ENOMEM; ++ a = kmalloc(sizeof(*a), GFP_NOFS); ++ if (unlikely(!a)) ++ goto out; ++ ++ err = aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH | AuLock_GEN); ++ if (unlikely(err)) ++ goto out_free; ++ err = au_alive_dir(dentry); ++ if (unlikely(err)) ++ goto out_unlock; ++ inode = d_inode(dentry); ++ IMustLock(inode); ++ err = -ENOTDIR; ++ if (unlikely(!d_is_dir(dentry))) ++ goto out_unlock; /* possible? */ ++ ++ err = -ENOMEM; ++ args = au_whtmp_rmdir_alloc(dir->i_sb, GFP_NOFS); ++ if (unlikely(!args)) ++ goto out_unlock; ++ ++ parent = dentry->d_parent; /* dir inode is locked */ ++ di_write_lock_parent(parent); ++ err = au_test_empty(dentry, &args->whlist); ++ if (unlikely(err)) ++ goto out_parent; ++ ++ btop = au_dbtop(dentry); ++ bwh = au_dbwh(dentry); ++ bindex = -1; ++ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/1, &bindex, &a->dt, ++ &a->pin); ++ err = PTR_ERR(wh_dentry); ++ if (IS_ERR(wh_dentry)) ++ goto out_parent; ++ ++ h_dentry = au_h_dptr(dentry, btop); ++ dget(h_dentry); ++ rmdir_later = 0; ++ if (bindex == btop) { ++ err = renwh_and_rmdir(dentry, btop, &args->whlist, dir); ++ if (err > 0) { ++ rmdir_later = err; ++ err = 0; ++ } ++ } else { ++ /* stop monitoring */ ++ au_hn_free(au_hi(inode, btop)); ++ ++ /* dir inode is locked */ ++ IMustLock(d_inode(wh_dentry->d_parent)); ++ err = 0; ++ } ++ ++ if (!err) { ++ vfsub_dead_dir(inode); ++ au_set_dbdiropq(dentry, -1); ++ epilog(dir, dentry, bindex); ++ ++ if (rmdir_later) { ++ au_whtmp_kick_rmdir(dir, btop, h_dentry, args); ++ args = NULL; ++ } ++ ++ goto out_unpin; /* success */ ++ } ++ ++ /* revert */ ++ AuLabel(revert); ++ if (wh_dentry) { ++ int rerr; ++ ++ rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry, ++ &a->dt); ++ if (rerr) ++ err = rerr; ++ } ++ ++out_unpin: ++ au_unpin(&a->pin); ++ dput(wh_dentry); ++ dput(h_dentry); ++out_parent: ++ di_write_unlock(parent); ++ if (args) ++ au_whtmp_rmdir_free(args); ++out_unlock: ++ aufs_read_unlock(dentry, AuLock_DW); ++out_free: ++ au_kfree_rcu(a); ++out: ++ AuTraceErr(err); ++ return err; ++} +diff -Nurp linux-5.4/fs/aufs/i_op_ren.c linux-5.4-aufs/fs/aufs/i_op_ren.c +--- linux-5.4/fs/aufs/i_op_ren.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/i_op_ren.c 2019-11-28 01:25:59.066925618 +0200 +@@ -0,0 +1,1237 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * inode operation (rename entry) ++ * todo: this is crazy monster ++ */ ++ ++#include ++#include "aufs.h" ++ ++enum { AuSRC, AuDST, AuSrcDst }; ++enum { AuPARENT, AuCHILD, AuParentChild }; ++ ++#define AuRen_ISDIR_SRC 1 ++#define AuRen_ISDIR_DST (1 << 1) ++#define AuRen_ISSAMEDIR (1 << 2) ++#define AuRen_WHSRC (1 << 3) ++#define AuRen_WHDST (1 << 4) ++#define AuRen_MNT_WRITE (1 << 5) ++#define AuRen_DT_DSTDIR (1 << 6) ++#define AuRen_DIROPQ_SRC (1 << 7) ++#define AuRen_DIROPQ_DST (1 << 8) ++#define AuRen_DIRREN (1 << 9) ++#define AuRen_DROPPED_SRC (1 << 10) ++#define AuRen_DROPPED_DST (1 << 11) ++#define au_ftest_ren(flags, name) ((flags) & AuRen_##name) ++#define au_fset_ren(flags, name) \ ++ do { (flags) |= AuRen_##name; } while (0) ++#define au_fclr_ren(flags, name) \ ++ do { (flags) &= ~AuRen_##name; } while (0) ++ ++#ifndef CONFIG_AUFS_DIRREN ++#undef AuRen_DIRREN ++#define AuRen_DIRREN 0 ++#endif ++ ++struct au_ren_args { ++ struct { ++ struct dentry *dentry, *h_dentry, *parent, *h_parent, ++ *wh_dentry; ++ struct inode *dir, *inode; ++ struct au_hinode *hdir, *hinode; ++ struct au_dtime dt[AuParentChild]; ++ aufs_bindex_t btop, bdiropq; ++ } sd[AuSrcDst]; ++ ++#define src_dentry sd[AuSRC].dentry ++#define src_dir sd[AuSRC].dir ++#define src_inode sd[AuSRC].inode ++#define src_h_dentry sd[AuSRC].h_dentry ++#define src_parent sd[AuSRC].parent ++#define src_h_parent sd[AuSRC].h_parent ++#define src_wh_dentry sd[AuSRC].wh_dentry ++#define src_hdir sd[AuSRC].hdir ++#define src_hinode sd[AuSRC].hinode ++#define src_h_dir sd[AuSRC].hdir->hi_inode ++#define src_dt sd[AuSRC].dt ++#define src_btop sd[AuSRC].btop ++#define src_bdiropq sd[AuSRC].bdiropq ++ ++#define dst_dentry sd[AuDST].dentry ++#define dst_dir sd[AuDST].dir ++#define dst_inode sd[AuDST].inode ++#define dst_h_dentry sd[AuDST].h_dentry ++#define dst_parent sd[AuDST].parent ++#define dst_h_parent sd[AuDST].h_parent ++#define dst_wh_dentry sd[AuDST].wh_dentry ++#define dst_hdir sd[AuDST].hdir ++#define dst_hinode sd[AuDST].hinode ++#define dst_h_dir sd[AuDST].hdir->hi_inode ++#define dst_dt sd[AuDST].dt ++#define dst_btop sd[AuDST].btop ++#define dst_bdiropq sd[AuDST].bdiropq ++ ++ struct dentry *h_trap; ++ struct au_branch *br; ++ struct path h_path; ++ struct au_nhash whlist; ++ aufs_bindex_t btgt, src_bwh; ++ ++ struct { ++ unsigned short auren_flags; ++ unsigned char flags; /* syscall parameter */ ++ unsigned char exchange; ++ } __packed; ++ ++ struct au_whtmp_rmdir *thargs; ++ struct dentry *h_dst; ++ struct au_hinode *h_root; ++}; ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * functions for reverting. ++ * when an error happened in a single rename systemcall, we should revert ++ * everything as if nothing happened. ++ * we don't need to revert the copied-up/down the parent dir since they are ++ * harmless. ++ */ ++ ++#define RevertFailure(fmt, ...) do { \ ++ AuIOErr("revert failure: " fmt " (%d, %d)\n", \ ++ ##__VA_ARGS__, err, rerr); \ ++ err = -EIO; \ ++} while (0) ++ ++static void au_ren_do_rev_diropq(int err, struct au_ren_args *a, int idx) ++{ ++ int rerr; ++ struct dentry *d; ++#define src_or_dst(member) a->sd[idx].member ++ ++ d = src_or_dst(dentry); /* {src,dst}_dentry */ ++ au_hn_inode_lock_nested(src_or_dst(hinode), AuLsc_I_CHILD); ++ rerr = au_diropq_remove(d, a->btgt); ++ au_hn_inode_unlock(src_or_dst(hinode)); ++ au_set_dbdiropq(d, src_or_dst(bdiropq)); ++ if (rerr) ++ RevertFailure("remove diropq %pd", d); ++ ++#undef src_or_dst_ ++} ++ ++static void au_ren_rev_diropq(int err, struct au_ren_args *a) ++{ ++ if (au_ftest_ren(a->auren_flags, DIROPQ_SRC)) ++ au_ren_do_rev_diropq(err, a, AuSRC); ++ if (au_ftest_ren(a->auren_flags, DIROPQ_DST)) ++ au_ren_do_rev_diropq(err, a, AuDST); ++} ++ ++static void au_ren_rev_rename(int err, struct au_ren_args *a) ++{ ++ int rerr; ++ struct inode *delegated; ++ ++ a->h_path.dentry = vfsub_lkup_one(&a->src_dentry->d_name, ++ a->src_h_parent); ++ rerr = PTR_ERR(a->h_path.dentry); ++ if (IS_ERR(a->h_path.dentry)) { ++ RevertFailure("lkup one %pd", a->src_dentry); ++ return; ++ } ++ ++ delegated = NULL; ++ rerr = vfsub_rename(a->dst_h_dir, ++ au_h_dptr(a->src_dentry, a->btgt), ++ a->src_h_dir, &a->h_path, &delegated, a->flags); ++ if (unlikely(rerr == -EWOULDBLOCK)) { ++ pr_warn("cannot retry for NFSv4 delegation" ++ " for an internal rename\n"); ++ iput(delegated); ++ } ++ d_drop(a->h_path.dentry); ++ dput(a->h_path.dentry); ++ /* au_set_h_dptr(a->src_dentry, a->btgt, NULL); */ ++ if (rerr) ++ RevertFailure("rename %pd", a->src_dentry); ++} ++ ++static void au_ren_rev_whtmp(int err, struct au_ren_args *a) ++{ ++ int rerr; ++ struct inode *delegated; ++ ++ a->h_path.dentry = vfsub_lkup_one(&a->dst_dentry->d_name, ++ a->dst_h_parent); ++ rerr = PTR_ERR(a->h_path.dentry); ++ if (IS_ERR(a->h_path.dentry)) { ++ RevertFailure("lkup one %pd", a->dst_dentry); ++ return; ++ } ++ if (d_is_positive(a->h_path.dentry)) { ++ d_drop(a->h_path.dentry); ++ dput(a->h_path.dentry); ++ return; ++ } ++ ++ delegated = NULL; ++ rerr = vfsub_rename(a->dst_h_dir, a->h_dst, a->dst_h_dir, &a->h_path, ++ &delegated, a->flags); ++ if (unlikely(rerr == -EWOULDBLOCK)) { ++ pr_warn("cannot retry for NFSv4 delegation" ++ " for an internal rename\n"); ++ iput(delegated); ++ } ++ d_drop(a->h_path.dentry); ++ dput(a->h_path.dentry); ++ if (!rerr) ++ au_set_h_dptr(a->dst_dentry, a->btgt, dget(a->h_dst)); ++ else ++ RevertFailure("rename %pd", a->h_dst); ++} ++ ++static void au_ren_rev_whsrc(int err, struct au_ren_args *a) ++{ ++ int rerr; ++ ++ a->h_path.dentry = a->src_wh_dentry; ++ rerr = au_wh_unlink_dentry(a->src_h_dir, &a->h_path, a->src_dentry); ++ au_set_dbwh(a->src_dentry, a->src_bwh); ++ if (rerr) ++ RevertFailure("unlink %pd", a->src_wh_dentry); ++} ++#undef RevertFailure ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * when we have to copyup the renaming entry, do it with the rename-target name ++ * in order to minimize the cost (the later actual rename is unnecessary). ++ * otherwise rename it on the target branch. ++ */ ++static int au_ren_or_cpup(struct au_ren_args *a) ++{ ++ int err; ++ struct dentry *d; ++ struct inode *delegated; ++ ++ d = a->src_dentry; ++ if (au_dbtop(d) == a->btgt) { ++ a->h_path.dentry = a->dst_h_dentry; ++ AuDebugOn(au_dbtop(d) != a->btgt); ++ delegated = NULL; ++ err = vfsub_rename(a->src_h_dir, au_h_dptr(d, a->btgt), ++ a->dst_h_dir, &a->h_path, &delegated, ++ a->flags); ++ if (unlikely(err == -EWOULDBLOCK)) { ++ pr_warn("cannot retry for NFSv4 delegation" ++ " for an internal rename\n"); ++ iput(delegated); ++ } ++ } else ++ BUG(); ++ ++ if (!err && a->h_dst) ++ /* it will be set to dinfo later */ ++ dget(a->h_dst); ++ ++ return err; ++} ++ ++/* cf. aufs_rmdir() */ ++static int au_ren_del_whtmp(struct au_ren_args *a) ++{ ++ int err; ++ struct inode *dir; ++ ++ dir = a->dst_dir; ++ SiMustAnyLock(dir->i_sb); ++ if (!au_nhash_test_longer_wh(&a->whlist, a->btgt, ++ au_sbi(dir->i_sb)->si_dirwh) ++ || au_test_fs_remote(a->h_dst->d_sb)) { ++ err = au_whtmp_rmdir(dir, a->btgt, a->h_dst, &a->whlist); ++ if (unlikely(err)) ++ pr_warn("failed removing whtmp dir %pd (%d), " ++ "ignored.\n", a->h_dst, err); ++ } else { ++ au_nhash_wh_free(&a->thargs->whlist); ++ a->thargs->whlist = a->whlist; ++ a->whlist.nh_num = 0; ++ au_whtmp_kick_rmdir(dir, a->btgt, a->h_dst, a->thargs); ++ dput(a->h_dst); ++ a->thargs = NULL; ++ } ++ ++ return 0; ++} ++ ++/* make it 'opaque' dir. */ ++static int au_ren_do_diropq(struct au_ren_args *a, int idx) ++{ ++ int err; ++ struct dentry *d, *diropq; ++#define src_or_dst(member) a->sd[idx].member ++ ++ err = 0; ++ d = src_or_dst(dentry); /* {src,dst}_dentry */ ++ src_or_dst(bdiropq) = au_dbdiropq(d); ++ src_or_dst(hinode) = au_hi(src_or_dst(inode), a->btgt); ++ au_hn_inode_lock_nested(src_or_dst(hinode), AuLsc_I_CHILD); ++ diropq = au_diropq_create(d, a->btgt); ++ au_hn_inode_unlock(src_or_dst(hinode)); ++ if (IS_ERR(diropq)) ++ err = PTR_ERR(diropq); ++ else ++ dput(diropq); ++ ++#undef src_or_dst_ ++ return err; ++} ++ ++static int au_ren_diropq(struct au_ren_args *a) ++{ ++ int err; ++ unsigned char always; ++ struct dentry *d; ++ ++ err = 0; ++ d = a->dst_dentry; /* already renamed on the branch */ ++ always = !!au_opt_test(au_mntflags(d->d_sb), ALWAYS_DIROPQ); ++ if (au_ftest_ren(a->auren_flags, ISDIR_SRC) ++ && !au_ftest_ren(a->auren_flags, DIRREN) ++ && a->btgt != au_dbdiropq(a->src_dentry) ++ && (a->dst_wh_dentry ++ || a->btgt <= au_dbdiropq(d) ++ /* hide the lower to keep xino */ ++ /* the lowers may not be a dir, but we hide them anyway */ ++ || a->btgt < au_dbbot(d) ++ || always)) { ++ AuDbg("here\n"); ++ err = au_ren_do_diropq(a, AuSRC); ++ if (unlikely(err)) ++ goto out; ++ au_fset_ren(a->auren_flags, DIROPQ_SRC); ++ } ++ if (!a->exchange) ++ goto out; /* success */ ++ ++ d = a->src_dentry; /* already renamed on the branch */ ++ if (au_ftest_ren(a->auren_flags, ISDIR_DST) ++ && a->btgt != au_dbdiropq(a->dst_dentry) ++ && (a->btgt < au_dbdiropq(d) ++ || a->btgt < au_dbbot(d) ++ || always)) { ++ AuDbgDentry(a->src_dentry); ++ AuDbgDentry(a->dst_dentry); ++ err = au_ren_do_diropq(a, AuDST); ++ if (unlikely(err)) ++ goto out_rev_src; ++ au_fset_ren(a->auren_flags, DIROPQ_DST); ++ } ++ goto out; /* success */ ++ ++out_rev_src: ++ AuDbg("err %d, reverting src\n", err); ++ au_ren_rev_diropq(err, a); ++out: ++ return err; ++} ++ ++static int do_rename(struct au_ren_args *a) ++{ ++ int err; ++ struct dentry *d, *h_d; ++ ++ if (!a->exchange) { ++ /* prepare workqueue args for asynchronous rmdir */ ++ h_d = a->dst_h_dentry; ++ if (au_ftest_ren(a->auren_flags, ISDIR_DST) ++ /* && !au_ftest_ren(a->auren_flags, DIRREN) */ ++ && d_is_positive(h_d)) { ++ err = -ENOMEM; ++ a->thargs = au_whtmp_rmdir_alloc(a->src_dentry->d_sb, ++ GFP_NOFS); ++ if (unlikely(!a->thargs)) ++ goto out; ++ a->h_dst = dget(h_d); ++ } ++ ++ /* create whiteout for src_dentry */ ++ if (au_ftest_ren(a->auren_flags, WHSRC)) { ++ a->src_bwh = au_dbwh(a->src_dentry); ++ AuDebugOn(a->src_bwh >= 0); ++ a->src_wh_dentry = au_wh_create(a->src_dentry, a->btgt, ++ a->src_h_parent); ++ err = PTR_ERR(a->src_wh_dentry); ++ if (IS_ERR(a->src_wh_dentry)) ++ goto out_thargs; ++ } ++ ++ /* lookup whiteout for dentry */ ++ if (au_ftest_ren(a->auren_flags, WHDST)) { ++ h_d = au_wh_lkup(a->dst_h_parent, ++ &a->dst_dentry->d_name, a->br); ++ err = PTR_ERR(h_d); ++ if (IS_ERR(h_d)) ++ goto out_whsrc; ++ if (d_is_negative(h_d)) ++ dput(h_d); ++ else ++ a->dst_wh_dentry = h_d; ++ } ++ ++ /* rename dentry to tmpwh */ ++ if (a->thargs) { ++ err = au_whtmp_ren(a->dst_h_dentry, a->br); ++ if (unlikely(err)) ++ goto out_whdst; ++ ++ d = a->dst_dentry; ++ au_set_h_dptr(d, a->btgt, NULL); ++ err = au_lkup_neg(d, a->btgt, /*wh*/0); ++ if (unlikely(err)) ++ goto out_whtmp; ++ a->dst_h_dentry = au_h_dptr(d, a->btgt); ++ } ++ } ++ ++ BUG_ON(d_is_positive(a->dst_h_dentry) && a->src_btop != a->btgt); ++#if 0 ++ BUG_ON(!au_ftest_ren(a->auren_flags, DIRREN) ++ && d_is_positive(a->dst_h_dentry) ++ && a->src_btop != a->btgt); ++#endif ++ ++ /* rename by vfs_rename or cpup */ ++ err = au_ren_or_cpup(a); ++ if (unlikely(err)) ++ /* leave the copied-up one */ ++ goto out_whtmp; ++ ++ /* make dir opaque */ ++ err = au_ren_diropq(a); ++ if (unlikely(err)) ++ goto out_rename; ++ ++ /* update target timestamps */ ++ if (a->exchange) { ++ AuDebugOn(au_dbtop(a->dst_dentry) != a->btgt); ++ a->h_path.dentry = au_h_dptr(a->dst_dentry, a->btgt); ++ vfsub_update_h_iattr(&a->h_path, /*did*/NULL); /*ignore*/ ++ a->dst_inode->i_ctime = d_inode(a->h_path.dentry)->i_ctime; ++ } ++ AuDebugOn(au_dbtop(a->src_dentry) != a->btgt); ++ a->h_path.dentry = au_h_dptr(a->src_dentry, a->btgt); ++ vfsub_update_h_iattr(&a->h_path, /*did*/NULL); /*ignore*/ ++ a->src_inode->i_ctime = d_inode(a->h_path.dentry)->i_ctime; ++ ++ if (!a->exchange) { ++ /* remove whiteout for dentry */ ++ if (a->dst_wh_dentry) { ++ a->h_path.dentry = a->dst_wh_dentry; ++ err = au_wh_unlink_dentry(a->dst_h_dir, &a->h_path, ++ a->dst_dentry); ++ if (unlikely(err)) ++ goto out_diropq; ++ } ++ ++ /* remove whtmp */ ++ if (a->thargs) ++ au_ren_del_whtmp(a); /* ignore this error */ ++ ++ au_fhsm_wrote(a->src_dentry->d_sb, a->btgt, /*force*/0); ++ } ++ err = 0; ++ goto out_success; ++ ++out_diropq: ++ au_ren_rev_diropq(err, a); ++out_rename: ++ au_ren_rev_rename(err, a); ++ dput(a->h_dst); ++out_whtmp: ++ if (a->thargs) ++ au_ren_rev_whtmp(err, a); ++out_whdst: ++ dput(a->dst_wh_dentry); ++ a->dst_wh_dentry = NULL; ++out_whsrc: ++ if (a->src_wh_dentry) ++ au_ren_rev_whsrc(err, a); ++out_success: ++ dput(a->src_wh_dentry); ++ dput(a->dst_wh_dentry); ++out_thargs: ++ if (a->thargs) { ++ dput(a->h_dst); ++ au_whtmp_rmdir_free(a->thargs); ++ a->thargs = NULL; ++ } ++out: ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * test if @dentry dir can be rename destination or not. ++ * success means, it is a logically empty dir. ++ */ ++static int may_rename_dstdir(struct dentry *dentry, struct au_nhash *whlist) ++{ ++ return au_test_empty(dentry, whlist); ++} ++ ++/* ++ * test if @a->src_dentry dir can be rename source or not. ++ * if it can, return 0. ++ * success means, ++ * - it is a logically empty dir. ++ * - or, it exists on writable branch and has no children including whiteouts ++ * on the lower branch unless DIRREN is on. ++ */ ++static int may_rename_srcdir(struct au_ren_args *a) ++{ ++ int err; ++ unsigned int rdhash; ++ aufs_bindex_t btop, btgt; ++ struct dentry *dentry; ++ struct super_block *sb; ++ struct au_sbinfo *sbinfo; ++ ++ dentry = a->src_dentry; ++ sb = dentry->d_sb; ++ sbinfo = au_sbi(sb); ++ if (au_opt_test(sbinfo->si_mntflags, DIRREN)) ++ au_fset_ren(a->auren_flags, DIRREN); ++ ++ btgt = a->btgt; ++ btop = au_dbtop(dentry); ++ if (btop != btgt) { ++ struct au_nhash whlist; ++ ++ SiMustAnyLock(sb); ++ rdhash = sbinfo->si_rdhash; ++ if (!rdhash) ++ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, ++ dentry)); ++ err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS); ++ if (unlikely(err)) ++ goto out; ++ err = au_test_empty(dentry, &whlist); ++ au_nhash_wh_free(&whlist); ++ goto out; ++ } ++ ++ if (btop == au_dbtaildir(dentry)) ++ return 0; /* success */ ++ ++ err = au_test_empty_lower(dentry); ++ ++out: ++ if (err == -ENOTEMPTY) { ++ if (au_ftest_ren(a->auren_flags, DIRREN)) { ++ err = 0; ++ } else { ++ AuWarn1("renaming dir who has child(ren) on multiple " ++ "branches, is not supported\n"); ++ err = -EXDEV; ++ } ++ } ++ return err; ++} ++ ++/* side effect: sets whlist and h_dentry */ ++static int au_ren_may_dir(struct au_ren_args *a) ++{ ++ int err; ++ unsigned int rdhash; ++ struct dentry *d; ++ ++ d = a->dst_dentry; ++ SiMustAnyLock(d->d_sb); ++ ++ err = 0; ++ if (au_ftest_ren(a->auren_flags, ISDIR_DST) && a->dst_inode) { ++ rdhash = au_sbi(d->d_sb)->si_rdhash; ++ if (!rdhash) ++ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, d)); ++ err = au_nhash_alloc(&a->whlist, rdhash, GFP_NOFS); ++ if (unlikely(err)) ++ goto out; ++ ++ if (!a->exchange) { ++ au_set_dbtop(d, a->dst_btop); ++ err = may_rename_dstdir(d, &a->whlist); ++ au_set_dbtop(d, a->btgt); ++ } else ++ err = may_rename_srcdir(a); ++ } ++ a->dst_h_dentry = au_h_dptr(d, au_dbtop(d)); ++ if (unlikely(err)) ++ goto out; ++ ++ d = a->src_dentry; ++ a->src_h_dentry = au_h_dptr(d, au_dbtop(d)); ++ if (au_ftest_ren(a->auren_flags, ISDIR_SRC)) { ++ err = may_rename_srcdir(a); ++ if (unlikely(err)) { ++ au_nhash_wh_free(&a->whlist); ++ a->whlist.nh_num = 0; ++ } ++ } ++out: ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * simple tests for rename. ++ * following the checks in vfs, plus the parent-child relationship. ++ */ ++static int au_may_ren(struct au_ren_args *a) ++{ ++ int err, isdir; ++ struct inode *h_inode; ++ ++ if (a->src_btop == a->btgt) { ++ err = au_may_del(a->src_dentry, a->btgt, a->src_h_parent, ++ au_ftest_ren(a->auren_flags, ISDIR_SRC)); ++ if (unlikely(err)) ++ goto out; ++ err = -EINVAL; ++ if (unlikely(a->src_h_dentry == a->h_trap)) ++ goto out; ++ } ++ ++ err = 0; ++ if (a->dst_btop != a->btgt) ++ goto out; ++ ++ err = -ENOTEMPTY; ++ if (unlikely(a->dst_h_dentry == a->h_trap)) ++ goto out; ++ ++ err = -EIO; ++ isdir = !!au_ftest_ren(a->auren_flags, ISDIR_DST); ++ if (d_really_is_negative(a->dst_dentry)) { ++ if (d_is_negative(a->dst_h_dentry)) ++ err = au_may_add(a->dst_dentry, a->btgt, ++ a->dst_h_parent, isdir); ++ } else { ++ if (unlikely(d_is_negative(a->dst_h_dentry))) ++ goto out; ++ h_inode = d_inode(a->dst_h_dentry); ++ if (h_inode->i_nlink) ++ err = au_may_del(a->dst_dentry, a->btgt, ++ a->dst_h_parent, isdir); ++ } ++ ++out: ++ if (unlikely(err == -ENOENT || err == -EEXIST)) ++ err = -EIO; ++ AuTraceErr(err); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * locking order ++ * (VFS) ++ * - src_dir and dir by lock_rename() ++ * - inode if exists ++ * (aufs) ++ * - lock all ++ * + src_dentry and dentry by aufs_read_and_write_lock2() which calls, ++ * + si_read_lock ++ * + di_write_lock2_child() ++ * + di_write_lock_child() ++ * + ii_write_lock_child() ++ * + di_write_lock_child2() ++ * + ii_write_lock_child2() ++ * + src_parent and parent ++ * + di_write_lock_parent() ++ * + ii_write_lock_parent() ++ * + di_write_lock_parent2() ++ * + ii_write_lock_parent2() ++ * + lower src_dir and dir by vfsub_lock_rename() ++ * + verify the every relationships between child and parent. if any ++ * of them failed, unlock all and return -EBUSY. ++ */ ++static void au_ren_unlock(struct au_ren_args *a) ++{ ++ vfsub_unlock_rename(a->src_h_parent, a->src_hdir, ++ a->dst_h_parent, a->dst_hdir); ++ if (au_ftest_ren(a->auren_flags, DIRREN) ++ && a->h_root) ++ au_hn_inode_unlock(a->h_root); ++ if (au_ftest_ren(a->auren_flags, MNT_WRITE)) ++ vfsub_mnt_drop_write(au_br_mnt(a->br)); ++} ++ ++static int au_ren_lock(struct au_ren_args *a) ++{ ++ int err; ++ unsigned int udba; ++ ++ err = 0; ++ a->src_h_parent = au_h_dptr(a->src_parent, a->btgt); ++ a->src_hdir = au_hi(a->src_dir, a->btgt); ++ a->dst_h_parent = au_h_dptr(a->dst_parent, a->btgt); ++ a->dst_hdir = au_hi(a->dst_dir, a->btgt); ++ ++ err = vfsub_mnt_want_write(au_br_mnt(a->br)); ++ if (unlikely(err)) ++ goto out; ++ au_fset_ren(a->auren_flags, MNT_WRITE); ++ if (au_ftest_ren(a->auren_flags, DIRREN)) { ++ struct dentry *root; ++ struct inode *dir; ++ ++ /* ++ * sbinfo is already locked, so this ii_read_lock is ++ * unnecessary. but our debugging feature checks it. ++ */ ++ root = a->src_inode->i_sb->s_root; ++ if (root != a->src_parent && root != a->dst_parent) { ++ dir = d_inode(root); ++ ii_read_lock_parent3(dir); ++ a->h_root = au_hi(dir, a->btgt); ++ ii_read_unlock(dir); ++ au_hn_inode_lock_nested(a->h_root, AuLsc_I_PARENT3); ++ } ++ } ++ a->h_trap = vfsub_lock_rename(a->src_h_parent, a->src_hdir, ++ a->dst_h_parent, a->dst_hdir); ++ udba = au_opt_udba(a->src_dentry->d_sb); ++ if (unlikely(a->src_hdir->hi_inode != d_inode(a->src_h_parent) ++ || a->dst_hdir->hi_inode != d_inode(a->dst_h_parent))) ++ err = au_busy_or_stale(); ++ if (!err && au_dbtop(a->src_dentry) == a->btgt) ++ err = au_h_verify(a->src_h_dentry, udba, ++ d_inode(a->src_h_parent), a->src_h_parent, ++ a->br); ++ if (!err && au_dbtop(a->dst_dentry) == a->btgt) ++ err = au_h_verify(a->dst_h_dentry, udba, ++ d_inode(a->dst_h_parent), a->dst_h_parent, ++ a->br); ++ if (!err) ++ goto out; /* success */ ++ ++ err = au_busy_or_stale(); ++ au_ren_unlock(a); ++ ++out: ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static void au_ren_refresh_dir(struct au_ren_args *a) ++{ ++ struct inode *dir; ++ ++ dir = a->dst_dir; ++ inode_inc_iversion(dir); ++ if (au_ftest_ren(a->auren_flags, ISDIR_SRC)) { ++ /* is this updating defined in POSIX? */ ++ au_cpup_attr_timesizes(a->src_inode); ++ au_cpup_attr_nlink(dir, /*force*/1); ++ } ++ au_dir_ts(dir, a->btgt); ++ ++ if (a->exchange) { ++ dir = a->src_dir; ++ inode_inc_iversion(dir); ++ if (au_ftest_ren(a->auren_flags, ISDIR_DST)) { ++ /* is this updating defined in POSIX? */ ++ au_cpup_attr_timesizes(a->dst_inode); ++ au_cpup_attr_nlink(dir, /*force*/1); ++ } ++ au_dir_ts(dir, a->btgt); ++ } ++ ++ if (au_ftest_ren(a->auren_flags, ISSAMEDIR)) ++ return; ++ ++ dir = a->src_dir; ++ inode_inc_iversion(dir); ++ if (au_ftest_ren(a->auren_flags, ISDIR_SRC)) ++ au_cpup_attr_nlink(dir, /*force*/1); ++ au_dir_ts(dir, a->btgt); ++} ++ ++static void au_ren_refresh(struct au_ren_args *a) ++{ ++ aufs_bindex_t bbot, bindex; ++ struct dentry *d, *h_d; ++ struct inode *i, *h_i; ++ struct super_block *sb; ++ ++ d = a->dst_dentry; ++ d_drop(d); ++ if (a->h_dst) ++ /* already dget-ed by au_ren_or_cpup() */ ++ au_set_h_dptr(d, a->btgt, a->h_dst); ++ ++ i = a->dst_inode; ++ if (i) { ++ if (!a->exchange) { ++ if (!au_ftest_ren(a->auren_flags, ISDIR_DST)) ++ vfsub_drop_nlink(i); ++ else { ++ vfsub_dead_dir(i); ++ au_cpup_attr_timesizes(i); ++ } ++ au_update_dbrange(d, /*do_put_zero*/1); ++ } else ++ au_cpup_attr_nlink(i, /*force*/1); ++ } else { ++ bbot = a->btgt; ++ for (bindex = au_dbtop(d); bindex < bbot; bindex++) ++ au_set_h_dptr(d, bindex, NULL); ++ bbot = au_dbbot(d); ++ for (bindex = a->btgt + 1; bindex <= bbot; bindex++) ++ au_set_h_dptr(d, bindex, NULL); ++ au_update_dbrange(d, /*do_put_zero*/0); ++ } ++ ++ if (a->exchange ++ || au_ftest_ren(a->auren_flags, DIRREN)) { ++ d_drop(a->src_dentry); ++ if (au_ftest_ren(a->auren_flags, DIRREN)) ++ au_set_dbwh(a->src_dentry, -1); ++ return; ++ } ++ ++ d = a->src_dentry; ++ au_set_dbwh(d, -1); ++ bbot = au_dbbot(d); ++ for (bindex = a->btgt + 1; bindex <= bbot; bindex++) { ++ h_d = au_h_dptr(d, bindex); ++ if (h_d) ++ au_set_h_dptr(d, bindex, NULL); ++ } ++ au_set_dbbot(d, a->btgt); ++ ++ sb = d->d_sb; ++ i = a->src_inode; ++ if (au_opt_test(au_mntflags(sb), PLINK) && au_plink_test(i)) ++ return; /* success */ ++ ++ bbot = au_ibbot(i); ++ for (bindex = a->btgt + 1; bindex <= bbot; bindex++) { ++ h_i = au_h_iptr(i, bindex); ++ if (h_i) { ++ au_xino_write(sb, bindex, h_i->i_ino, /*ino*/0); ++ /* ignore this error */ ++ au_set_h_iptr(i, bindex, NULL, 0); ++ } ++ } ++ au_set_ibbot(i, a->btgt); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* mainly for link(2) and rename(2) */ ++int au_wbr(struct dentry *dentry, aufs_bindex_t btgt) ++{ ++ aufs_bindex_t bdiropq, bwh; ++ struct dentry *parent; ++ struct au_branch *br; ++ ++ parent = dentry->d_parent; ++ IMustLock(d_inode(parent)); /* dir is locked */ ++ ++ bdiropq = au_dbdiropq(parent); ++ bwh = au_dbwh(dentry); ++ br = au_sbr(dentry->d_sb, btgt); ++ if (au_br_rdonly(br) ++ || (0 <= bdiropq && bdiropq < btgt) ++ || (0 <= bwh && bwh < btgt)) ++ btgt = -1; ++ ++ AuDbg("btgt %d\n", btgt); ++ return btgt; ++} ++ ++/* sets src_btop, dst_btop and btgt */ ++static int au_ren_wbr(struct au_ren_args *a) ++{ ++ int err; ++ struct au_wr_dir_args wr_dir_args = { ++ /* .force_btgt = -1, */ ++ .flags = AuWrDir_ADD_ENTRY ++ }; ++ ++ a->src_btop = au_dbtop(a->src_dentry); ++ a->dst_btop = au_dbtop(a->dst_dentry); ++ if (au_ftest_ren(a->auren_flags, ISDIR_SRC) ++ || au_ftest_ren(a->auren_flags, ISDIR_DST)) ++ au_fset_wrdir(wr_dir_args.flags, ISDIR); ++ wr_dir_args.force_btgt = a->src_btop; ++ if (a->dst_inode && a->dst_btop < a->src_btop) ++ wr_dir_args.force_btgt = a->dst_btop; ++ wr_dir_args.force_btgt = au_wbr(a->dst_dentry, wr_dir_args.force_btgt); ++ err = au_wr_dir(a->dst_dentry, a->src_dentry, &wr_dir_args); ++ a->btgt = err; ++ if (a->exchange) ++ au_update_dbtop(a->dst_dentry); ++ ++ return err; ++} ++ ++static void au_ren_dt(struct au_ren_args *a) ++{ ++ a->h_path.dentry = a->src_h_parent; ++ au_dtime_store(a->src_dt + AuPARENT, a->src_parent, &a->h_path); ++ if (!au_ftest_ren(a->auren_flags, ISSAMEDIR)) { ++ a->h_path.dentry = a->dst_h_parent; ++ au_dtime_store(a->dst_dt + AuPARENT, a->dst_parent, &a->h_path); ++ } ++ ++ au_fclr_ren(a->auren_flags, DT_DSTDIR); ++ if (!au_ftest_ren(a->auren_flags, ISDIR_SRC) ++ && !a->exchange) ++ return; ++ ++ a->h_path.dentry = a->src_h_dentry; ++ au_dtime_store(a->src_dt + AuCHILD, a->src_dentry, &a->h_path); ++ if (d_is_positive(a->dst_h_dentry)) { ++ au_fset_ren(a->auren_flags, DT_DSTDIR); ++ a->h_path.dentry = a->dst_h_dentry; ++ au_dtime_store(a->dst_dt + AuCHILD, a->dst_dentry, &a->h_path); ++ } ++} ++ ++static void au_ren_rev_dt(int err, struct au_ren_args *a) ++{ ++ struct dentry *h_d; ++ struct inode *h_inode; ++ ++ au_dtime_revert(a->src_dt + AuPARENT); ++ if (!au_ftest_ren(a->auren_flags, ISSAMEDIR)) ++ au_dtime_revert(a->dst_dt + AuPARENT); ++ ++ if (au_ftest_ren(a->auren_flags, ISDIR_SRC) && err != -EIO) { ++ h_d = a->src_dt[AuCHILD].dt_h_path.dentry; ++ h_inode = d_inode(h_d); ++ inode_lock_nested(h_inode, AuLsc_I_CHILD); ++ au_dtime_revert(a->src_dt + AuCHILD); ++ inode_unlock(h_inode); ++ ++ if (au_ftest_ren(a->auren_flags, DT_DSTDIR)) { ++ h_d = a->dst_dt[AuCHILD].dt_h_path.dentry; ++ h_inode = d_inode(h_d); ++ inode_lock_nested(h_inode, AuLsc_I_CHILD); ++ au_dtime_revert(a->dst_dt + AuCHILD); ++ inode_unlock(h_inode); ++ } ++ } ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++int aufs_rename(struct inode *_src_dir, struct dentry *_src_dentry, ++ struct inode *_dst_dir, struct dentry *_dst_dentry, ++ unsigned int _flags) ++{ ++ int err, lock_flags; ++ void *rev; ++ /* reduce stack space */ ++ struct au_ren_args *a; ++ struct au_pin pin; ++ ++ AuDbg("%pd, %pd, 0x%x\n", _src_dentry, _dst_dentry, _flags); ++ IMustLock(_src_dir); ++ IMustLock(_dst_dir); ++ ++ err = -EINVAL; ++ if (unlikely(_flags & RENAME_WHITEOUT)) ++ goto out; ++ ++ err = -ENOMEM; ++ BUILD_BUG_ON(sizeof(*a) > PAGE_SIZE); ++ a = kzalloc(sizeof(*a), GFP_NOFS); ++ if (unlikely(!a)) ++ goto out; ++ ++ a->flags = _flags; ++ BUILD_BUG_ON(sizeof(a->exchange) == sizeof(u8) ++ && RENAME_EXCHANGE > U8_MAX); ++ a->exchange = _flags & RENAME_EXCHANGE; ++ a->src_dir = _src_dir; ++ a->src_dentry = _src_dentry; ++ a->src_inode = NULL; ++ if (d_really_is_positive(a->src_dentry)) ++ a->src_inode = d_inode(a->src_dentry); ++ a->src_parent = a->src_dentry->d_parent; /* dir inode is locked */ ++ a->dst_dir = _dst_dir; ++ a->dst_dentry = _dst_dentry; ++ a->dst_inode = NULL; ++ if (d_really_is_positive(a->dst_dentry)) ++ a->dst_inode = d_inode(a->dst_dentry); ++ a->dst_parent = a->dst_dentry->d_parent; /* dir inode is locked */ ++ if (a->dst_inode) { ++ /* ++ * if EXCHANGE && src is non-dir && dst is dir, ++ * dst is not locked. ++ */ ++ /* IMustLock(a->dst_inode); */ ++ au_igrab(a->dst_inode); ++ } ++ ++ err = -ENOTDIR; ++ lock_flags = AuLock_FLUSH | AuLock_NOPLM | AuLock_GEN; ++ if (d_is_dir(a->src_dentry)) { ++ au_fset_ren(a->auren_flags, ISDIR_SRC); ++ if (unlikely(!a->exchange ++ && d_really_is_positive(a->dst_dentry) ++ && !d_is_dir(a->dst_dentry))) ++ goto out_free; ++ lock_flags |= AuLock_DIRS; ++ } ++ if (a->dst_inode && d_is_dir(a->dst_dentry)) { ++ au_fset_ren(a->auren_flags, ISDIR_DST); ++ if (unlikely(!a->exchange ++ && d_really_is_positive(a->src_dentry) ++ && !d_is_dir(a->src_dentry))) ++ goto out_free; ++ lock_flags |= AuLock_DIRS; ++ } ++ err = aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry, ++ lock_flags); ++ if (unlikely(err)) ++ goto out_free; ++ ++ err = au_d_hashed_positive(a->src_dentry); ++ if (unlikely(err)) ++ goto out_unlock; ++ err = -ENOENT; ++ if (a->dst_inode) { ++ /* ++ * If it is a dir, VFS unhash it before this ++ * function. It means we cannot rely upon d_unhashed(). ++ */ ++ if (unlikely(!a->dst_inode->i_nlink)) ++ goto out_unlock; ++ if (!au_ftest_ren(a->auren_flags, ISDIR_DST)) { ++ err = au_d_hashed_positive(a->dst_dentry); ++ if (unlikely(err && !a->exchange)) ++ goto out_unlock; ++ } else if (unlikely(IS_DEADDIR(a->dst_inode))) ++ goto out_unlock; ++ } else if (unlikely(d_unhashed(a->dst_dentry))) ++ goto out_unlock; ++ ++ /* ++ * is it possible? ++ * yes, it happened (in linux-3.3-rcN) but I don't know why. ++ * there may exist a problem somewhere else. ++ */ ++ err = -EINVAL; ++ if (unlikely(d_inode(a->dst_parent) == d_inode(a->src_dentry))) ++ goto out_unlock; ++ ++ au_fset_ren(a->auren_flags, ISSAMEDIR); /* temporary */ ++ di_write_lock_parent(a->dst_parent); ++ ++ /* which branch we process */ ++ err = au_ren_wbr(a); ++ if (unlikely(err < 0)) ++ goto out_parent; ++ a->br = au_sbr(a->dst_dentry->d_sb, a->btgt); ++ a->h_path.mnt = au_br_mnt(a->br); ++ ++ /* are they available to be renamed */ ++ err = au_ren_may_dir(a); ++ if (unlikely(err)) ++ goto out_children; ++ ++ /* prepare the writable parent dir on the same branch */ ++ if (a->dst_btop == a->btgt) { ++ au_fset_ren(a->auren_flags, WHDST); ++ } else { ++ err = au_cpup_dirs(a->dst_dentry, a->btgt); ++ if (unlikely(err)) ++ goto out_children; ++ } ++ ++ err = 0; ++ if (!a->exchange) { ++ if (a->src_dir != a->dst_dir) { ++ /* ++ * this temporary unlock is safe, ++ * because both dir->i_mutex are locked. ++ */ ++ di_write_unlock(a->dst_parent); ++ di_write_lock_parent(a->src_parent); ++ err = au_wr_dir_need_wh(a->src_dentry, ++ au_ftest_ren(a->auren_flags, ++ ISDIR_SRC), ++ &a->btgt); ++ di_write_unlock(a->src_parent); ++ di_write_lock2_parent(a->src_parent, a->dst_parent, ++ /*isdir*/1); ++ au_fclr_ren(a->auren_flags, ISSAMEDIR); ++ } else ++ err = au_wr_dir_need_wh(a->src_dentry, ++ au_ftest_ren(a->auren_flags, ++ ISDIR_SRC), ++ &a->btgt); ++ } ++ if (unlikely(err < 0)) ++ goto out_children; ++ if (err) ++ au_fset_ren(a->auren_flags, WHSRC); ++ ++ /* cpup src */ ++ if (a->src_btop != a->btgt) { ++ err = au_pin(&pin, a->src_dentry, a->btgt, ++ au_opt_udba(a->src_dentry->d_sb), ++ AuPin_DI_LOCKED | AuPin_MNT_WRITE); ++ if (!err) { ++ struct au_cp_generic cpg = { ++ .dentry = a->src_dentry, ++ .bdst = a->btgt, ++ .bsrc = a->src_btop, ++ .len = -1, ++ .pin = &pin, ++ .flags = AuCpup_DTIME | AuCpup_HOPEN ++ }; ++ AuDebugOn(au_dbtop(a->src_dentry) != a->src_btop); ++ err = au_sio_cpup_simple(&cpg); ++ au_unpin(&pin); ++ } ++ if (unlikely(err)) ++ goto out_children; ++ a->src_btop = a->btgt; ++ a->src_h_dentry = au_h_dptr(a->src_dentry, a->btgt); ++ if (!a->exchange) ++ au_fset_ren(a->auren_flags, WHSRC); ++ } ++ ++ /* cpup dst */ ++ if (a->exchange && a->dst_inode ++ && a->dst_btop != a->btgt) { ++ err = au_pin(&pin, a->dst_dentry, a->btgt, ++ au_opt_udba(a->dst_dentry->d_sb), ++ AuPin_DI_LOCKED | AuPin_MNT_WRITE); ++ if (!err) { ++ struct au_cp_generic cpg = { ++ .dentry = a->dst_dentry, ++ .bdst = a->btgt, ++ .bsrc = a->dst_btop, ++ .len = -1, ++ .pin = &pin, ++ .flags = AuCpup_DTIME | AuCpup_HOPEN ++ }; ++ err = au_sio_cpup_simple(&cpg); ++ au_unpin(&pin); ++ } ++ if (unlikely(err)) ++ goto out_children; ++ a->dst_btop = a->btgt; ++ a->dst_h_dentry = au_h_dptr(a->dst_dentry, a->btgt); ++ } ++ ++ /* lock them all */ ++ err = au_ren_lock(a); ++ if (unlikely(err)) ++ /* leave the copied-up one */ ++ goto out_children; ++ ++ if (!a->exchange) { ++ if (!au_opt_test(au_mntflags(a->dst_dir->i_sb), UDBA_NONE)) ++ err = au_may_ren(a); ++ else if (unlikely(a->dst_dentry->d_name.len > AUFS_MAX_NAMELEN)) ++ err = -ENAMETOOLONG; ++ if (unlikely(err)) ++ goto out_hdir; ++ } ++ ++ /* store timestamps to be revertible */ ++ au_ren_dt(a); ++ ++ /* store dirren info */ ++ if (au_ftest_ren(a->auren_flags, DIRREN)) { ++ err = au_dr_rename(a->src_dentry, a->btgt, ++ &a->dst_dentry->d_name, &rev); ++ AuTraceErr(err); ++ if (unlikely(err)) ++ goto out_dt; ++ } ++ ++ /* here we go */ ++ err = do_rename(a); ++ if (unlikely(err)) ++ goto out_dirren; ++ ++ if (au_ftest_ren(a->auren_flags, DIRREN)) ++ au_dr_rename_fin(a->src_dentry, a->btgt, rev); ++ ++ /* update dir attributes */ ++ au_ren_refresh_dir(a); ++ ++ /* dput/iput all lower dentries */ ++ au_ren_refresh(a); ++ ++ goto out_hdir; /* success */ ++ ++out_dirren: ++ if (au_ftest_ren(a->auren_flags, DIRREN)) ++ au_dr_rename_rev(a->src_dentry, a->btgt, rev); ++out_dt: ++ au_ren_rev_dt(err, a); ++out_hdir: ++ au_ren_unlock(a); ++out_children: ++ au_nhash_wh_free(&a->whlist); ++ if (err && a->dst_inode && a->dst_btop != a->btgt) { ++ AuDbg("btop %d, btgt %d\n", a->dst_btop, a->btgt); ++ au_set_h_dptr(a->dst_dentry, a->btgt, NULL); ++ au_set_dbtop(a->dst_dentry, a->dst_btop); ++ } ++out_parent: ++ if (!err) { ++ if (d_unhashed(a->src_dentry)) ++ au_fset_ren(a->auren_flags, DROPPED_SRC); ++ if (d_unhashed(a->dst_dentry)) ++ au_fset_ren(a->auren_flags, DROPPED_DST); ++ if (!a->exchange) ++ d_move(a->src_dentry, a->dst_dentry); ++ else { ++ d_exchange(a->src_dentry, a->dst_dentry); ++ if (au_ftest_ren(a->auren_flags, DROPPED_DST)) ++ d_drop(a->dst_dentry); ++ } ++ if (au_ftest_ren(a->auren_flags, DROPPED_SRC)) ++ d_drop(a->src_dentry); ++ } else { ++ au_update_dbtop(a->dst_dentry); ++ if (!a->dst_inode) ++ d_drop(a->dst_dentry); ++ } ++ if (au_ftest_ren(a->auren_flags, ISSAMEDIR)) ++ di_write_unlock(a->dst_parent); ++ else ++ di_write_unlock2(a->src_parent, a->dst_parent); ++out_unlock: ++ aufs_read_and_write_unlock2(a->dst_dentry, a->src_dentry); ++out_free: ++ iput(a->dst_inode); ++ if (a->thargs) ++ au_whtmp_rmdir_free(a->thargs); ++ au_kfree_rcu(a); ++out: ++ AuTraceErr(err); ++ return err; ++} +diff -Nurp linux-5.4/fs/aufs/Kconfig linux-5.4-aufs/fs/aufs/Kconfig +--- linux-5.4/fs/aufs/Kconfig 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/Kconfig 2019-11-28 01:25:59.062925618 +0200 +@@ -0,0 +1,199 @@ ++# SPDX-License-Identifier: GPL-2.0 ++config AUFS_FS ++ bool "Aufs (Advanced multi layered unification filesystem) support" ++ help ++ Aufs is a stackable unification filesystem such as Unionfs, ++ which unifies several directories and provides a merged single ++ directory. ++ In the early days, aufs was entirely re-designed and ++ re-implemented Unionfs Version 1.x series. Introducing many ++ original ideas, approaches and improvements, it becomes totally ++ different from Unionfs while keeping the basic features. ++ ++if AUFS_FS ++choice ++ prompt "Maximum number of branches" ++ default AUFS_BRANCH_MAX_127 ++ help ++ Specifies the maximum number of branches (or member directories) ++ in a single aufs. The larger value consumes more system ++ resources and has a minor impact to performance. ++config AUFS_BRANCH_MAX_127 ++ bool "127" ++ help ++ Specifies the maximum number of branches (or member directories) ++ in a single aufs. The larger value consumes more system ++ resources and has a minor impact to performance. ++config AUFS_BRANCH_MAX_511 ++ bool "511" ++ help ++ Specifies the maximum number of branches (or member directories) ++ in a single aufs. The larger value consumes more system ++ resources and has a minor impact to performance. ++config AUFS_BRANCH_MAX_1023 ++ bool "1023" ++ help ++ Specifies the maximum number of branches (or member directories) ++ in a single aufs. The larger value consumes more system ++ resources and has a minor impact to performance. ++config AUFS_BRANCH_MAX_32767 ++ bool "32767" ++ help ++ Specifies the maximum number of branches (or member directories) ++ in a single aufs. The larger value consumes more system ++ resources and has a minor impact to performance. ++endchoice ++ ++config AUFS_SBILIST ++ bool ++ depends on AUFS_MAGIC_SYSRQ || PROC_FS ++ default y ++ help ++ Automatic configuration for internal use. ++ When aufs supports Magic SysRq or /proc, enabled automatically. ++ ++config AUFS_HNOTIFY ++ bool "Detect direct branch access (bypassing aufs)" ++ help ++ If you want to modify files on branches directly, eg. bypassing aufs, ++ and want aufs to detect the changes of them fully, then enable this ++ option and use 'udba=notify' mount option. ++ Currently there is only one available configuration, "fsnotify". ++ It will have a negative impact to the performance. ++ See detail in aufs.5. ++ ++choice ++ prompt "method" if AUFS_HNOTIFY ++ default AUFS_HFSNOTIFY ++config AUFS_HFSNOTIFY ++ bool "fsnotify" ++ select FSNOTIFY ++endchoice ++ ++config AUFS_EXPORT ++ bool "NFS-exportable aufs" ++ depends on EXPORTFS = y ++ help ++ If you want to export your mounted aufs via NFS, then enable this ++ option. There are several requirements for this configuration. ++ See detail in aufs.5. ++ ++config AUFS_INO_T_64 ++ bool ++ depends on AUFS_EXPORT ++ depends on 64BIT && !(ALPHA || S390) ++ default y ++ help ++ Automatic configuration for internal use. ++ /* typedef unsigned long/int __kernel_ino_t */ ++ /* alpha and s390x are int */ ++ ++config AUFS_XATTR ++ bool "support for XATTR/EA (including Security Labels)" ++ help ++ If your branch fs supports XATTR/EA and you want to make them ++ available in aufs too, then enable this opsion and specify the ++ branch attributes for EA. ++ See detail in aufs.5. ++ ++config AUFS_FHSM ++ bool "File-based Hierarchical Storage Management" ++ help ++ Hierarchical Storage Management (or HSM) is a well-known feature ++ in the storage world. Aufs provides this feature as file-based. ++ with multiple branches. ++ These multiple branches are prioritized, ie. the topmost one ++ should be the fastest drive and be used heavily. ++ ++config AUFS_RDU ++ bool "Readdir in userspace" ++ help ++ Aufs has two methods to provide a merged view for a directory, ++ by a user-space library and by kernel-space natively. The latter ++ is always enabled but sometimes large and slow. ++ If you enable this option, install the library in aufs2-util ++ package, and set some environment variables for your readdir(3), ++ then the work will be handled in user-space which generally ++ shows better performance in most cases. ++ See detail in aufs.5. ++ ++config AUFS_DIRREN ++ bool "Workaround for rename(2)-ing a directory" ++ help ++ By default, aufs returns EXDEV error in renameing a dir who has ++ his child on the lower branch, since it is a bad idea to issue ++ rename(2) internally for every lower branch. But user may not ++ accept this behaviour. So here is a workaround to allow such ++ rename(2) and store some extra infromation on the writable ++ branch. Obviously this costs high (and I don't like it). ++ To use this feature, you need to enable this configuration AND ++ to specify the mount option `dirren.' ++ See details in aufs.5 and the design documents. ++ ++config AUFS_SHWH ++ bool "Show whiteouts" ++ help ++ If you want to make the whiteouts in aufs visible, then enable ++ this option and specify 'shwh' mount option. Although it may ++ sounds like philosophy or something, but in technically it ++ simply shows the name of whiteout with keeping its behaviour. ++ ++config AUFS_BR_RAMFS ++ bool "Ramfs (initramfs/rootfs) as an aufs branch" ++ help ++ If you want to use ramfs as an aufs branch fs, then enable this ++ option. Generally tmpfs is recommended. ++ Aufs prohibited them to be a branch fs by default, because ++ initramfs becomes unusable after switch_root or something ++ generally. If you sets initramfs as an aufs branch and boot your ++ system by switch_root, you will meet a problem easily since the ++ files in initramfs may be inaccessible. ++ Unless you are going to use ramfs as an aufs branch fs without ++ switch_root or something, leave it N. ++ ++config AUFS_BR_FUSE ++ bool "Fuse fs as an aufs branch" ++ depends on FUSE_FS ++ select AUFS_POLL ++ help ++ If you want to use fuse-based userspace filesystem as an aufs ++ branch fs, then enable this option. ++ It implements the internal poll(2) operation which is ++ implemented by fuse only (curretnly). ++ ++config AUFS_POLL ++ bool ++ help ++ Automatic configuration for internal use. ++ ++config AUFS_BR_HFSPLUS ++ bool "Hfsplus as an aufs branch" ++ depends on HFSPLUS_FS ++ default y ++ help ++ If you want to use hfsplus fs as an aufs branch fs, then enable ++ this option. This option introduces a small overhead at ++ copying-up a file on hfsplus. ++ ++config AUFS_BDEV_LOOP ++ bool ++ depends on BLK_DEV_LOOP ++ default y ++ help ++ Automatic configuration for internal use. ++ Convert =[ym] into =y. ++ ++config AUFS_DEBUG ++ bool "Debug aufs" ++ help ++ Enable this to compile aufs internal debug code. ++ It will have a negative impact to the performance. ++ ++config AUFS_MAGIC_SYSRQ ++ bool ++ depends on AUFS_DEBUG && MAGIC_SYSRQ ++ default y ++ help ++ Automatic configuration for internal use. ++ When aufs supports Magic SysRq, enabled automatically. ++endif +diff -Nurp linux-5.4/fs/aufs/lcnt.h linux-5.4-aufs/fs/aufs/lcnt.h +--- linux-5.4/fs/aufs/lcnt.h 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/lcnt.h 2019-11-28 01:25:59.066925618 +0200 +@@ -0,0 +1,173 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2018-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * simple long counter wrapper ++ */ ++ ++#ifndef __AUFS_LCNT_H__ ++#define __AUFS_LCNT_H__ ++ ++#ifdef __KERNEL__ ++ ++#include "debug.h" ++ ++#define AuLCntATOMIC 1 ++#define AuLCntPCPUCNT 2 ++/* ++ * why does percpu_refcount require extra synchronize_rcu()s in ++ * au_br_do_free() ++ */ ++#define AuLCntPCPUREF 3 ++ ++/* #define AuLCntChosen AuLCntATOMIC */ ++#define AuLCntChosen AuLCntPCPUCNT ++/* #define AuLCntChosen AuLCntPCPUREF */ ++ ++#if AuLCntChosen == AuLCntATOMIC ++#include ++ ++typedef atomic_long_t au_lcnt_t; ++ ++static inline int au_lcnt_init(au_lcnt_t *cnt, void *release __maybe_unused) ++{ ++ atomic_long_set(cnt, 0); ++ return 0; ++} ++ ++static inline void au_lcnt_wait_for_fin(au_lcnt_t *cnt __maybe_unused) ++{ ++ /* empty */ ++} ++ ++static inline void au_lcnt_fin(au_lcnt_t *cnt __maybe_unused, ++ int do_sync __maybe_unused) ++{ ++ /* empty */ ++} ++ ++static inline void au_lcnt_inc(au_lcnt_t *cnt) ++{ ++ atomic_long_inc(cnt); ++} ++ ++static inline void au_lcnt_dec(au_lcnt_t *cnt) ++{ ++ atomic_long_dec(cnt); ++} ++ ++static inline long au_lcnt_read(au_lcnt_t *cnt, int do_rev __maybe_unused) ++{ ++ return atomic_long_read(cnt); ++} ++#endif ++ ++#if AuLCntChosen == AuLCntPCPUCNT ++#include ++ ++typedef struct percpu_counter au_lcnt_t; ++ ++static inline int au_lcnt_init(au_lcnt_t *cnt, void *release __maybe_unused) ++{ ++ return percpu_counter_init(cnt, 0, GFP_NOFS); ++} ++ ++static inline void au_lcnt_wait_for_fin(au_lcnt_t *cnt __maybe_unused) ++{ ++ /* empty */ ++} ++ ++static inline void au_lcnt_fin(au_lcnt_t *cnt, int do_sync __maybe_unused) ++{ ++ percpu_counter_destroy(cnt); ++} ++ ++static inline void au_lcnt_inc(au_lcnt_t *cnt) ++{ ++ percpu_counter_inc(cnt); ++} ++ ++static inline void au_lcnt_dec(au_lcnt_t *cnt) ++{ ++ percpu_counter_dec(cnt); ++} ++ ++static inline long au_lcnt_read(au_lcnt_t *cnt, int do_rev __maybe_unused) ++{ ++ s64 n; ++ ++ n = percpu_counter_sum(cnt); ++ BUG_ON(n < 0); ++ if (LONG_MAX != LLONG_MAX ++ && n > LONG_MAX) ++ AuWarn1("%s\n", "wrap-around"); ++ ++ return n; ++} ++#endif ++ ++#if AuLCntChosen == AuLCntPCPUREF ++#include ++ ++typedef struct percpu_ref au_lcnt_t; ++ ++static inline int au_lcnt_init(au_lcnt_t *cnt, percpu_ref_func_t *release) ++{ ++ if (!release) ++ release = percpu_ref_exit; ++ return percpu_ref_init(cnt, release, /*percpu mode*/0, GFP_NOFS); ++} ++ ++static inline void au_lcnt_wait_for_fin(au_lcnt_t *cnt __maybe_unused) ++{ ++ synchronize_rcu(); ++} ++ ++static inline void au_lcnt_fin(au_lcnt_t *cnt, int do_sync) ++{ ++ percpu_ref_kill(cnt); ++ if (do_sync) ++ au_lcnt_wait_for_fin(cnt); ++} ++ ++static inline void au_lcnt_inc(au_lcnt_t *cnt) ++{ ++ percpu_ref_get(cnt); ++} ++ ++static inline void au_lcnt_dec(au_lcnt_t *cnt) ++{ ++ percpu_ref_put(cnt); ++} ++ ++/* ++ * avoid calling this func as possible. ++ */ ++static inline long au_lcnt_read(au_lcnt_t *cnt, int do_rev) ++{ ++ long l; ++ ++ percpu_ref_switch_to_atomic_sync(cnt); ++ l = atomic_long_read(&cnt->count); ++ if (do_rev) ++ percpu_ref_switch_to_percpu(cnt); ++ ++ /* percpu_ref is initialized by 1 instead of 0 */ ++ return l - 1; ++} ++#endif ++ ++#ifdef CONFIG_AUFS_DEBUG ++#define AuLCntZero(val) do { \ ++ long l = val; \ ++ if (l) \ ++ AuDbg("%s = %ld\n", #val, l); \ ++} while (0) ++#else ++#define AuLCntZero(val) do {} while (0) ++#endif ++ ++#endif /* __KERNEL__ */ ++#endif /* __AUFS_LCNT_H__ */ +diff -Nurp linux-5.4/fs/aufs/loop.c linux-5.4-aufs/fs/aufs/loop.c +--- linux-5.4/fs/aufs/loop.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/loop.c 2019-11-28 01:25:59.066925618 +0200 +@@ -0,0 +1,135 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * support for loopback block device as a branch ++ */ ++ ++#include "aufs.h" ++ ++/* added into drivers/block/loop.c */ ++static struct file *(*backing_file_func)(struct super_block *sb); ++ ++/* ++ * test if two lower dentries have overlapping branches. ++ */ ++int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding) ++{ ++ struct super_block *h_sb; ++ struct file *backing_file; ++ ++ if (unlikely(!backing_file_func)) { ++ /* don't load "loop" module here */ ++ backing_file_func = symbol_get(loop_backing_file); ++ if (unlikely(!backing_file_func)) ++ /* "loop" module is not loaded */ ++ return 0; ++ } ++ ++ h_sb = h_adding->d_sb; ++ backing_file = backing_file_func(h_sb); ++ if (!backing_file) ++ return 0; ++ ++ h_adding = backing_file->f_path.dentry; ++ /* ++ * h_adding can be local NFS. ++ * in this case aufs cannot detect the loop. ++ */ ++ if (unlikely(h_adding->d_sb == sb)) ++ return 1; ++ return !!au_test_subdir(h_adding, sb->s_root); ++} ++ ++/* true if a kernel thread named 'loop[0-9].*' accesses a file */ ++int au_test_loopback_kthread(void) ++{ ++ int ret; ++ struct task_struct *tsk = current; ++ char c, comm[sizeof(tsk->comm)]; ++ ++ ret = 0; ++ if (tsk->flags & PF_KTHREAD) { ++ get_task_comm(comm, tsk); ++ c = comm[4]; ++ ret = ('0' <= c && c <= '9' ++ && !strncmp(comm, "loop", 4)); ++ } ++ ++ return ret; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++#define au_warn_loopback_step 16 ++static int au_warn_loopback_nelem = au_warn_loopback_step; ++static unsigned long *au_warn_loopback_array; ++ ++void au_warn_loopback(struct super_block *h_sb) ++{ ++ int i, new_nelem; ++ unsigned long *a, magic; ++ static DEFINE_SPINLOCK(spin); ++ ++ magic = h_sb->s_magic; ++ spin_lock(&spin); ++ a = au_warn_loopback_array; ++ for (i = 0; i < au_warn_loopback_nelem && *a; i++) ++ if (a[i] == magic) { ++ spin_unlock(&spin); ++ return; ++ } ++ ++ /* h_sb is new to us, print it */ ++ if (i < au_warn_loopback_nelem) { ++ a[i] = magic; ++ goto pr; ++ } ++ ++ /* expand the array */ ++ new_nelem = au_warn_loopback_nelem + au_warn_loopback_step; ++ a = au_kzrealloc(au_warn_loopback_array, ++ au_warn_loopback_nelem * sizeof(unsigned long), ++ new_nelem * sizeof(unsigned long), GFP_ATOMIC, ++ /*may_shrink*/0); ++ if (a) { ++ au_warn_loopback_nelem = new_nelem; ++ au_warn_loopback_array = a; ++ a[i] = magic; ++ goto pr; ++ } ++ ++ spin_unlock(&spin); ++ AuWarn1("realloc failed, ignored\n"); ++ return; ++ ++pr: ++ spin_unlock(&spin); ++ pr_warn("you may want to try another patch for loopback file " ++ "on %s(0x%lx) branch\n", au_sbtype(h_sb), magic); ++} ++ ++int au_loopback_init(void) ++{ ++ int err; ++ struct super_block *sb __maybe_unused; ++ ++ BUILD_BUG_ON(sizeof(sb->s_magic) != sizeof(*au_warn_loopback_array)); ++ ++ err = 0; ++ au_warn_loopback_array = kcalloc(au_warn_loopback_step, ++ sizeof(unsigned long), GFP_NOFS); ++ if (unlikely(!au_warn_loopback_array)) ++ err = -ENOMEM; ++ ++ return err; ++} ++ ++void au_loopback_fin(void) ++{ ++ if (backing_file_func) ++ symbol_put(loop_backing_file); ++ au_kfree_try_rcu(au_warn_loopback_array); ++} +diff -Nurp linux-5.4/fs/aufs/loop.h linux-5.4-aufs/fs/aufs/loop.h +--- linux-5.4/fs/aufs/loop.h 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/loop.h 2019-11-28 01:25:59.066925618 +0200 +@@ -0,0 +1,42 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * support for loopback mount as a branch ++ */ ++ ++#ifndef __AUFS_LOOP_H__ ++#define __AUFS_LOOP_H__ ++ ++#ifdef __KERNEL__ ++ ++struct dentry; ++struct super_block; ++ ++#ifdef CONFIG_AUFS_BDEV_LOOP ++/* drivers/block/loop.c */ ++struct file *loop_backing_file(struct super_block *sb); ++ ++/* loop.c */ ++int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding); ++int au_test_loopback_kthread(void); ++void au_warn_loopback(struct super_block *h_sb); ++ ++int au_loopback_init(void); ++void au_loopback_fin(void); ++#else ++AuStub(struct file *, loop_backing_file, return NULL, struct super_block *sb) ++ ++AuStubInt0(au_test_loopback_overlap, struct super_block *sb, ++ struct dentry *h_adding) ++AuStubInt0(au_test_loopback_kthread, void) ++AuStubVoid(au_warn_loopback, struct super_block *h_sb) ++ ++AuStubInt0(au_loopback_init, void) ++AuStubVoid(au_loopback_fin, void) ++#endif /* BLK_DEV_LOOP */ ++ ++#endif /* __KERNEL__ */ ++#endif /* __AUFS_LOOP_H__ */ +diff -Nurp linux-5.4/fs/aufs/magic.mk linux-5.4-aufs/fs/aufs/magic.mk +--- linux-5.4/fs/aufs/magic.mk 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/magic.mk 2019-11-28 01:25:59.066925618 +0200 +@@ -0,0 +1,31 @@ ++# SPDX-License-Identifier: GPL-2.0 ++ ++# defined in ${srctree}/fs/fuse/inode.c ++# tristate ++ifdef CONFIG_FUSE_FS ++ccflags-y += -DFUSE_SUPER_MAGIC=0x65735546 ++endif ++ ++# defined in ${srctree}/fs/xfs/xfs_sb.h ++# tristate ++ifdef CONFIG_XFS_FS ++ccflags-y += -DXFS_SB_MAGIC=0x58465342 ++endif ++ ++# defined in ${srctree}/fs/configfs/mount.c ++# tristate ++ifdef CONFIG_CONFIGFS_FS ++ccflags-y += -DCONFIGFS_MAGIC=0x62656570 ++endif ++ ++# defined in ${srctree}/fs/ubifs/ubifs.h ++# tristate ++ifdef CONFIG_UBIFS_FS ++ccflags-y += -DUBIFS_SUPER_MAGIC=0x24051905 ++endif ++ ++# defined in ${srctree}/fs/hfsplus/hfsplus_raw.h ++# tristate ++ifdef CONFIG_HFSPLUS_FS ++ccflags-y += -DHFSPLUS_SUPER_MAGIC=0x482b ++endif +diff -Nurp linux-5.4/fs/aufs/Makefile linux-5.4-aufs/fs/aufs/Makefile +--- linux-5.4/fs/aufs/Makefile 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/Makefile 2019-11-28 01:25:59.062925618 +0200 +@@ -0,0 +1,39 @@ ++# SPDX-License-Identifier: GPL-2.0 ++ ++include ${srctree}/${src}/magic.mk ++-include ${srctree}/${src}/priv_def.mk ++ ++# cf. include/linux/kernel.h ++# enable pr_debug ++ccflags-y += -DDEBUG ++# sparse requires the full pathname ++ccflags-y += -include ${srctree}/include/uapi/linux/aufs_type.h ++ ++obj-$(CONFIG_AUFS_FS) += aufs.o ++aufs-y := module.o sbinfo.o super.o branch.o xino.o sysaufs.o opts.o \ ++ wkq.o vfsub.o dcsub.o \ ++ cpup.o whout.o wbr_policy.o \ ++ dinfo.o dentry.o \ ++ dynop.o \ ++ finfo.o file.o f_op.o \ ++ dir.o vdir.o \ ++ iinfo.o inode.o i_op.o i_op_add.o i_op_del.o i_op_ren.o \ ++ mvdown.o ioctl.o ++ ++# all are boolean ++aufs-$(CONFIG_PROC_FS) += procfs.o plink.o ++aufs-$(CONFIG_SYSFS) += sysfs.o ++aufs-$(CONFIG_DEBUG_FS) += dbgaufs.o ++aufs-$(CONFIG_AUFS_BDEV_LOOP) += loop.o ++aufs-$(CONFIG_AUFS_HNOTIFY) += hnotify.o ++aufs-$(CONFIG_AUFS_HFSNOTIFY) += hfsnotify.o ++aufs-$(CONFIG_AUFS_EXPORT) += export.o ++aufs-$(CONFIG_AUFS_XATTR) += xattr.o ++aufs-$(CONFIG_FS_POSIX_ACL) += posix_acl.o ++aufs-$(CONFIG_AUFS_DIRREN) += dirren.o ++aufs-$(CONFIG_AUFS_FHSM) += fhsm.o ++aufs-$(CONFIG_AUFS_POLL) += poll.o ++aufs-$(CONFIG_AUFS_RDU) += rdu.o ++aufs-$(CONFIG_AUFS_BR_HFSPLUS) += hfsplus.o ++aufs-$(CONFIG_AUFS_DEBUG) += debug.o ++aufs-$(CONFIG_AUFS_MAGIC_SYSRQ) += sysrq.o +diff -Nurp linux-5.4/fs/aufs/module.c linux-5.4-aufs/fs/aufs/module.c +--- linux-5.4/fs/aufs/module.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/module.c 2019-11-28 01:25:59.066925618 +0200 +@@ -0,0 +1,259 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * module global variables and operations ++ */ ++ ++#include ++#include ++#include "aufs.h" ++ ++/* shrinkable realloc */ ++void *au_krealloc(void *p, unsigned int new_sz, gfp_t gfp, int may_shrink) ++{ ++ size_t sz; ++ int diff; ++ ++ sz = 0; ++ diff = -1; ++ if (p) { ++#if 0 /* unused */ ++ if (!new_sz) { ++ au_kfree_rcu(p); ++ p = NULL; ++ goto out; ++ } ++#else ++ AuDebugOn(!new_sz); ++#endif ++ sz = ksize(p); ++ diff = au_kmidx_sub(sz, new_sz); ++ } ++ if (sz && !diff) ++ goto out; ++ ++ if (sz < new_sz) ++ /* expand or SLOB */ ++ p = krealloc(p, new_sz, gfp); ++ else if (new_sz < sz && may_shrink) { ++ /* shrink */ ++ void *q; ++ ++ q = kmalloc(new_sz, gfp); ++ if (q) { ++ if (p) { ++ memcpy(q, p, new_sz); ++ au_kfree_try_rcu(p); ++ } ++ p = q; ++ } else ++ p = NULL; ++ } ++ ++out: ++ return p; ++} ++ ++void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp, ++ int may_shrink) ++{ ++ p = au_krealloc(p, new_sz, gfp, may_shrink); ++ if (p && new_sz > nused) ++ memset(p + nused, 0, new_sz - nused); ++ return p; ++} ++ ++/* ---------------------------------------------------------------------- */ ++/* ++ * aufs caches ++ */ ++struct kmem_cache *au_cache[AuCache_Last]; ++ ++static void au_cache_fin(void) ++{ ++ int i; ++ ++ /* ++ * Make sure all delayed rcu free inodes are flushed before we ++ * destroy cache. ++ */ ++ rcu_barrier(); ++ ++ /* excluding AuCache_HNOTIFY */ ++ BUILD_BUG_ON(AuCache_HNOTIFY + 1 != AuCache_Last); ++ for (i = 0; i < AuCache_HNOTIFY; i++) { ++ kmem_cache_destroy(au_cache[i]); ++ au_cache[i] = NULL; ++ } ++} ++ ++static int __init au_cache_init(void) ++{ ++ au_cache[AuCache_DINFO] = AuCacheCtor(au_dinfo, au_di_init_once); ++ if (au_cache[AuCache_DINFO]) ++ /* SLAB_DESTROY_BY_RCU */ ++ au_cache[AuCache_ICNTNR] = AuCacheCtor(au_icntnr, ++ au_icntnr_init_once); ++ if (au_cache[AuCache_ICNTNR]) ++ au_cache[AuCache_FINFO] = AuCacheCtor(au_finfo, ++ au_fi_init_once); ++ if (au_cache[AuCache_FINFO]) ++ au_cache[AuCache_VDIR] = AuCache(au_vdir); ++ if (au_cache[AuCache_VDIR]) ++ au_cache[AuCache_DEHSTR] = AuCache(au_vdir_dehstr); ++ if (au_cache[AuCache_DEHSTR]) ++ return 0; ++ ++ au_cache_fin(); ++ return -ENOMEM; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++int au_dir_roflags; ++ ++#ifdef CONFIG_AUFS_SBILIST ++/* ++ * iterate_supers_type() doesn't protect us from ++ * remounting (branch management) ++ */ ++struct hlist_bl_head au_sbilist; ++#endif ++ ++/* ++ * functions for module interface. ++ */ ++MODULE_LICENSE("GPL"); ++/* MODULE_LICENSE("GPL v2"); */ ++MODULE_AUTHOR("Junjiro R. Okajima "); ++MODULE_DESCRIPTION(AUFS_NAME ++ " -- Advanced multi layered unification filesystem"); ++MODULE_VERSION(AUFS_VERSION); ++ ++/* this module parameter has no meaning when SYSFS is disabled */ ++int sysaufs_brs = 1; ++MODULE_PARM_DESC(brs, "use /fs/aufs/si_*/brN"); ++module_param_named(brs, sysaufs_brs, int, 0444); ++ ++/* this module parameter has no meaning when USER_NS is disabled */ ++bool au_userns; ++MODULE_PARM_DESC(allow_userns, "allow unprivileged to mount under userns"); ++module_param_named(allow_userns, au_userns, bool, 0444); ++ ++/* ---------------------------------------------------------------------- */ ++ ++static char au_esc_chars[0x20 + 3]; /* 0x01-0x20, backslash, del, and NULL */ ++ ++int au_seq_path(struct seq_file *seq, struct path *path) ++{ ++ int err; ++ ++ err = seq_path(seq, path, au_esc_chars); ++ if (err >= 0) ++ err = 0; ++ else ++ err = -ENOMEM; ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int __init aufs_init(void) ++{ ++ int err, i; ++ char *p; ++ ++ p = au_esc_chars; ++ for (i = 1; i <= ' '; i++) ++ *p++ = i; ++ *p++ = '\\'; ++ *p++ = '\x7f'; ++ *p = 0; ++ ++ au_dir_roflags = au_file_roflags(O_DIRECTORY | O_LARGEFILE); ++ ++ memcpy(aufs_iop_nogetattr, aufs_iop, sizeof(aufs_iop)); ++ for (i = 0; i < AuIop_Last; i++) ++ aufs_iop_nogetattr[i].getattr = NULL; ++ ++ memset(au_cache, 0, sizeof(au_cache)); /* including hnotify */ ++ ++ au_sbilist_init(); ++ sysaufs_brs_init(); ++ au_debug_init(); ++ au_dy_init(); ++ err = sysaufs_init(); ++ if (unlikely(err)) ++ goto out; ++ err = dbgaufs_init(); ++ if (unlikely(err)) ++ goto out_sysaufs; ++ err = au_procfs_init(); ++ if (unlikely(err)) ++ goto out_dbgaufs; ++ err = au_wkq_init(); ++ if (unlikely(err)) ++ goto out_procfs; ++ err = au_loopback_init(); ++ if (unlikely(err)) ++ goto out_wkq; ++ err = au_hnotify_init(); ++ if (unlikely(err)) ++ goto out_loopback; ++ err = au_sysrq_init(); ++ if (unlikely(err)) ++ goto out_hin; ++ err = au_cache_init(); ++ if (unlikely(err)) ++ goto out_sysrq; ++ ++ aufs_fs_type.fs_flags |= au_userns ? FS_USERNS_MOUNT : 0; ++ err = register_filesystem(&aufs_fs_type); ++ if (unlikely(err)) ++ goto out_cache; ++ ++ /* since we define pr_fmt, call printk directly */ ++ printk(KERN_INFO AUFS_NAME " " AUFS_VERSION "\n"); ++ goto out; /* success */ ++ ++out_cache: ++ au_cache_fin(); ++out_sysrq: ++ au_sysrq_fin(); ++out_hin: ++ au_hnotify_fin(); ++out_loopback: ++ au_loopback_fin(); ++out_wkq: ++ au_wkq_fin(); ++out_procfs: ++ au_procfs_fin(); ++out_dbgaufs: ++ dbgaufs_fin(); ++out_sysaufs: ++ sysaufs_fin(); ++ au_dy_fin(); ++out: ++ return err; ++} ++ ++static void __exit aufs_exit(void) ++{ ++ unregister_filesystem(&aufs_fs_type); ++ au_cache_fin(); ++ au_sysrq_fin(); ++ au_hnotify_fin(); ++ au_loopback_fin(); ++ au_wkq_fin(); ++ au_procfs_fin(); ++ dbgaufs_fin(); ++ sysaufs_fin(); ++ au_dy_fin(); ++} ++ ++module_init(aufs_init); ++module_exit(aufs_exit); +diff -Nurp linux-5.4/fs/aufs/module.h linux-5.4-aufs/fs/aufs/module.h +--- linux-5.4/fs/aufs/module.h 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/module.h 2019-11-28 01:25:59.066925618 +0200 +@@ -0,0 +1,153 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * module initialization and module-global ++ */ ++ ++#ifndef __AUFS_MODULE_H__ ++#define __AUFS_MODULE_H__ ++ ++#ifdef __KERNEL__ ++ ++#include ++#include "debug.h" ++#include "dentry.h" ++#include "dir.h" ++#include "file.h" ++#include "inode.h" ++ ++struct path; ++struct seq_file; ++ ++/* module parameters */ ++extern int sysaufs_brs; ++extern bool au_userns; ++ ++/* ---------------------------------------------------------------------- */ ++ ++extern int au_dir_roflags; ++ ++void *au_krealloc(void *p, unsigned int new_sz, gfp_t gfp, int may_shrink); ++void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp, ++ int may_shrink); ++ ++/* ++ * Comparing the size of the object with sizeof(struct rcu_head) ++ * case 1: object is always larger ++ * --> au_kfree_rcu() or au_kfree_do_rcu() ++ * case 2: object is always smaller ++ * --> au_kfree_small() ++ * case 3: object can be any size ++ * --> au_kfree_try_rcu() ++ */ ++ ++static inline void au_kfree_do_rcu(const void *p) ++{ ++ struct { ++ struct rcu_head rcu; ++ } *a = (void *)p; ++ ++ kfree_rcu(a, rcu); ++} ++ ++#define au_kfree_rcu(_p) do { \ ++ typeof(_p) p = (_p); \ ++ BUILD_BUG_ON(sizeof(*p) < sizeof(struct rcu_head)); \ ++ if (p) \ ++ au_kfree_do_rcu(p); \ ++ } while (0) ++ ++#define au_kfree_do_sz_test(sz) (sz >= sizeof(struct rcu_head)) ++#define au_kfree_sz_test(p) (p && au_kfree_do_sz_test(ksize(p))) ++ ++static inline void au_kfree_try_rcu(const void *p) ++{ ++ if (!p) ++ return; ++ if (au_kfree_sz_test(p)) ++ au_kfree_do_rcu(p); ++ else ++ kfree(p); ++} ++ ++static inline void au_kfree_small(const void *p) ++{ ++ if (!p) ++ return; ++ AuDebugOn(au_kfree_sz_test(p)); ++ kfree(p); ++} ++ ++static inline int au_kmidx_sub(size_t sz, size_t new_sz) ++{ ++#ifndef CONFIG_SLOB ++ return kmalloc_index(sz) - kmalloc_index(new_sz); ++#else ++ return -1; /* SLOB is untested */ ++#endif ++} ++ ++int au_seq_path(struct seq_file *seq, struct path *path); ++ ++#ifdef CONFIG_PROC_FS ++/* procfs.c */ ++int __init au_procfs_init(void); ++void au_procfs_fin(void); ++#else ++AuStubInt0(au_procfs_init, void); ++AuStubVoid(au_procfs_fin, void); ++#endif ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* kmem cache */ ++enum { ++ AuCache_DINFO, ++ AuCache_ICNTNR, ++ AuCache_FINFO, ++ AuCache_VDIR, ++ AuCache_DEHSTR, ++ AuCache_HNOTIFY, /* must be last */ ++ AuCache_Last ++}; ++ ++extern struct kmem_cache *au_cache[AuCache_Last]; ++ ++#define AuCacheFlags (SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD) ++#define AuCache(type) KMEM_CACHE(type, AuCacheFlags) ++#define AuCacheCtor(type, ctor) \ ++ kmem_cache_create(#type, sizeof(struct type), \ ++ __alignof__(struct type), AuCacheFlags, ctor) ++ ++#define AuCacheFuncs(name, index) \ ++ static inline struct au_##name *au_cache_alloc_##name(void) \ ++ { return kmem_cache_alloc(au_cache[AuCache_##index], GFP_NOFS); } \ ++ static inline void au_cache_free_##name##_norcu(struct au_##name *p) \ ++ { kmem_cache_free(au_cache[AuCache_##index], p); } \ ++ \ ++ static inline void au_cache_free_##name##_rcu_cb(struct rcu_head *rcu) \ ++ { void *p = rcu; \ ++ p -= offsetof(struct au_##name, rcu); \ ++ kmem_cache_free(au_cache[AuCache_##index], p); } \ ++ static inline void au_cache_free_##name##_rcu(struct au_##name *p) \ ++ { BUILD_BUG_ON(sizeof(struct au_##name) < sizeof(struct rcu_head)); \ ++ call_rcu(&p->rcu, au_cache_free_##name##_rcu_cb); } \ ++ \ ++ static inline void au_cache_free_##name(struct au_##name *p) \ ++ { /* au_cache_free_##name##_norcu(p); */ \ ++ au_cache_free_##name##_rcu(p); } ++ ++AuCacheFuncs(dinfo, DINFO); ++AuCacheFuncs(icntnr, ICNTNR); ++AuCacheFuncs(finfo, FINFO); ++AuCacheFuncs(vdir, VDIR); ++AuCacheFuncs(vdir_dehstr, DEHSTR); ++#ifdef CONFIG_AUFS_HNOTIFY ++AuCacheFuncs(hnotify, HNOTIFY); ++#endif ++ ++#endif /* __KERNEL__ */ ++#endif /* __AUFS_MODULE_H__ */ +diff -Nurp linux-5.4/fs/aufs/mvdown.c linux-5.4-aufs/fs/aufs/mvdown.c +--- linux-5.4/fs/aufs/mvdown.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/mvdown.c 2019-11-28 01:25:59.067925618 +0200 +@@ -0,0 +1,693 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2011-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * move-down, opposite of copy-up ++ */ ++ ++#include "aufs.h" ++ ++struct au_mvd_args { ++ struct { ++ struct super_block *h_sb; ++ struct dentry *h_parent; ++ struct au_hinode *hdir; ++ struct inode *h_dir, *h_inode; ++ struct au_pin pin; ++ } info[AUFS_MVDOWN_NARRAY]; ++ ++ struct aufs_mvdown mvdown; ++ struct dentry *dentry, *parent; ++ struct inode *inode, *dir; ++ struct super_block *sb; ++ aufs_bindex_t bopq, bwh, bfound; ++ unsigned char rename_lock; ++}; ++ ++#define mvd_errno mvdown.au_errno ++#define mvd_bsrc mvdown.stbr[AUFS_MVDOWN_UPPER].bindex ++#define mvd_src_brid mvdown.stbr[AUFS_MVDOWN_UPPER].brid ++#define mvd_bdst mvdown.stbr[AUFS_MVDOWN_LOWER].bindex ++#define mvd_dst_brid mvdown.stbr[AUFS_MVDOWN_LOWER].brid ++ ++#define mvd_h_src_sb info[AUFS_MVDOWN_UPPER].h_sb ++#define mvd_h_src_parent info[AUFS_MVDOWN_UPPER].h_parent ++#define mvd_hdir_src info[AUFS_MVDOWN_UPPER].hdir ++#define mvd_h_src_dir info[AUFS_MVDOWN_UPPER].h_dir ++#define mvd_h_src_inode info[AUFS_MVDOWN_UPPER].h_inode ++#define mvd_pin_src info[AUFS_MVDOWN_UPPER].pin ++ ++#define mvd_h_dst_sb info[AUFS_MVDOWN_LOWER].h_sb ++#define mvd_h_dst_parent info[AUFS_MVDOWN_LOWER].h_parent ++#define mvd_hdir_dst info[AUFS_MVDOWN_LOWER].hdir ++#define mvd_h_dst_dir info[AUFS_MVDOWN_LOWER].h_dir ++#define mvd_h_dst_inode info[AUFS_MVDOWN_LOWER].h_inode ++#define mvd_pin_dst info[AUFS_MVDOWN_LOWER].pin ++ ++#define AU_MVD_PR(flag, ...) do { \ ++ if (flag) \ ++ pr_err(__VA_ARGS__); \ ++ } while (0) ++ ++static int find_lower_writable(struct au_mvd_args *a) ++{ ++ struct super_block *sb; ++ aufs_bindex_t bindex, bbot; ++ struct au_branch *br; ++ ++ sb = a->sb; ++ bindex = a->mvd_bsrc; ++ bbot = au_sbbot(sb); ++ if (a->mvdown.flags & AUFS_MVDOWN_FHSM_LOWER) ++ for (bindex++; bindex <= bbot; bindex++) { ++ br = au_sbr(sb, bindex); ++ if (au_br_fhsm(br->br_perm) ++ && !sb_rdonly(au_br_sb(br))) ++ return bindex; ++ } ++ else if (!(a->mvdown.flags & AUFS_MVDOWN_ROLOWER)) ++ for (bindex++; bindex <= bbot; bindex++) { ++ br = au_sbr(sb, bindex); ++ if (!au_br_rdonly(br)) ++ return bindex; ++ } ++ else ++ for (bindex++; bindex <= bbot; bindex++) { ++ br = au_sbr(sb, bindex); ++ if (!sb_rdonly(au_br_sb(br))) { ++ if (au_br_rdonly(br)) ++ a->mvdown.flags ++ |= AUFS_MVDOWN_ROLOWER_R; ++ return bindex; ++ } ++ } ++ ++ return -1; ++} ++ ++/* make the parent dir on bdst */ ++static int au_do_mkdir(const unsigned char dmsg, struct au_mvd_args *a) ++{ ++ int err; ++ ++ err = 0; ++ a->mvd_hdir_src = au_hi(a->dir, a->mvd_bsrc); ++ a->mvd_hdir_dst = au_hi(a->dir, a->mvd_bdst); ++ a->mvd_h_src_parent = au_h_dptr(a->parent, a->mvd_bsrc); ++ a->mvd_h_dst_parent = NULL; ++ if (au_dbbot(a->parent) >= a->mvd_bdst) ++ a->mvd_h_dst_parent = au_h_dptr(a->parent, a->mvd_bdst); ++ if (!a->mvd_h_dst_parent) { ++ err = au_cpdown_dirs(a->dentry, a->mvd_bdst); ++ if (unlikely(err)) { ++ AU_MVD_PR(dmsg, "cpdown_dirs failed\n"); ++ goto out; ++ } ++ a->mvd_h_dst_parent = au_h_dptr(a->parent, a->mvd_bdst); ++ } ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++/* lock them all */ ++static int au_do_lock(const unsigned char dmsg, struct au_mvd_args *a) ++{ ++ int err; ++ struct dentry *h_trap; ++ ++ a->mvd_h_src_sb = au_sbr_sb(a->sb, a->mvd_bsrc); ++ a->mvd_h_dst_sb = au_sbr_sb(a->sb, a->mvd_bdst); ++ err = au_pin(&a->mvd_pin_dst, a->dentry, a->mvd_bdst, ++ au_opt_udba(a->sb), ++ AuPin_MNT_WRITE | AuPin_DI_LOCKED); ++ AuTraceErr(err); ++ if (unlikely(err)) { ++ AU_MVD_PR(dmsg, "pin_dst failed\n"); ++ goto out; ++ } ++ ++ if (a->mvd_h_src_sb != a->mvd_h_dst_sb) { ++ a->rename_lock = 0; ++ au_pin_init(&a->mvd_pin_src, a->dentry, a->mvd_bsrc, ++ AuLsc_DI_PARENT, AuLsc_I_PARENT3, ++ au_opt_udba(a->sb), ++ AuPin_MNT_WRITE | AuPin_DI_LOCKED); ++ err = au_do_pin(&a->mvd_pin_src); ++ AuTraceErr(err); ++ a->mvd_h_src_dir = d_inode(a->mvd_h_src_parent); ++ if (unlikely(err)) { ++ AU_MVD_PR(dmsg, "pin_src failed\n"); ++ goto out_dst; ++ } ++ goto out; /* success */ ++ } ++ ++ a->rename_lock = 1; ++ au_pin_hdir_unlock(&a->mvd_pin_dst); ++ err = au_pin(&a->mvd_pin_src, a->dentry, a->mvd_bsrc, ++ au_opt_udba(a->sb), ++ AuPin_MNT_WRITE | AuPin_DI_LOCKED); ++ AuTraceErr(err); ++ a->mvd_h_src_dir = d_inode(a->mvd_h_src_parent); ++ if (unlikely(err)) { ++ AU_MVD_PR(dmsg, "pin_src failed\n"); ++ au_pin_hdir_lock(&a->mvd_pin_dst); ++ goto out_dst; ++ } ++ au_pin_hdir_unlock(&a->mvd_pin_src); ++ h_trap = vfsub_lock_rename(a->mvd_h_src_parent, a->mvd_hdir_src, ++ a->mvd_h_dst_parent, a->mvd_hdir_dst); ++ if (h_trap) { ++ err = (h_trap != a->mvd_h_src_parent); ++ if (err) ++ err = (h_trap != a->mvd_h_dst_parent); ++ } ++ BUG_ON(err); /* it should never happen */ ++ if (unlikely(a->mvd_h_src_dir != au_pinned_h_dir(&a->mvd_pin_src))) { ++ err = -EBUSY; ++ AuTraceErr(err); ++ vfsub_unlock_rename(a->mvd_h_src_parent, a->mvd_hdir_src, ++ a->mvd_h_dst_parent, a->mvd_hdir_dst); ++ au_pin_hdir_lock(&a->mvd_pin_src); ++ au_unpin(&a->mvd_pin_src); ++ au_pin_hdir_lock(&a->mvd_pin_dst); ++ goto out_dst; ++ } ++ goto out; /* success */ ++ ++out_dst: ++ au_unpin(&a->mvd_pin_dst); ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++static void au_do_unlock(const unsigned char dmsg, struct au_mvd_args *a) ++{ ++ if (!a->rename_lock) ++ au_unpin(&a->mvd_pin_src); ++ else { ++ vfsub_unlock_rename(a->mvd_h_src_parent, a->mvd_hdir_src, ++ a->mvd_h_dst_parent, a->mvd_hdir_dst); ++ au_pin_hdir_lock(&a->mvd_pin_src); ++ au_unpin(&a->mvd_pin_src); ++ au_pin_hdir_lock(&a->mvd_pin_dst); ++ } ++ au_unpin(&a->mvd_pin_dst); ++} ++ ++/* copy-down the file */ ++static int au_do_cpdown(const unsigned char dmsg, struct au_mvd_args *a) ++{ ++ int err; ++ struct au_cp_generic cpg = { ++ .dentry = a->dentry, ++ .bdst = a->mvd_bdst, ++ .bsrc = a->mvd_bsrc, ++ .len = -1, ++ .pin = &a->mvd_pin_dst, ++ .flags = AuCpup_DTIME | AuCpup_HOPEN ++ }; ++ ++ AuDbg("b%d, b%d\n", cpg.bsrc, cpg.bdst); ++ if (a->mvdown.flags & AUFS_MVDOWN_OWLOWER) ++ au_fset_cpup(cpg.flags, OVERWRITE); ++ if (a->mvdown.flags & AUFS_MVDOWN_ROLOWER) ++ au_fset_cpup(cpg.flags, RWDST); ++ err = au_sio_cpdown_simple(&cpg); ++ if (unlikely(err)) ++ AU_MVD_PR(dmsg, "cpdown failed\n"); ++ ++ AuTraceErr(err); ++ return err; ++} ++ ++/* ++ * unlink the whiteout on bdst if exist which may be created by UDBA while we ++ * were sleeping ++ */ ++static int au_do_unlink_wh(const unsigned char dmsg, struct au_mvd_args *a) ++{ ++ int err; ++ struct path h_path; ++ struct au_branch *br; ++ struct inode *delegated; ++ ++ br = au_sbr(a->sb, a->mvd_bdst); ++ h_path.dentry = au_wh_lkup(a->mvd_h_dst_parent, &a->dentry->d_name, br); ++ err = PTR_ERR(h_path.dentry); ++ if (IS_ERR(h_path.dentry)) { ++ AU_MVD_PR(dmsg, "wh_lkup failed\n"); ++ goto out; ++ } ++ ++ err = 0; ++ if (d_is_positive(h_path.dentry)) { ++ h_path.mnt = au_br_mnt(br); ++ delegated = NULL; ++ err = vfsub_unlink(d_inode(a->mvd_h_dst_parent), &h_path, ++ &delegated, /*force*/0); ++ if (unlikely(err == -EWOULDBLOCK)) { ++ pr_warn("cannot retry for NFSv4 delegation" ++ " for an internal unlink\n"); ++ iput(delegated); ++ } ++ if (unlikely(err)) ++ AU_MVD_PR(dmsg, "wh_unlink failed\n"); ++ } ++ dput(h_path.dentry); ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++/* ++ * unlink the topmost h_dentry ++ */ ++static int au_do_unlink(const unsigned char dmsg, struct au_mvd_args *a) ++{ ++ int err; ++ struct path h_path; ++ struct inode *delegated; ++ ++ h_path.mnt = au_sbr_mnt(a->sb, a->mvd_bsrc); ++ h_path.dentry = au_h_dptr(a->dentry, a->mvd_bsrc); ++ delegated = NULL; ++ err = vfsub_unlink(a->mvd_h_src_dir, &h_path, &delegated, /*force*/0); ++ if (unlikely(err == -EWOULDBLOCK)) { ++ pr_warn("cannot retry for NFSv4 delegation" ++ " for an internal unlink\n"); ++ iput(delegated); ++ } ++ if (unlikely(err)) ++ AU_MVD_PR(dmsg, "unlink failed\n"); ++ ++ AuTraceErr(err); ++ return err; ++} ++ ++/* Since mvdown succeeded, we ignore an error of this function */ ++static void au_do_stfs(const unsigned char dmsg, struct au_mvd_args *a) ++{ ++ int err; ++ struct au_branch *br; ++ ++ a->mvdown.flags |= AUFS_MVDOWN_STFS_FAILED; ++ br = au_sbr(a->sb, a->mvd_bsrc); ++ err = au_br_stfs(br, &a->mvdown.stbr[AUFS_MVDOWN_UPPER].stfs); ++ if (!err) { ++ br = au_sbr(a->sb, a->mvd_bdst); ++ a->mvdown.stbr[AUFS_MVDOWN_LOWER].brid = br->br_id; ++ err = au_br_stfs(br, &a->mvdown.stbr[AUFS_MVDOWN_LOWER].stfs); ++ } ++ if (!err) ++ a->mvdown.flags &= ~AUFS_MVDOWN_STFS_FAILED; ++ else ++ AU_MVD_PR(dmsg, "statfs failed (%d), ignored\n", err); ++} ++ ++/* ++ * copy-down the file and unlink the bsrc file. ++ * - unlink the bdst whout if exist ++ * - copy-down the file (with whtmp name and rename) ++ * - unlink the bsrc file ++ */ ++static int au_do_mvdown(const unsigned char dmsg, struct au_mvd_args *a) ++{ ++ int err; ++ ++ err = au_do_mkdir(dmsg, a); ++ if (!err) ++ err = au_do_lock(dmsg, a); ++ if (unlikely(err)) ++ goto out; ++ ++ /* ++ * do not revert the activities we made on bdst since they should be ++ * harmless in aufs. ++ */ ++ ++ err = au_do_cpdown(dmsg, a); ++ if (!err) ++ err = au_do_unlink_wh(dmsg, a); ++ if (!err && !(a->mvdown.flags & AUFS_MVDOWN_KUPPER)) ++ err = au_do_unlink(dmsg, a); ++ if (unlikely(err)) ++ goto out_unlock; ++ ++ AuDbg("%pd2, 0x%x, %d --> %d\n", ++ a->dentry, a->mvdown.flags, a->mvd_bsrc, a->mvd_bdst); ++ if (find_lower_writable(a) < 0) ++ a->mvdown.flags |= AUFS_MVDOWN_BOTTOM; ++ ++ if (a->mvdown.flags & AUFS_MVDOWN_STFS) ++ au_do_stfs(dmsg, a); ++ ++ /* maintain internal array */ ++ if (!(a->mvdown.flags & AUFS_MVDOWN_KUPPER)) { ++ au_set_h_dptr(a->dentry, a->mvd_bsrc, NULL); ++ au_set_dbtop(a->dentry, a->mvd_bdst); ++ au_set_h_iptr(a->inode, a->mvd_bsrc, NULL, /*flags*/0); ++ au_set_ibtop(a->inode, a->mvd_bdst); ++ } else { ++ /* hide the lower */ ++ au_set_h_dptr(a->dentry, a->mvd_bdst, NULL); ++ au_set_dbbot(a->dentry, a->mvd_bsrc); ++ au_set_h_iptr(a->inode, a->mvd_bdst, NULL, /*flags*/0); ++ au_set_ibbot(a->inode, a->mvd_bsrc); ++ } ++ if (au_dbbot(a->dentry) < a->mvd_bdst) ++ au_set_dbbot(a->dentry, a->mvd_bdst); ++ if (au_ibbot(a->inode) < a->mvd_bdst) ++ au_set_ibbot(a->inode, a->mvd_bdst); ++ ++out_unlock: ++ au_do_unlock(dmsg, a); ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* make sure the file is idle */ ++static int au_mvd_args_busy(const unsigned char dmsg, struct au_mvd_args *a) ++{ ++ int err, plinked; ++ ++ err = 0; ++ plinked = !!au_opt_test(au_mntflags(a->sb), PLINK); ++ if (au_dbtop(a->dentry) == a->mvd_bsrc ++ && au_dcount(a->dentry) == 1 ++ && atomic_read(&a->inode->i_count) == 1 ++ /* && a->mvd_h_src_inode->i_nlink == 1 */ ++ && (!plinked || !au_plink_test(a->inode)) ++ && a->inode->i_nlink == 1) ++ goto out; ++ ++ err = -EBUSY; ++ AU_MVD_PR(dmsg, ++ "b%d, d{b%d, c%d?}, i{c%d?, l%u}, hi{l%u}, p{%d, %d}\n", ++ a->mvd_bsrc, au_dbtop(a->dentry), au_dcount(a->dentry), ++ atomic_read(&a->inode->i_count), a->inode->i_nlink, ++ a->mvd_h_src_inode->i_nlink, ++ plinked, plinked ? au_plink_test(a->inode) : 0); ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++/* make sure the parent dir is fine */ ++static int au_mvd_args_parent(const unsigned char dmsg, ++ struct au_mvd_args *a) ++{ ++ int err; ++ aufs_bindex_t bindex; ++ ++ err = 0; ++ if (unlikely(au_alive_dir(a->parent))) { ++ err = -ENOENT; ++ AU_MVD_PR(dmsg, "parent dir is dead\n"); ++ goto out; ++ } ++ ++ a->bopq = au_dbdiropq(a->parent); ++ bindex = au_wbr_nonopq(a->dentry, a->mvd_bdst); ++ AuDbg("b%d\n", bindex); ++ if (unlikely((bindex >= 0 && bindex < a->mvd_bdst) ++ || (a->bopq != -1 && a->bopq < a->mvd_bdst))) { ++ err = -EINVAL; ++ a->mvd_errno = EAU_MVDOWN_OPAQUE; ++ AU_MVD_PR(dmsg, "ancestor is opaque b%d, b%d\n", ++ a->bopq, a->mvd_bdst); ++ } ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++static int au_mvd_args_intermediate(const unsigned char dmsg, ++ struct au_mvd_args *a) ++{ ++ int err; ++ struct au_dinfo *dinfo, *tmp; ++ ++ /* lookup the next lower positive entry */ ++ err = -ENOMEM; ++ tmp = au_di_alloc(a->sb, AuLsc_DI_TMP); ++ if (unlikely(!tmp)) ++ goto out; ++ ++ a->bfound = -1; ++ a->bwh = -1; ++ dinfo = au_di(a->dentry); ++ au_di_cp(tmp, dinfo); ++ au_di_swap(tmp, dinfo); ++ ++ /* returns the number of positive dentries */ ++ err = au_lkup_dentry(a->dentry, a->mvd_bsrc + 1, ++ /* AuLkup_IGNORE_PERM */ 0); ++ if (!err) ++ a->bwh = au_dbwh(a->dentry); ++ else if (err > 0) ++ a->bfound = au_dbtop(a->dentry); ++ ++ au_di_swap(tmp, dinfo); ++ au_rw_write_unlock(&tmp->di_rwsem); ++ au_di_free(tmp); ++ if (unlikely(err < 0)) ++ AU_MVD_PR(dmsg, "failed look-up lower\n"); ++ ++ /* ++ * here, we have these cases. ++ * bfound == -1 ++ * no positive dentry under bsrc. there are more sub-cases. ++ * bwh < 0 ++ * there no whiteout, we can safely move-down. ++ * bwh <= bsrc ++ * impossible ++ * bsrc < bwh && bwh < bdst ++ * there is a whiteout on RO branch. cannot proceed. ++ * bwh == bdst ++ * there is a whiteout on the RW target branch. it should ++ * be removed. ++ * bdst < bwh ++ * there is a whiteout somewhere unrelated branch. ++ * -1 < bfound && bfound <= bsrc ++ * impossible. ++ * bfound < bdst ++ * found, but it is on RO branch between bsrc and bdst. cannot ++ * proceed. ++ * bfound == bdst ++ * found, replace it if AUFS_MVDOWN_FORCE is set. otherwise return ++ * error. ++ * bdst < bfound ++ * found, after we create the file on bdst, it will be hidden. ++ */ ++ ++ AuDebugOn(a->bfound == -1 ++ && a->bwh != -1 ++ && a->bwh <= a->mvd_bsrc); ++ AuDebugOn(-1 < a->bfound ++ && a->bfound <= a->mvd_bsrc); ++ ++ err = -EINVAL; ++ if (a->bfound == -1 ++ && a->mvd_bsrc < a->bwh ++ && a->bwh != -1 ++ && a->bwh < a->mvd_bdst) { ++ a->mvd_errno = EAU_MVDOWN_WHITEOUT; ++ AU_MVD_PR(dmsg, "bsrc %d, bdst %d, bfound %d, bwh %d\n", ++ a->mvd_bsrc, a->mvd_bdst, a->bfound, a->bwh); ++ goto out; ++ } else if (a->bfound != -1 && a->bfound < a->mvd_bdst) { ++ a->mvd_errno = EAU_MVDOWN_UPPER; ++ AU_MVD_PR(dmsg, "bdst %d, bfound %d\n", ++ a->mvd_bdst, a->bfound); ++ goto out; ++ } ++ ++ err = 0; /* success */ ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++static int au_mvd_args_exist(const unsigned char dmsg, struct au_mvd_args *a) ++{ ++ int err; ++ ++ err = 0; ++ if (!(a->mvdown.flags & AUFS_MVDOWN_OWLOWER) ++ && a->bfound == a->mvd_bdst) ++ err = -EEXIST; ++ AuTraceErr(err); ++ return err; ++} ++ ++static int au_mvd_args(const unsigned char dmsg, struct au_mvd_args *a) ++{ ++ int err; ++ struct au_branch *br; ++ ++ err = -EISDIR; ++ if (unlikely(S_ISDIR(a->inode->i_mode))) ++ goto out; ++ ++ err = -EINVAL; ++ if (!(a->mvdown.flags & AUFS_MVDOWN_BRID_UPPER)) ++ a->mvd_bsrc = au_ibtop(a->inode); ++ else { ++ a->mvd_bsrc = au_br_index(a->sb, a->mvd_src_brid); ++ if (unlikely(a->mvd_bsrc < 0 ++ || (a->mvd_bsrc < au_dbtop(a->dentry) ++ || au_dbbot(a->dentry) < a->mvd_bsrc ++ || !au_h_dptr(a->dentry, a->mvd_bsrc)) ++ || (a->mvd_bsrc < au_ibtop(a->inode) ++ || au_ibbot(a->inode) < a->mvd_bsrc ++ || !au_h_iptr(a->inode, a->mvd_bsrc)))) { ++ a->mvd_errno = EAU_MVDOWN_NOUPPER; ++ AU_MVD_PR(dmsg, "no upper\n"); ++ goto out; ++ } ++ } ++ if (unlikely(a->mvd_bsrc == au_sbbot(a->sb))) { ++ a->mvd_errno = EAU_MVDOWN_BOTTOM; ++ AU_MVD_PR(dmsg, "on the bottom\n"); ++ goto out; ++ } ++ a->mvd_h_src_inode = au_h_iptr(a->inode, a->mvd_bsrc); ++ br = au_sbr(a->sb, a->mvd_bsrc); ++ err = au_br_rdonly(br); ++ if (!(a->mvdown.flags & AUFS_MVDOWN_ROUPPER)) { ++ if (unlikely(err)) ++ goto out; ++ } else if (!(vfsub_native_ro(a->mvd_h_src_inode) ++ || IS_APPEND(a->mvd_h_src_inode))) { ++ if (err) ++ a->mvdown.flags |= AUFS_MVDOWN_ROUPPER_R; ++ /* go on */ ++ } else ++ goto out; ++ ++ err = -EINVAL; ++ if (!(a->mvdown.flags & AUFS_MVDOWN_BRID_LOWER)) { ++ a->mvd_bdst = find_lower_writable(a); ++ if (unlikely(a->mvd_bdst < 0)) { ++ a->mvd_errno = EAU_MVDOWN_BOTTOM; ++ AU_MVD_PR(dmsg, "no writable lower branch\n"); ++ goto out; ++ } ++ } else { ++ a->mvd_bdst = au_br_index(a->sb, a->mvd_dst_brid); ++ if (unlikely(a->mvd_bdst < 0 ++ || au_sbbot(a->sb) < a->mvd_bdst)) { ++ a->mvd_errno = EAU_MVDOWN_NOLOWERBR; ++ AU_MVD_PR(dmsg, "no lower brid\n"); ++ goto out; ++ } ++ } ++ ++ err = au_mvd_args_busy(dmsg, a); ++ if (!err) ++ err = au_mvd_args_parent(dmsg, a); ++ if (!err) ++ err = au_mvd_args_intermediate(dmsg, a); ++ if (!err) ++ err = au_mvd_args_exist(dmsg, a); ++ if (!err) ++ AuDbg("b%d, b%d\n", a->mvd_bsrc, a->mvd_bdst); ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++int au_mvdown(struct dentry *dentry, struct aufs_mvdown __user *uarg) ++{ ++ int err, e; ++ unsigned char dmsg; ++ struct au_mvd_args *args; ++ struct inode *inode; ++ ++ inode = d_inode(dentry); ++ err = -EPERM; ++ if (unlikely(!capable(CAP_SYS_ADMIN))) ++ goto out; ++ ++ err = -ENOMEM; ++ args = kmalloc(sizeof(*args), GFP_NOFS); ++ if (unlikely(!args)) ++ goto out; ++ ++ err = copy_from_user(&args->mvdown, uarg, sizeof(args->mvdown)); ++ if (!err) ++ /* VERIFY_WRITE */ ++ err = !access_ok(uarg, sizeof(*uarg)); ++ if (unlikely(err)) { ++ err = -EFAULT; ++ AuTraceErr(err); ++ goto out_free; ++ } ++ AuDbg("flags 0x%x\n", args->mvdown.flags); ++ args->mvdown.flags &= ~(AUFS_MVDOWN_ROLOWER_R | AUFS_MVDOWN_ROUPPER_R); ++ args->mvdown.au_errno = 0; ++ args->dentry = dentry; ++ args->inode = inode; ++ args->sb = dentry->d_sb; ++ ++ err = -ENOENT; ++ dmsg = !!(args->mvdown.flags & AUFS_MVDOWN_DMSG); ++ args->parent = dget_parent(dentry); ++ args->dir = d_inode(args->parent); ++ inode_lock_nested(args->dir, I_MUTEX_PARENT); ++ dput(args->parent); ++ if (unlikely(args->parent != dentry->d_parent)) { ++ AU_MVD_PR(dmsg, "parent dir is moved\n"); ++ goto out_dir; ++ } ++ ++ inode_lock_nested(inode, I_MUTEX_CHILD); ++ err = aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH | AuLock_NOPLMW); ++ if (unlikely(err)) ++ goto out_inode; ++ ++ di_write_lock_parent(args->parent); ++ err = au_mvd_args(dmsg, args); ++ if (unlikely(err)) ++ goto out_parent; ++ ++ err = au_do_mvdown(dmsg, args); ++ if (unlikely(err)) ++ goto out_parent; ++ ++ au_cpup_attr_timesizes(args->dir); ++ au_cpup_attr_timesizes(inode); ++ if (!(args->mvdown.flags & AUFS_MVDOWN_KUPPER)) ++ au_cpup_igen(inode, au_h_iptr(inode, args->mvd_bdst)); ++ /* au_digen_dec(dentry); */ ++ ++out_parent: ++ di_write_unlock(args->parent); ++ aufs_read_unlock(dentry, AuLock_DW); ++out_inode: ++ inode_unlock(inode); ++out_dir: ++ inode_unlock(args->dir); ++out_free: ++ e = copy_to_user(uarg, &args->mvdown, sizeof(args->mvdown)); ++ if (unlikely(e)) ++ err = -EFAULT; ++ au_kfree_rcu(args); ++out: ++ AuTraceErr(err); ++ return err; ++} +diff -Nurp linux-5.4/fs/aufs/opts.c linux-5.4-aufs/fs/aufs/opts.c +--- linux-5.4/fs/aufs/opts.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/opts.c 2019-11-28 01:25:59.067925618 +0200 +@@ -0,0 +1,1867 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * mount options/flags ++ */ ++ ++#include ++#include /* a distribution requires */ ++#include ++#include "aufs.h" ++ ++/* ---------------------------------------------------------------------- */ ++ ++enum { ++ Opt_br, ++ Opt_add, Opt_del, Opt_mod, Opt_append, Opt_prepend, ++ Opt_idel, Opt_imod, ++ Opt_dirwh, Opt_rdcache, Opt_rdblk, Opt_rdhash, ++ Opt_rdblk_def, Opt_rdhash_def, ++ Opt_xino, Opt_noxino, ++ Opt_trunc_xino, Opt_trunc_xino_v, Opt_notrunc_xino, ++ Opt_trunc_xino_path, Opt_itrunc_xino, ++ Opt_trunc_xib, Opt_notrunc_xib, ++ Opt_shwh, Opt_noshwh, ++ Opt_plink, Opt_noplink, Opt_list_plink, ++ Opt_udba, ++ Opt_dio, Opt_nodio, ++ Opt_diropq_a, Opt_diropq_w, ++ Opt_warn_perm, Opt_nowarn_perm, ++ Opt_wbr_copyup, Opt_wbr_create, ++ Opt_fhsm_sec, ++ Opt_verbose, Opt_noverbose, ++ Opt_sum, Opt_nosum, Opt_wsum, ++ Opt_dirperm1, Opt_nodirperm1, ++ Opt_dirren, Opt_nodirren, ++ Opt_acl, Opt_noacl, ++ Opt_tail, Opt_ignore, Opt_ignore_silent, Opt_err ++}; ++ ++static match_table_t options = { ++ {Opt_br, "br=%s"}, ++ {Opt_br, "br:%s"}, ++ ++ {Opt_add, "add=%d:%s"}, ++ {Opt_add, "add:%d:%s"}, ++ {Opt_add, "ins=%d:%s"}, ++ {Opt_add, "ins:%d:%s"}, ++ {Opt_append, "append=%s"}, ++ {Opt_append, "append:%s"}, ++ {Opt_prepend, "prepend=%s"}, ++ {Opt_prepend, "prepend:%s"}, ++ ++ {Opt_del, "del=%s"}, ++ {Opt_del, "del:%s"}, ++ /* {Opt_idel, "idel:%d"}, */ ++ {Opt_mod, "mod=%s"}, ++ {Opt_mod, "mod:%s"}, ++ /* {Opt_imod, "imod:%d:%s"}, */ ++ ++ {Opt_dirwh, "dirwh=%d"}, ++ ++ {Opt_xino, "xino=%s"}, ++ {Opt_noxino, "noxino"}, ++ {Opt_trunc_xino, "trunc_xino"}, ++ {Opt_trunc_xino_v, "trunc_xino_v=%d:%d"}, ++ {Opt_notrunc_xino, "notrunc_xino"}, ++ {Opt_trunc_xino_path, "trunc_xino=%s"}, ++ {Opt_itrunc_xino, "itrunc_xino=%d"}, ++ /* {Opt_zxino, "zxino=%s"}, */ ++ {Opt_trunc_xib, "trunc_xib"}, ++ {Opt_notrunc_xib, "notrunc_xib"}, ++ ++#ifdef CONFIG_PROC_FS ++ {Opt_plink, "plink"}, ++#else ++ {Opt_ignore_silent, "plink"}, ++#endif ++ ++ {Opt_noplink, "noplink"}, ++ ++#ifdef CONFIG_AUFS_DEBUG ++ {Opt_list_plink, "list_plink"}, ++#endif ++ ++ {Opt_udba, "udba=%s"}, ++ ++ {Opt_dio, "dio"}, ++ {Opt_nodio, "nodio"}, ++ ++#ifdef CONFIG_AUFS_DIRREN ++ {Opt_dirren, "dirren"}, ++ {Opt_nodirren, "nodirren"}, ++#else ++ {Opt_ignore, "dirren"}, ++ {Opt_ignore_silent, "nodirren"}, ++#endif ++ ++#ifdef CONFIG_AUFS_FHSM ++ {Opt_fhsm_sec, "fhsm_sec=%d"}, ++#else ++ {Opt_ignore, "fhsm_sec=%d"}, ++#endif ++ ++ {Opt_diropq_a, "diropq=always"}, ++ {Opt_diropq_a, "diropq=a"}, ++ {Opt_diropq_w, "diropq=whiteouted"}, ++ {Opt_diropq_w, "diropq=w"}, ++ ++ {Opt_warn_perm, "warn_perm"}, ++ {Opt_nowarn_perm, "nowarn_perm"}, ++ ++ /* keep them temporary */ ++ {Opt_ignore_silent, "nodlgt"}, ++ {Opt_ignore, "clean_plink"}, ++ ++#ifdef CONFIG_AUFS_SHWH ++ {Opt_shwh, "shwh"}, ++#endif ++ {Opt_noshwh, "noshwh"}, ++ ++ {Opt_dirperm1, "dirperm1"}, ++ {Opt_nodirperm1, "nodirperm1"}, ++ ++ {Opt_verbose, "verbose"}, ++ {Opt_verbose, "v"}, ++ {Opt_noverbose, "noverbose"}, ++ {Opt_noverbose, "quiet"}, ++ {Opt_noverbose, "q"}, ++ {Opt_noverbose, "silent"}, ++ ++ {Opt_sum, "sum"}, ++ {Opt_nosum, "nosum"}, ++ {Opt_wsum, "wsum"}, ++ ++ {Opt_rdcache, "rdcache=%d"}, ++ {Opt_rdblk, "rdblk=%d"}, ++ {Opt_rdblk_def, "rdblk=def"}, ++ {Opt_rdhash, "rdhash=%d"}, ++ {Opt_rdhash_def, "rdhash=def"}, ++ ++ {Opt_wbr_create, "create=%s"}, ++ {Opt_wbr_create, "create_policy=%s"}, ++ {Opt_wbr_copyup, "cpup=%s"}, ++ {Opt_wbr_copyup, "copyup=%s"}, ++ {Opt_wbr_copyup, "copyup_policy=%s"}, ++ ++ /* generic VFS flag */ ++#ifdef CONFIG_FS_POSIX_ACL ++ {Opt_acl, "acl"}, ++ {Opt_noacl, "noacl"}, ++#else ++ {Opt_ignore, "acl"}, ++ {Opt_ignore_silent, "noacl"}, ++#endif ++ ++ /* internal use for the scripts */ ++ {Opt_ignore_silent, "si=%s"}, ++ ++ {Opt_br, "dirs=%s"}, ++ {Opt_ignore, "debug=%d"}, ++ {Opt_ignore, "delete=whiteout"}, ++ {Opt_ignore, "delete=all"}, ++ {Opt_ignore, "imap=%s"}, ++ ++ /* temporary workaround, due to old mount(8)? */ ++ {Opt_ignore_silent, "relatime"}, ++ ++ {Opt_err, NULL} ++}; ++ ++/* ---------------------------------------------------------------------- */ ++ ++static const char *au_parser_pattern(int val, match_table_t tbl) ++{ ++ struct match_token *p; ++ ++ p = tbl; ++ while (p->pattern) { ++ if (p->token == val) ++ return p->pattern; ++ p++; ++ } ++ BUG(); ++ return "??"; ++} ++ ++static const char *au_optstr(int *val, match_table_t tbl) ++{ ++ struct match_token *p; ++ int v; ++ ++ v = *val; ++ if (!v) ++ goto out; ++ p = tbl; ++ while (p->pattern) { ++ if (p->token ++ && (v & p->token) == p->token) { ++ *val &= ~p->token; ++ return p->pattern; ++ } ++ p++; ++ } ++ ++out: ++ return NULL; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static match_table_t brperm = { ++ {AuBrPerm_RO, AUFS_BRPERM_RO}, ++ {AuBrPerm_RR, AUFS_BRPERM_RR}, ++ {AuBrPerm_RW, AUFS_BRPERM_RW}, ++ {0, NULL} ++}; ++ ++static match_table_t brattr = { ++ /* general */ ++ {AuBrAttr_COO_REG, AUFS_BRATTR_COO_REG}, ++ {AuBrAttr_COO_ALL, AUFS_BRATTR_COO_ALL}, ++ /* 'unpin' attrib is meaningless since linux-3.18-rc1 */ ++ {AuBrAttr_UNPIN, AUFS_BRATTR_UNPIN}, ++#ifdef CONFIG_AUFS_FHSM ++ {AuBrAttr_FHSM, AUFS_BRATTR_FHSM}, ++#endif ++#ifdef CONFIG_AUFS_XATTR ++ {AuBrAttr_ICEX, AUFS_BRATTR_ICEX}, ++ {AuBrAttr_ICEX_SEC, AUFS_BRATTR_ICEX_SEC}, ++ {AuBrAttr_ICEX_SYS, AUFS_BRATTR_ICEX_SYS}, ++ {AuBrAttr_ICEX_TR, AUFS_BRATTR_ICEX_TR}, ++ {AuBrAttr_ICEX_USR, AUFS_BRATTR_ICEX_USR}, ++ {AuBrAttr_ICEX_OTH, AUFS_BRATTR_ICEX_OTH}, ++#endif ++ ++ /* ro/rr branch */ ++ {AuBrRAttr_WH, AUFS_BRRATTR_WH}, ++ ++ /* rw branch */ ++ {AuBrWAttr_MOO, AUFS_BRWATTR_MOO}, ++ {AuBrWAttr_NoLinkWH, AUFS_BRWATTR_NLWH}, ++ ++ {0, NULL} ++}; ++ ++static int br_attr_val(char *str, match_table_t table, substring_t args[]) ++{ ++ int attr, v; ++ char *p; ++ ++ attr = 0; ++ do { ++ p = strchr(str, '+'); ++ if (p) ++ *p = 0; ++ v = match_token(str, table, args); ++ if (v) { ++ if (v & AuBrAttr_CMOO_Mask) ++ attr &= ~AuBrAttr_CMOO_Mask; ++ attr |= v; ++ } else { ++ if (p) ++ *p = '+'; ++ pr_warn("ignored branch attribute %s\n", str); ++ break; ++ } ++ if (p) ++ str = p + 1; ++ } while (p); ++ ++ return attr; ++} ++ ++static int au_do_optstr_br_attr(au_br_perm_str_t *str, int perm) ++{ ++ int sz; ++ const char *p; ++ char *q; ++ ++ q = str->a; ++ *q = 0; ++ p = au_optstr(&perm, brattr); ++ if (p) { ++ sz = strlen(p); ++ memcpy(q, p, sz + 1); ++ q += sz; ++ } else ++ goto out; ++ ++ do { ++ p = au_optstr(&perm, brattr); ++ if (p) { ++ *q++ = '+'; ++ sz = strlen(p); ++ memcpy(q, p, sz + 1); ++ q += sz; ++ } ++ } while (p); ++ ++out: ++ return q - str->a; ++} ++ ++static int noinline_for_stack br_perm_val(char *perm) ++{ ++ int val, bad, sz; ++ char *p; ++ substring_t args[MAX_OPT_ARGS]; ++ au_br_perm_str_t attr; ++ ++ p = strchr(perm, '+'); ++ if (p) ++ *p = 0; ++ val = match_token(perm, brperm, args); ++ if (!val) { ++ if (p) ++ *p = '+'; ++ pr_warn("ignored branch permission %s\n", perm); ++ val = AuBrPerm_RO; ++ goto out; ++ } ++ if (!p) ++ goto out; ++ ++ val |= br_attr_val(p + 1, brattr, args); ++ ++ bad = 0; ++ switch (val & AuBrPerm_Mask) { ++ case AuBrPerm_RO: ++ case AuBrPerm_RR: ++ bad = val & AuBrWAttr_Mask; ++ val &= ~AuBrWAttr_Mask; ++ break; ++ case AuBrPerm_RW: ++ bad = val & AuBrRAttr_Mask; ++ val &= ~AuBrRAttr_Mask; ++ break; ++ } ++ ++ /* ++ * 'unpin' attrib becomes meaningless since linux-3.18-rc1, but aufs ++ * does not treat it as an error, just warning. ++ * this is a tiny guard for the user operation. ++ */ ++ if (val & AuBrAttr_UNPIN) { ++ bad |= AuBrAttr_UNPIN; ++ val &= ~AuBrAttr_UNPIN; ++ } ++ ++ if (unlikely(bad)) { ++ sz = au_do_optstr_br_attr(&attr, bad); ++ AuDebugOn(!sz); ++ pr_warn("ignored branch attribute %s\n", attr.a); ++ } ++ ++out: ++ return val; ++} ++ ++void au_optstr_br_perm(au_br_perm_str_t *str, int perm) ++{ ++ au_br_perm_str_t attr; ++ const char *p; ++ char *q; ++ int sz; ++ ++ q = str->a; ++ p = au_optstr(&perm, brperm); ++ AuDebugOn(!p || !*p); ++ sz = strlen(p); ++ memcpy(q, p, sz + 1); ++ q += sz; ++ ++ sz = au_do_optstr_br_attr(&attr, perm); ++ if (sz) { ++ *q++ = '+'; ++ memcpy(q, attr.a, sz + 1); ++ } ++ ++ AuDebugOn(strlen(str->a) >= sizeof(str->a)); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static match_table_t udbalevel = { ++ {AuOpt_UDBA_REVAL, "reval"}, ++ {AuOpt_UDBA_NONE, "none"}, ++#ifdef CONFIG_AUFS_HNOTIFY ++ {AuOpt_UDBA_HNOTIFY, "notify"}, /* abstraction */ ++#ifdef CONFIG_AUFS_HFSNOTIFY ++ {AuOpt_UDBA_HNOTIFY, "fsnotify"}, ++#endif ++#endif ++ {-1, NULL} ++}; ++ ++static int noinline_for_stack udba_val(char *str) ++{ ++ substring_t args[MAX_OPT_ARGS]; ++ ++ return match_token(str, udbalevel, args); ++} ++ ++const char *au_optstr_udba(int udba) ++{ ++ return au_parser_pattern(udba, udbalevel); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static match_table_t au_wbr_create_policy = { ++ {AuWbrCreate_TDP, "tdp"}, ++ {AuWbrCreate_TDP, "top-down-parent"}, ++ {AuWbrCreate_RR, "rr"}, ++ {AuWbrCreate_RR, "round-robin"}, ++ {AuWbrCreate_MFS, "mfs"}, ++ {AuWbrCreate_MFS, "most-free-space"}, ++ {AuWbrCreate_MFSV, "mfs:%d"}, ++ {AuWbrCreate_MFSV, "most-free-space:%d"}, ++ ++ /* top-down regardless the parent, and then mfs */ ++ {AuWbrCreate_TDMFS, "tdmfs:%d"}, ++ {AuWbrCreate_TDMFSV, "tdmfs:%d:%d"}, ++ ++ {AuWbrCreate_MFSRR, "mfsrr:%d"}, ++ {AuWbrCreate_MFSRRV, "mfsrr:%d:%d"}, ++ {AuWbrCreate_PMFS, "pmfs"}, ++ {AuWbrCreate_PMFSV, "pmfs:%d"}, ++ {AuWbrCreate_PMFSRR, "pmfsrr:%d"}, ++ {AuWbrCreate_PMFSRRV, "pmfsrr:%d:%d"}, ++ ++ {-1, NULL} ++}; ++ ++static int au_wbr_mfs_wmark(substring_t *arg, char *str, ++ struct au_opt_wbr_create *create) ++{ ++ int err; ++ unsigned long long ull; ++ ++ err = 0; ++ if (!match_u64(arg, &ull)) ++ create->mfsrr_watermark = ull; ++ else { ++ pr_err("bad integer in %s\n", str); ++ err = -EINVAL; ++ } ++ ++ return err; ++} ++ ++static int au_wbr_mfs_sec(substring_t *arg, char *str, ++ struct au_opt_wbr_create *create) ++{ ++ int n, err; ++ ++ err = 0; ++ if (!match_int(arg, &n) && 0 <= n && n <= AUFS_MFS_MAX_SEC) ++ create->mfs_second = n; ++ else { ++ pr_err("bad integer in %s\n", str); ++ err = -EINVAL; ++ } ++ ++ return err; ++} ++ ++static int noinline_for_stack ++au_wbr_create_val(char *str, struct au_opt_wbr_create *create) ++{ ++ int err, e; ++ substring_t args[MAX_OPT_ARGS]; ++ ++ err = match_token(str, au_wbr_create_policy, args); ++ create->wbr_create = err; ++ switch (err) { ++ case AuWbrCreate_MFSRRV: ++ case AuWbrCreate_TDMFSV: ++ case AuWbrCreate_PMFSRRV: ++ e = au_wbr_mfs_wmark(&args[0], str, create); ++ if (!e) ++ e = au_wbr_mfs_sec(&args[1], str, create); ++ if (unlikely(e)) ++ err = e; ++ break; ++ case AuWbrCreate_MFSRR: ++ case AuWbrCreate_TDMFS: ++ case AuWbrCreate_PMFSRR: ++ e = au_wbr_mfs_wmark(&args[0], str, create); ++ if (unlikely(e)) { ++ err = e; ++ break; ++ } ++ /*FALLTHROUGH*/ ++ case AuWbrCreate_MFS: ++ case AuWbrCreate_PMFS: ++ create->mfs_second = AUFS_MFS_DEF_SEC; ++ break; ++ case AuWbrCreate_MFSV: ++ case AuWbrCreate_PMFSV: ++ e = au_wbr_mfs_sec(&args[0], str, create); ++ if (unlikely(e)) ++ err = e; ++ break; ++ } ++ ++ return err; ++} ++ ++const char *au_optstr_wbr_create(int wbr_create) ++{ ++ return au_parser_pattern(wbr_create, au_wbr_create_policy); ++} ++ ++static match_table_t au_wbr_copyup_policy = { ++ {AuWbrCopyup_TDP, "tdp"}, ++ {AuWbrCopyup_TDP, "top-down-parent"}, ++ {AuWbrCopyup_BUP, "bup"}, ++ {AuWbrCopyup_BUP, "bottom-up-parent"}, ++ {AuWbrCopyup_BU, "bu"}, ++ {AuWbrCopyup_BU, "bottom-up"}, ++ {-1, NULL} ++}; ++ ++static int noinline_for_stack au_wbr_copyup_val(char *str) ++{ ++ substring_t args[MAX_OPT_ARGS]; ++ ++ return match_token(str, au_wbr_copyup_policy, args); ++} ++ ++const char *au_optstr_wbr_copyup(int wbr_copyup) ++{ ++ return au_parser_pattern(wbr_copyup, au_wbr_copyup_policy); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static const int lkup_dirflags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY; ++ ++static void dump_opts(struct au_opts *opts) ++{ ++#ifdef CONFIG_AUFS_DEBUG ++ /* reduce stack space */ ++ union { ++ struct au_opt_add *add; ++ struct au_opt_del *del; ++ struct au_opt_mod *mod; ++ struct au_opt_xino *xino; ++ struct au_opt_xino_itrunc *xino_itrunc; ++ struct au_opt_wbr_create *create; ++ } u; ++ struct au_opt *opt; ++ ++ opt = opts->opt; ++ while (opt->type != Opt_tail) { ++ switch (opt->type) { ++ case Opt_add: ++ u.add = &opt->add; ++ AuDbg("add {b%d, %s, 0x%x, %p}\n", ++ u.add->bindex, u.add->pathname, u.add->perm, ++ u.add->path.dentry); ++ break; ++ case Opt_del: ++ case Opt_idel: ++ u.del = &opt->del; ++ AuDbg("del {%s, %p}\n", ++ u.del->pathname, u.del->h_path.dentry); ++ break; ++ case Opt_mod: ++ case Opt_imod: ++ u.mod = &opt->mod; ++ AuDbg("mod {%s, 0x%x, %p}\n", ++ u.mod->path, u.mod->perm, u.mod->h_root); ++ break; ++ case Opt_append: ++ u.add = &opt->add; ++ AuDbg("append {b%d, %s, 0x%x, %p}\n", ++ u.add->bindex, u.add->pathname, u.add->perm, ++ u.add->path.dentry); ++ break; ++ case Opt_prepend: ++ u.add = &opt->add; ++ AuDbg("prepend {b%d, %s, 0x%x, %p}\n", ++ u.add->bindex, u.add->pathname, u.add->perm, ++ u.add->path.dentry); ++ break; ++ case Opt_dirwh: ++ AuDbg("dirwh %d\n", opt->dirwh); ++ break; ++ case Opt_rdcache: ++ AuDbg("rdcache %d\n", opt->rdcache); ++ break; ++ case Opt_rdblk: ++ AuDbg("rdblk %u\n", opt->rdblk); ++ break; ++ case Opt_rdblk_def: ++ AuDbg("rdblk_def\n"); ++ break; ++ case Opt_rdhash: ++ AuDbg("rdhash %u\n", opt->rdhash); ++ break; ++ case Opt_rdhash_def: ++ AuDbg("rdhash_def\n"); ++ break; ++ case Opt_xino: ++ u.xino = &opt->xino; ++ AuDbg("xino {%s %pD}\n", u.xino->path, u.xino->file); ++ break; ++ case Opt_trunc_xino: ++ AuLabel(trunc_xino); ++ break; ++ case Opt_notrunc_xino: ++ AuLabel(notrunc_xino); ++ break; ++ case Opt_trunc_xino_path: ++ case Opt_itrunc_xino: ++ u.xino_itrunc = &opt->xino_itrunc; ++ AuDbg("trunc_xino %d\n", u.xino_itrunc->bindex); ++ break; ++ case Opt_noxino: ++ AuLabel(noxino); ++ break; ++ case Opt_trunc_xib: ++ AuLabel(trunc_xib); ++ break; ++ case Opt_notrunc_xib: ++ AuLabel(notrunc_xib); ++ break; ++ case Opt_shwh: ++ AuLabel(shwh); ++ break; ++ case Opt_noshwh: ++ AuLabel(noshwh); ++ break; ++ case Opt_dirperm1: ++ AuLabel(dirperm1); ++ break; ++ case Opt_nodirperm1: ++ AuLabel(nodirperm1); ++ break; ++ case Opt_plink: ++ AuLabel(plink); ++ break; ++ case Opt_noplink: ++ AuLabel(noplink); ++ break; ++ case Opt_list_plink: ++ AuLabel(list_plink); ++ break; ++ case Opt_udba: ++ AuDbg("udba %d, %s\n", ++ opt->udba, au_optstr_udba(opt->udba)); ++ break; ++ case Opt_dio: ++ AuLabel(dio); ++ break; ++ case Opt_nodio: ++ AuLabel(nodio); ++ break; ++ case Opt_diropq_a: ++ AuLabel(diropq_a); ++ break; ++ case Opt_diropq_w: ++ AuLabel(diropq_w); ++ break; ++ case Opt_warn_perm: ++ AuLabel(warn_perm); ++ break; ++ case Opt_nowarn_perm: ++ AuLabel(nowarn_perm); ++ break; ++ case Opt_verbose: ++ AuLabel(verbose); ++ break; ++ case Opt_noverbose: ++ AuLabel(noverbose); ++ break; ++ case Opt_sum: ++ AuLabel(sum); ++ break; ++ case Opt_nosum: ++ AuLabel(nosum); ++ break; ++ case Opt_wsum: ++ AuLabel(wsum); ++ break; ++ case Opt_wbr_create: ++ u.create = &opt->wbr_create; ++ AuDbg("create %d, %s\n", u.create->wbr_create, ++ au_optstr_wbr_create(u.create->wbr_create)); ++ switch (u.create->wbr_create) { ++ case AuWbrCreate_MFSV: ++ case AuWbrCreate_PMFSV: ++ AuDbg("%d sec\n", u.create->mfs_second); ++ break; ++ case AuWbrCreate_MFSRR: ++ case AuWbrCreate_TDMFS: ++ AuDbg("%llu watermark\n", ++ u.create->mfsrr_watermark); ++ break; ++ case AuWbrCreate_MFSRRV: ++ case AuWbrCreate_TDMFSV: ++ case AuWbrCreate_PMFSRRV: ++ AuDbg("%llu watermark, %d sec\n", ++ u.create->mfsrr_watermark, ++ u.create->mfs_second); ++ break; ++ } ++ break; ++ case Opt_wbr_copyup: ++ AuDbg("copyup %d, %s\n", opt->wbr_copyup, ++ au_optstr_wbr_copyup(opt->wbr_copyup)); ++ break; ++ case Opt_fhsm_sec: ++ AuDbg("fhsm_sec %u\n", opt->fhsm_second); ++ break; ++ case Opt_dirren: ++ AuLabel(dirren); ++ break; ++ case Opt_nodirren: ++ AuLabel(nodirren); ++ break; ++ case Opt_acl: ++ AuLabel(acl); ++ break; ++ case Opt_noacl: ++ AuLabel(noacl); ++ break; ++ default: ++ BUG(); ++ } ++ opt++; ++ } ++#endif ++} ++ ++void au_opts_free(struct au_opts *opts) ++{ ++ struct au_opt *opt; ++ ++ opt = opts->opt; ++ while (opt->type != Opt_tail) { ++ switch (opt->type) { ++ case Opt_add: ++ case Opt_append: ++ case Opt_prepend: ++ path_put(&opt->add.path); ++ break; ++ case Opt_del: ++ case Opt_idel: ++ path_put(&opt->del.h_path); ++ break; ++ case Opt_mod: ++ case Opt_imod: ++ dput(opt->mod.h_root); ++ break; ++ case Opt_xino: ++ fput(opt->xino.file); ++ break; ++ } ++ opt++; ++ } ++} ++ ++static int opt_add(struct au_opt *opt, char *opt_str, unsigned long sb_flags, ++ aufs_bindex_t bindex) ++{ ++ int err; ++ struct au_opt_add *add = &opt->add; ++ char *p; ++ ++ add->bindex = bindex; ++ add->perm = AuBrPerm_RO; ++ add->pathname = opt_str; ++ p = strchr(opt_str, '='); ++ if (p) { ++ *p++ = 0; ++ if (*p) ++ add->perm = br_perm_val(p); ++ } ++ ++ err = vfsub_kern_path(add->pathname, lkup_dirflags, &add->path); ++ if (!err) { ++ if (!p) { ++ add->perm = AuBrPerm_RO; ++ if (au_test_fs_rr(add->path.dentry->d_sb)) ++ add->perm = AuBrPerm_RR; ++ else if (!bindex && !(sb_flags & SB_RDONLY)) ++ add->perm = AuBrPerm_RW; ++ } ++ opt->type = Opt_add; ++ goto out; ++ } ++ pr_err("lookup failed %s (%d)\n", add->pathname, err); ++ err = -EINVAL; ++ ++out: ++ return err; ++} ++ ++static int au_opts_parse_del(struct au_opt_del *del, substring_t args[]) ++{ ++ int err; ++ ++ del->pathname = args[0].from; ++ AuDbg("del path %s\n", del->pathname); ++ ++ err = vfsub_kern_path(del->pathname, lkup_dirflags, &del->h_path); ++ if (unlikely(err)) ++ pr_err("lookup failed %s (%d)\n", del->pathname, err); ++ ++ return err; ++} ++ ++#if 0 /* reserved for future use */ ++static int au_opts_parse_idel(struct super_block *sb, aufs_bindex_t bindex, ++ struct au_opt_del *del, substring_t args[]) ++{ ++ int err; ++ struct dentry *root; ++ ++ err = -EINVAL; ++ root = sb->s_root; ++ aufs_read_lock(root, AuLock_FLUSH); ++ if (bindex < 0 || au_sbbot(sb) < bindex) { ++ pr_err("out of bounds, %d\n", bindex); ++ goto out; ++ } ++ ++ err = 0; ++ del->h_path.dentry = dget(au_h_dptr(root, bindex)); ++ del->h_path.mnt = mntget(au_sbr_mnt(sb, bindex)); ++ ++out: ++ aufs_read_unlock(root, !AuLock_IR); ++ return err; ++} ++#endif ++ ++static int noinline_for_stack ++au_opts_parse_mod(struct au_opt_mod *mod, substring_t args[]) ++{ ++ int err; ++ struct path path; ++ char *p; ++ ++ err = -EINVAL; ++ mod->path = args[0].from; ++ p = strchr(mod->path, '='); ++ if (unlikely(!p)) { ++ pr_err("no permission %s\n", args[0].from); ++ goto out; ++ } ++ ++ *p++ = 0; ++ err = vfsub_kern_path(mod->path, lkup_dirflags, &path); ++ if (unlikely(err)) { ++ pr_err("lookup failed %s (%d)\n", mod->path, err); ++ goto out; ++ } ++ ++ mod->perm = br_perm_val(p); ++ AuDbg("mod path %s, perm 0x%x, %s\n", mod->path, mod->perm, p); ++ mod->h_root = dget(path.dentry); ++ path_put(&path); ++ ++out: ++ return err; ++} ++ ++#if 0 /* reserved for future use */ ++static int au_opts_parse_imod(struct super_block *sb, aufs_bindex_t bindex, ++ struct au_opt_mod *mod, substring_t args[]) ++{ ++ int err; ++ struct dentry *root; ++ ++ err = -EINVAL; ++ root = sb->s_root; ++ aufs_read_lock(root, AuLock_FLUSH); ++ if (bindex < 0 || au_sbbot(sb) < bindex) { ++ pr_err("out of bounds, %d\n", bindex); ++ goto out; ++ } ++ ++ err = 0; ++ mod->perm = br_perm_val(args[1].from); ++ AuDbg("mod path %s, perm 0x%x, %s\n", ++ mod->path, mod->perm, args[1].from); ++ mod->h_root = dget(au_h_dptr(root, bindex)); ++ ++out: ++ aufs_read_unlock(root, !AuLock_IR); ++ return err; ++} ++#endif ++ ++static int au_opts_parse_xino(struct super_block *sb, struct au_opt_xino *xino, ++ substring_t args[]) ++{ ++ int err; ++ struct file *file; ++ ++ file = au_xino_create(sb, args[0].from, /*silent*/0, /*wbrtop*/0); ++ err = PTR_ERR(file); ++ if (IS_ERR(file)) ++ goto out; ++ ++ err = -EINVAL; ++ if (unlikely(file->f_path.dentry->d_sb == sb)) { ++ fput(file); ++ pr_err("%s must be outside\n", args[0].from); ++ goto out; ++ } ++ ++ err = 0; ++ xino->file = file; ++ xino->path = args[0].from; ++ ++out: ++ return err; ++} ++ ++static int noinline_for_stack ++au_opts_parse_xino_itrunc_path(struct super_block *sb, ++ struct au_opt_xino_itrunc *xino_itrunc, ++ substring_t args[]) ++{ ++ int err; ++ aufs_bindex_t bbot, bindex; ++ struct path path; ++ struct dentry *root; ++ ++ err = vfsub_kern_path(args[0].from, lkup_dirflags, &path); ++ if (unlikely(err)) { ++ pr_err("lookup failed %s (%d)\n", args[0].from, err); ++ goto out; ++ } ++ ++ xino_itrunc->bindex = -1; ++ root = sb->s_root; ++ aufs_read_lock(root, AuLock_FLUSH); ++ bbot = au_sbbot(sb); ++ for (bindex = 0; bindex <= bbot; bindex++) { ++ if (au_h_dptr(root, bindex) == path.dentry) { ++ xino_itrunc->bindex = bindex; ++ break; ++ } ++ } ++ aufs_read_unlock(root, !AuLock_IR); ++ path_put(&path); ++ ++ if (unlikely(xino_itrunc->bindex < 0)) { ++ pr_err("no such branch %s\n", args[0].from); ++ err = -EINVAL; ++ } ++ ++out: ++ return err; ++} ++ ++/* called without aufs lock */ ++int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts) ++{ ++ int err, n, token; ++ aufs_bindex_t bindex; ++ unsigned char skipped; ++ struct dentry *root; ++ struct au_opt *opt, *opt_tail; ++ char *opt_str; ++ /* reduce the stack space */ ++ union { ++ struct au_opt_xino_itrunc *xino_itrunc; ++ struct au_opt_wbr_create *create; ++ } u; ++ struct { ++ substring_t args[MAX_OPT_ARGS]; ++ } *a; ++ ++ err = -ENOMEM; ++ a = kmalloc(sizeof(*a), GFP_NOFS); ++ if (unlikely(!a)) ++ goto out; ++ ++ root = sb->s_root; ++ err = 0; ++ bindex = 0; ++ opt = opts->opt; ++ opt_tail = opt + opts->max_opt - 1; ++ opt->type = Opt_tail; ++ while (!err && (opt_str = strsep(&str, ",")) && *opt_str) { ++ err = -EINVAL; ++ skipped = 0; ++ token = match_token(opt_str, options, a->args); ++ switch (token) { ++ case Opt_br: ++ err = 0; ++ while (!err && (opt_str = strsep(&a->args[0].from, ":")) ++ && *opt_str) { ++ err = opt_add(opt, opt_str, opts->sb_flags, ++ bindex++); ++ if (unlikely(!err && ++opt > opt_tail)) { ++ err = -E2BIG; ++ break; ++ } ++ opt->type = Opt_tail; ++ skipped = 1; ++ } ++ break; ++ case Opt_add: ++ if (unlikely(match_int(&a->args[0], &n))) { ++ pr_err("bad integer in %s\n", opt_str); ++ break; ++ } ++ bindex = n; ++ err = opt_add(opt, a->args[1].from, opts->sb_flags, ++ bindex); ++ if (!err) ++ opt->type = token; ++ break; ++ case Opt_append: ++ err = opt_add(opt, a->args[0].from, opts->sb_flags, ++ /*dummy bindex*/1); ++ if (!err) ++ opt->type = token; ++ break; ++ case Opt_prepend: ++ err = opt_add(opt, a->args[0].from, opts->sb_flags, ++ /*bindex*/0); ++ if (!err) ++ opt->type = token; ++ break; ++ case Opt_del: ++ err = au_opts_parse_del(&opt->del, a->args); ++ if (!err) ++ opt->type = token; ++ break; ++#if 0 /* reserved for future use */ ++ case Opt_idel: ++ del->pathname = "(indexed)"; ++ if (unlikely(match_int(&args[0], &n))) { ++ pr_err("bad integer in %s\n", opt_str); ++ break; ++ } ++ err = au_opts_parse_idel(sb, n, &opt->del, a->args); ++ if (!err) ++ opt->type = token; ++ break; ++#endif ++ case Opt_mod: ++ err = au_opts_parse_mod(&opt->mod, a->args); ++ if (!err) ++ opt->type = token; ++ break; ++#ifdef IMOD /* reserved for future use */ ++ case Opt_imod: ++ u.mod->path = "(indexed)"; ++ if (unlikely(match_int(&a->args[0], &n))) { ++ pr_err("bad integer in %s\n", opt_str); ++ break; ++ } ++ err = au_opts_parse_imod(sb, n, &opt->mod, a->args); ++ if (!err) ++ opt->type = token; ++ break; ++#endif ++ case Opt_xino: ++ err = au_opts_parse_xino(sb, &opt->xino, a->args); ++ if (!err) ++ opt->type = token; ++ break; ++ ++ case Opt_trunc_xino_path: ++ err = au_opts_parse_xino_itrunc_path ++ (sb, &opt->xino_itrunc, a->args); ++ if (!err) ++ opt->type = token; ++ break; ++ ++ case Opt_itrunc_xino: ++ u.xino_itrunc = &opt->xino_itrunc; ++ if (unlikely(match_int(&a->args[0], &n))) { ++ pr_err("bad integer in %s\n", opt_str); ++ break; ++ } ++ u.xino_itrunc->bindex = n; ++ aufs_read_lock(root, AuLock_FLUSH); ++ if (n < 0 || au_sbbot(sb) < n) { ++ pr_err("out of bounds, %d\n", n); ++ aufs_read_unlock(root, !AuLock_IR); ++ break; ++ } ++ aufs_read_unlock(root, !AuLock_IR); ++ err = 0; ++ opt->type = token; ++ break; ++ ++ case Opt_dirwh: ++ if (unlikely(match_int(&a->args[0], &opt->dirwh))) ++ break; ++ err = 0; ++ opt->type = token; ++ break; ++ ++ case Opt_rdcache: ++ if (unlikely(match_int(&a->args[0], &n))) { ++ pr_err("bad integer in %s\n", opt_str); ++ break; ++ } ++ if (unlikely(n > AUFS_RDCACHE_MAX)) { ++ pr_err("rdcache must be smaller than %d\n", ++ AUFS_RDCACHE_MAX); ++ break; ++ } ++ opt->rdcache = n; ++ err = 0; ++ opt->type = token; ++ break; ++ case Opt_rdblk: ++ if (unlikely(match_int(&a->args[0], &n) ++ || n < 0 ++ || n > KMALLOC_MAX_SIZE)) { ++ pr_err("bad integer in %s\n", opt_str); ++ break; ++ } ++ if (unlikely(n && n < NAME_MAX)) { ++ pr_err("rdblk must be larger than %d\n", ++ NAME_MAX); ++ break; ++ } ++ opt->rdblk = n; ++ err = 0; ++ opt->type = token; ++ break; ++ case Opt_rdhash: ++ if (unlikely(match_int(&a->args[0], &n) ++ || n < 0 ++ || n * sizeof(struct hlist_head) ++ > KMALLOC_MAX_SIZE)) { ++ pr_err("bad integer in %s\n", opt_str); ++ break; ++ } ++ opt->rdhash = n; ++ err = 0; ++ opt->type = token; ++ break; ++ ++ case Opt_trunc_xino: ++ case Opt_notrunc_xino: ++ case Opt_noxino: ++ case Opt_trunc_xib: ++ case Opt_notrunc_xib: ++ case Opt_shwh: ++ case Opt_noshwh: ++ case Opt_dirperm1: ++ case Opt_nodirperm1: ++ case Opt_plink: ++ case Opt_noplink: ++ case Opt_list_plink: ++ case Opt_dio: ++ case Opt_nodio: ++ case Opt_diropq_a: ++ case Opt_diropq_w: ++ case Opt_warn_perm: ++ case Opt_nowarn_perm: ++ case Opt_verbose: ++ case Opt_noverbose: ++ case Opt_sum: ++ case Opt_nosum: ++ case Opt_wsum: ++ case Opt_rdblk_def: ++ case Opt_rdhash_def: ++ case Opt_dirren: ++ case Opt_nodirren: ++ case Opt_acl: ++ case Opt_noacl: ++ err = 0; ++ opt->type = token; ++ break; ++ ++ case Opt_udba: ++ opt->udba = udba_val(a->args[0].from); ++ if (opt->udba >= 0) { ++ err = 0; ++ opt->type = token; ++ } else ++ pr_err("wrong value, %s\n", opt_str); ++ break; ++ ++ case Opt_wbr_create: ++ u.create = &opt->wbr_create; ++ u.create->wbr_create ++ = au_wbr_create_val(a->args[0].from, u.create); ++ if (u.create->wbr_create >= 0) { ++ err = 0; ++ opt->type = token; ++ } else ++ pr_err("wrong value, %s\n", opt_str); ++ break; ++ case Opt_wbr_copyup: ++ opt->wbr_copyup = au_wbr_copyup_val(a->args[0].from); ++ if (opt->wbr_copyup >= 0) { ++ err = 0; ++ opt->type = token; ++ } else ++ pr_err("wrong value, %s\n", opt_str); ++ break; ++ ++ case Opt_fhsm_sec: ++ if (unlikely(match_int(&a->args[0], &n) ++ || n < 0)) { ++ pr_err("bad integer in %s\n", opt_str); ++ break; ++ } ++ if (sysaufs_brs) { ++ opt->fhsm_second = n; ++ opt->type = token; ++ } else ++ pr_warn("ignored %s\n", opt_str); ++ err = 0; ++ break; ++ ++ case Opt_ignore: ++ pr_warn("ignored %s\n", opt_str); ++ /*FALLTHROUGH*/ ++ case Opt_ignore_silent: ++ skipped = 1; ++ err = 0; ++ break; ++ case Opt_err: ++ pr_err("unknown option %s\n", opt_str); ++ break; ++ } ++ ++ if (!err && !skipped) { ++ if (unlikely(++opt > opt_tail)) { ++ err = -E2BIG; ++ opt--; ++ opt->type = Opt_tail; ++ break; ++ } ++ opt->type = Opt_tail; ++ } ++ } ++ ++ au_kfree_rcu(a); ++ dump_opts(opts); ++ if (unlikely(err)) ++ au_opts_free(opts); ++ ++out: ++ return err; ++} ++ ++static int au_opt_wbr_create(struct super_block *sb, ++ struct au_opt_wbr_create *create) ++{ ++ int err; ++ struct au_sbinfo *sbinfo; ++ ++ SiMustWriteLock(sb); ++ ++ err = 1; /* handled */ ++ sbinfo = au_sbi(sb); ++ if (sbinfo->si_wbr_create_ops->fin) { ++ err = sbinfo->si_wbr_create_ops->fin(sb); ++ if (!err) ++ err = 1; ++ } ++ ++ sbinfo->si_wbr_create = create->wbr_create; ++ sbinfo->si_wbr_create_ops = au_wbr_create_ops + create->wbr_create; ++ switch (create->wbr_create) { ++ case AuWbrCreate_MFSRRV: ++ case AuWbrCreate_MFSRR: ++ case AuWbrCreate_TDMFS: ++ case AuWbrCreate_TDMFSV: ++ case AuWbrCreate_PMFSRR: ++ case AuWbrCreate_PMFSRRV: ++ sbinfo->si_wbr_mfs.mfsrr_watermark = create->mfsrr_watermark; ++ /*FALLTHROUGH*/ ++ case AuWbrCreate_MFS: ++ case AuWbrCreate_MFSV: ++ case AuWbrCreate_PMFS: ++ case AuWbrCreate_PMFSV: ++ sbinfo->si_wbr_mfs.mfs_expire ++ = msecs_to_jiffies(create->mfs_second * MSEC_PER_SEC); ++ break; ++ } ++ ++ if (sbinfo->si_wbr_create_ops->init) ++ sbinfo->si_wbr_create_ops->init(sb); /* ignore */ ++ ++ return err; ++} ++ ++/* ++ * returns, ++ * plus: processed without an error ++ * zero: unprocessed ++ */ ++static int au_opt_simple(struct super_block *sb, struct au_opt *opt, ++ struct au_opts *opts) ++{ ++ int err; ++ struct au_sbinfo *sbinfo; ++ ++ SiMustWriteLock(sb); ++ ++ err = 1; /* handled */ ++ sbinfo = au_sbi(sb); ++ switch (opt->type) { ++ case Opt_udba: ++ sbinfo->si_mntflags &= ~AuOptMask_UDBA; ++ sbinfo->si_mntflags |= opt->udba; ++ opts->given_udba |= opt->udba; ++ break; ++ ++ case Opt_plink: ++ au_opt_set(sbinfo->si_mntflags, PLINK); ++ break; ++ case Opt_noplink: ++ if (au_opt_test(sbinfo->si_mntflags, PLINK)) ++ au_plink_put(sb, /*verbose*/1); ++ au_opt_clr(sbinfo->si_mntflags, PLINK); ++ break; ++ case Opt_list_plink: ++ if (au_opt_test(sbinfo->si_mntflags, PLINK)) ++ au_plink_list(sb); ++ break; ++ ++ case Opt_dio: ++ au_opt_set(sbinfo->si_mntflags, DIO); ++ au_fset_opts(opts->flags, REFRESH_DYAOP); ++ break; ++ case Opt_nodio: ++ au_opt_clr(sbinfo->si_mntflags, DIO); ++ au_fset_opts(opts->flags, REFRESH_DYAOP); ++ break; ++ ++ case Opt_fhsm_sec: ++ au_fhsm_set(sbinfo, opt->fhsm_second); ++ break; ++ ++ case Opt_diropq_a: ++ au_opt_set(sbinfo->si_mntflags, ALWAYS_DIROPQ); ++ break; ++ case Opt_diropq_w: ++ au_opt_clr(sbinfo->si_mntflags, ALWAYS_DIROPQ); ++ break; ++ ++ case Opt_warn_perm: ++ au_opt_set(sbinfo->si_mntflags, WARN_PERM); ++ break; ++ case Opt_nowarn_perm: ++ au_opt_clr(sbinfo->si_mntflags, WARN_PERM); ++ break; ++ ++ case Opt_verbose: ++ au_opt_set(sbinfo->si_mntflags, VERBOSE); ++ break; ++ case Opt_noverbose: ++ au_opt_clr(sbinfo->si_mntflags, VERBOSE); ++ break; ++ ++ case Opt_sum: ++ au_opt_set(sbinfo->si_mntflags, SUM); ++ break; ++ case Opt_wsum: ++ au_opt_clr(sbinfo->si_mntflags, SUM); ++ au_opt_set(sbinfo->si_mntflags, SUM_W); ++ break; ++ case Opt_nosum: ++ au_opt_clr(sbinfo->si_mntflags, SUM); ++ au_opt_clr(sbinfo->si_mntflags, SUM_W); ++ break; ++ ++ case Opt_wbr_create: ++ err = au_opt_wbr_create(sb, &opt->wbr_create); ++ break; ++ case Opt_wbr_copyup: ++ sbinfo->si_wbr_copyup = opt->wbr_copyup; ++ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + opt->wbr_copyup; ++ break; ++ ++ case Opt_dirwh: ++ sbinfo->si_dirwh = opt->dirwh; ++ break; ++ ++ case Opt_rdcache: ++ sbinfo->si_rdcache ++ = msecs_to_jiffies(opt->rdcache * MSEC_PER_SEC); ++ break; ++ case Opt_rdblk: ++ sbinfo->si_rdblk = opt->rdblk; ++ break; ++ case Opt_rdblk_def: ++ sbinfo->si_rdblk = AUFS_RDBLK_DEF; ++ break; ++ case Opt_rdhash: ++ sbinfo->si_rdhash = opt->rdhash; ++ break; ++ case Opt_rdhash_def: ++ sbinfo->si_rdhash = AUFS_RDHASH_DEF; ++ break; ++ ++ case Opt_shwh: ++ au_opt_set(sbinfo->si_mntflags, SHWH); ++ break; ++ case Opt_noshwh: ++ au_opt_clr(sbinfo->si_mntflags, SHWH); ++ break; ++ ++ case Opt_dirperm1: ++ au_opt_set(sbinfo->si_mntflags, DIRPERM1); ++ break; ++ case Opt_nodirperm1: ++ au_opt_clr(sbinfo->si_mntflags, DIRPERM1); ++ break; ++ ++ case Opt_trunc_xino: ++ au_opt_set(sbinfo->si_mntflags, TRUNC_XINO); ++ break; ++ case Opt_notrunc_xino: ++ au_opt_clr(sbinfo->si_mntflags, TRUNC_XINO); ++ break; ++ ++ case Opt_trunc_xino_path: ++ case Opt_itrunc_xino: ++ err = au_xino_trunc(sb, opt->xino_itrunc.bindex, ++ /*idx_begin*/0); ++ if (!err) ++ err = 1; ++ break; ++ ++ case Opt_trunc_xib: ++ au_fset_opts(opts->flags, TRUNC_XIB); ++ break; ++ case Opt_notrunc_xib: ++ au_fclr_opts(opts->flags, TRUNC_XIB); ++ break; ++ ++ case Opt_dirren: ++ err = 1; ++ if (!au_opt_test(sbinfo->si_mntflags, DIRREN)) { ++ err = au_dr_opt_set(sb); ++ if (!err) ++ err = 1; ++ } ++ if (err == 1) ++ au_opt_set(sbinfo->si_mntflags, DIRREN); ++ break; ++ case Opt_nodirren: ++ err = 1; ++ if (au_opt_test(sbinfo->si_mntflags, DIRREN)) { ++ err = au_dr_opt_clr(sb, au_ftest_opts(opts->flags, ++ DR_FLUSHED)); ++ if (!err) ++ err = 1; ++ } ++ if (err == 1) ++ au_opt_clr(sbinfo->si_mntflags, DIRREN); ++ break; ++ ++ case Opt_acl: ++ sb->s_flags |= SB_POSIXACL; ++ break; ++ case Opt_noacl: ++ sb->s_flags &= ~SB_POSIXACL; ++ break; ++ ++ default: ++ err = 0; ++ break; ++ } ++ ++ return err; ++} ++ ++/* ++ * returns tri-state. ++ * plus: processed without an error ++ * zero: unprocessed ++ * minus: error ++ */ ++static int au_opt_br(struct super_block *sb, struct au_opt *opt, ++ struct au_opts *opts) ++{ ++ int err, do_refresh; ++ ++ err = 0; ++ switch (opt->type) { ++ case Opt_append: ++ opt->add.bindex = au_sbbot(sb) + 1; ++ if (opt->add.bindex < 0) ++ opt->add.bindex = 0; ++ goto add; ++ /* Always goto add, not fallthrough */ ++ case Opt_prepend: ++ opt->add.bindex = 0; ++ /* fallthrough */ ++ add: /* indented label */ ++ case Opt_add: ++ err = au_br_add(sb, &opt->add, ++ au_ftest_opts(opts->flags, REMOUNT)); ++ if (!err) { ++ err = 1; ++ au_fset_opts(opts->flags, REFRESH); ++ } ++ break; ++ ++ case Opt_del: ++ case Opt_idel: ++ err = au_br_del(sb, &opt->del, ++ au_ftest_opts(opts->flags, REMOUNT)); ++ if (!err) { ++ err = 1; ++ au_fset_opts(opts->flags, TRUNC_XIB); ++ au_fset_opts(opts->flags, REFRESH); ++ } ++ break; ++ ++ case Opt_mod: ++ case Opt_imod: ++ err = au_br_mod(sb, &opt->mod, ++ au_ftest_opts(opts->flags, REMOUNT), ++ &do_refresh); ++ if (!err) { ++ err = 1; ++ if (do_refresh) ++ au_fset_opts(opts->flags, REFRESH); ++ } ++ break; ++ } ++ return err; ++} ++ ++static int au_opt_xino(struct super_block *sb, struct au_opt *opt, ++ struct au_opt_xino **opt_xino, ++ struct au_opts *opts) ++{ ++ int err; ++ ++ err = 0; ++ switch (opt->type) { ++ case Opt_xino: ++ err = au_xino_set(sb, &opt->xino, ++ !!au_ftest_opts(opts->flags, REMOUNT)); ++ if (unlikely(err)) ++ break; ++ ++ *opt_xino = &opt->xino; ++ break; ++ ++ case Opt_noxino: ++ au_xino_clr(sb); ++ *opt_xino = (void *)-1; ++ break; ++ } ++ ++ return err; ++} ++ ++int au_opts_verify(struct super_block *sb, unsigned long sb_flags, ++ unsigned int pending) ++{ ++ int err, fhsm; ++ aufs_bindex_t bindex, bbot; ++ unsigned char do_plink, skip, do_free, can_no_dreval; ++ struct au_branch *br; ++ struct au_wbr *wbr; ++ struct dentry *root, *dentry; ++ struct inode *dir, *h_dir; ++ struct au_sbinfo *sbinfo; ++ struct au_hinode *hdir; ++ ++ SiMustAnyLock(sb); ++ ++ sbinfo = au_sbi(sb); ++ AuDebugOn(!(sbinfo->si_mntflags & AuOptMask_UDBA)); ++ ++ if (!(sb_flags & SB_RDONLY)) { ++ if (unlikely(!au_br_writable(au_sbr_perm(sb, 0)))) ++ pr_warn("first branch should be rw\n"); ++ if (unlikely(au_opt_test(sbinfo->si_mntflags, SHWH))) ++ pr_warn_once("shwh should be used with ro\n"); ++ } ++ ++ if (au_opt_test((sbinfo->si_mntflags | pending), UDBA_HNOTIFY) ++ && !au_opt_test(sbinfo->si_mntflags, XINO)) ++ pr_warn_once("udba=*notify requires xino\n"); ++ ++ if (au_opt_test(sbinfo->si_mntflags, DIRPERM1)) ++ pr_warn_once("dirperm1 breaks the protection" ++ " by the permission bits on the lower branch\n"); ++ ++ err = 0; ++ fhsm = 0; ++ root = sb->s_root; ++ dir = d_inode(root); ++ do_plink = !!au_opt_test(sbinfo->si_mntflags, PLINK); ++ can_no_dreval = !!au_opt_test((sbinfo->si_mntflags | pending), ++ UDBA_NONE); ++ bbot = au_sbbot(sb); ++ for (bindex = 0; !err && bindex <= bbot; bindex++) { ++ skip = 0; ++ h_dir = au_h_iptr(dir, bindex); ++ br = au_sbr(sb, bindex); ++ ++ if ((br->br_perm & AuBrAttr_ICEX) ++ && !h_dir->i_op->listxattr) ++ br->br_perm &= ~AuBrAttr_ICEX; ++#if 0 ++ if ((br->br_perm & AuBrAttr_ICEX_SEC) ++ && (au_br_sb(br)->s_flags & SB_NOSEC)) ++ br->br_perm &= ~AuBrAttr_ICEX_SEC; ++#endif ++ ++ do_free = 0; ++ wbr = br->br_wbr; ++ if (wbr) ++ wbr_wh_read_lock(wbr); ++ ++ if (!au_br_writable(br->br_perm)) { ++ do_free = !!wbr; ++ skip = (!wbr ++ || (!wbr->wbr_whbase ++ && !wbr->wbr_plink ++ && !wbr->wbr_orph)); ++ } else if (!au_br_wh_linkable(br->br_perm)) { ++ /* skip = (!br->br_whbase && !br->br_orph); */ ++ skip = (!wbr || !wbr->wbr_whbase); ++ if (skip && wbr) { ++ if (do_plink) ++ skip = !!wbr->wbr_plink; ++ else ++ skip = !wbr->wbr_plink; ++ } ++ } else { ++ /* skip = (br->br_whbase && br->br_ohph); */ ++ skip = (wbr && wbr->wbr_whbase); ++ if (skip) { ++ if (do_plink) ++ skip = !!wbr->wbr_plink; ++ else ++ skip = !wbr->wbr_plink; ++ } ++ } ++ if (wbr) ++ wbr_wh_read_unlock(wbr); ++ ++ if (can_no_dreval) { ++ dentry = br->br_path.dentry; ++ spin_lock(&dentry->d_lock); ++ if (dentry->d_flags & ++ (DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE)) ++ can_no_dreval = 0; ++ spin_unlock(&dentry->d_lock); ++ } ++ ++ if (au_br_fhsm(br->br_perm)) { ++ fhsm++; ++ AuDebugOn(!br->br_fhsm); ++ } ++ ++ if (skip) ++ continue; ++ ++ hdir = au_hi(dir, bindex); ++ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT); ++ if (wbr) ++ wbr_wh_write_lock(wbr); ++ err = au_wh_init(br, sb); ++ if (wbr) ++ wbr_wh_write_unlock(wbr); ++ au_hn_inode_unlock(hdir); ++ ++ if (!err && do_free) { ++ au_kfree_rcu(wbr); ++ br->br_wbr = NULL; ++ } ++ } ++ ++ if (can_no_dreval) ++ au_fset_si(sbinfo, NO_DREVAL); ++ else ++ au_fclr_si(sbinfo, NO_DREVAL); ++ ++ if (fhsm >= 2) { ++ au_fset_si(sbinfo, FHSM); ++ for (bindex = bbot; bindex >= 0; bindex--) { ++ br = au_sbr(sb, bindex); ++ if (au_br_fhsm(br->br_perm)) { ++ au_fhsm_set_bottom(sb, bindex); ++ break; ++ } ++ } ++ } else { ++ au_fclr_si(sbinfo, FHSM); ++ au_fhsm_set_bottom(sb, -1); ++ } ++ ++ return err; ++} ++ ++int au_opts_mount(struct super_block *sb, struct au_opts *opts) ++{ ++ int err; ++ unsigned int tmp; ++ aufs_bindex_t bindex, bbot; ++ struct au_opt *opt; ++ struct au_opt_xino *opt_xino, xino; ++ struct au_sbinfo *sbinfo; ++ struct au_branch *br; ++ struct inode *dir; ++ ++ SiMustWriteLock(sb); ++ ++ err = 0; ++ opt_xino = NULL; ++ opt = opts->opt; ++ while (err >= 0 && opt->type != Opt_tail) ++ err = au_opt_simple(sb, opt++, opts); ++ if (err > 0) ++ err = 0; ++ else if (unlikely(err < 0)) ++ goto out; ++ ++ /* disable xino and udba temporary */ ++ sbinfo = au_sbi(sb); ++ tmp = sbinfo->si_mntflags; ++ au_opt_clr(sbinfo->si_mntflags, XINO); ++ au_opt_set_udba(sbinfo->si_mntflags, UDBA_REVAL); ++ ++ opt = opts->opt; ++ while (err >= 0 && opt->type != Opt_tail) ++ err = au_opt_br(sb, opt++, opts); ++ if (err > 0) ++ err = 0; ++ else if (unlikely(err < 0)) ++ goto out; ++ ++ bbot = au_sbbot(sb); ++ if (unlikely(bbot < 0)) { ++ err = -EINVAL; ++ pr_err("no branches\n"); ++ goto out; ++ } ++ ++ if (au_opt_test(tmp, XINO)) ++ au_opt_set(sbinfo->si_mntflags, XINO); ++ opt = opts->opt; ++ while (!err && opt->type != Opt_tail) ++ err = au_opt_xino(sb, opt++, &opt_xino, opts); ++ if (unlikely(err)) ++ goto out; ++ ++ err = au_opts_verify(sb, sb->s_flags, tmp); ++ if (unlikely(err)) ++ goto out; ++ ++ /* restore xino */ ++ if (au_opt_test(tmp, XINO) && !opt_xino) { ++ xino.file = au_xino_def(sb); ++ err = PTR_ERR(xino.file); ++ if (IS_ERR(xino.file)) ++ goto out; ++ ++ err = au_xino_set(sb, &xino, /*remount*/0); ++ fput(xino.file); ++ if (unlikely(err)) ++ goto out; ++ } ++ ++ /* restore udba */ ++ tmp &= AuOptMask_UDBA; ++ sbinfo->si_mntflags &= ~AuOptMask_UDBA; ++ sbinfo->si_mntflags |= tmp; ++ bbot = au_sbbot(sb); ++ for (bindex = 0; bindex <= bbot; bindex++) { ++ br = au_sbr(sb, bindex); ++ err = au_hnotify_reset_br(tmp, br, br->br_perm); ++ if (unlikely(err)) ++ AuIOErr("hnotify failed on br %d, %d, ignored\n", ++ bindex, err); ++ /* go on even if err */ ++ } ++ if (au_opt_test(tmp, UDBA_HNOTIFY)) { ++ dir = d_inode(sb->s_root); ++ au_hn_reset(dir, au_hi_flags(dir, /*isdir*/1) & ~AuHi_XINO); ++ } ++ ++out: ++ return err; ++} ++ ++int au_opts_remount(struct super_block *sb, struct au_opts *opts) ++{ ++ int err, rerr; ++ unsigned char no_dreval; ++ struct inode *dir; ++ struct au_opt_xino *opt_xino; ++ struct au_opt *opt; ++ struct au_sbinfo *sbinfo; ++ ++ SiMustWriteLock(sb); ++ ++ err = au_dr_opt_flush(sb); ++ if (unlikely(err)) ++ goto out; ++ au_fset_opts(opts->flags, DR_FLUSHED); ++ ++ dir = d_inode(sb->s_root); ++ sbinfo = au_sbi(sb); ++ opt_xino = NULL; ++ opt = opts->opt; ++ while (err >= 0 && opt->type != Opt_tail) { ++ err = au_opt_simple(sb, opt, opts); ++ if (!err) ++ err = au_opt_br(sb, opt, opts); ++ if (!err) ++ err = au_opt_xino(sb, opt, &opt_xino, opts); ++ opt++; ++ } ++ if (err > 0) ++ err = 0; ++ AuTraceErr(err); ++ /* go on even err */ ++ ++ no_dreval = !!au_ftest_si(sbinfo, NO_DREVAL); ++ rerr = au_opts_verify(sb, opts->sb_flags, /*pending*/0); ++ if (unlikely(rerr && !err)) ++ err = rerr; ++ ++ if (no_dreval != !!au_ftest_si(sbinfo, NO_DREVAL)) ++ au_fset_opts(opts->flags, REFRESH_IDOP); ++ ++ if (au_ftest_opts(opts->flags, TRUNC_XIB)) { ++ rerr = au_xib_trunc(sb); ++ if (unlikely(rerr && !err)) ++ err = rerr; ++ } ++ ++ /* will be handled by the caller */ ++ if (!au_ftest_opts(opts->flags, REFRESH) ++ && (opts->given_udba ++ || au_opt_test(sbinfo->si_mntflags, XINO) ++ || au_ftest_opts(opts->flags, REFRESH_IDOP) ++ )) ++ au_fset_opts(opts->flags, REFRESH); ++ ++ AuDbg("status 0x%x\n", opts->flags); ++ ++out: ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++unsigned int au_opt_udba(struct super_block *sb) ++{ ++ return au_mntflags(sb) & AuOptMask_UDBA; ++} +diff -Nurp linux-5.4/fs/aufs/opts.h linux-5.4-aufs/fs/aufs/opts.h +--- linux-5.4/fs/aufs/opts.h 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/opts.h 2019-11-28 01:25:59.067925618 +0200 +@@ -0,0 +1,212 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * mount options/flags ++ */ ++ ++#ifndef __AUFS_OPTS_H__ ++#define __AUFS_OPTS_H__ ++ ++#ifdef __KERNEL__ ++ ++#include ++ ++struct file; ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* mount flags */ ++#define AuOpt_XINO 1 /* external inode number bitmap ++ and translation table */ ++#define AuOpt_TRUNC_XINO (1 << 1) /* truncate xino files */ ++#define AuOpt_UDBA_NONE (1 << 2) /* users direct branch access */ ++#define AuOpt_UDBA_REVAL (1 << 3) ++#define AuOpt_UDBA_HNOTIFY (1 << 4) ++#define AuOpt_SHWH (1 << 5) /* show whiteout */ ++#define AuOpt_PLINK (1 << 6) /* pseudo-link */ ++#define AuOpt_DIRPERM1 (1 << 7) /* ignore the lower dir's perm ++ bits */ ++#define AuOpt_ALWAYS_DIROPQ (1 << 9) /* policy to creating diropq */ ++#define AuOpt_SUM (1 << 10) /* summation for statfs(2) */ ++#define AuOpt_SUM_W (1 << 11) /* unimplemented */ ++#define AuOpt_WARN_PERM (1 << 12) /* warn when add-branch */ ++#define AuOpt_VERBOSE (1 << 13) /* print the cause of error */ ++#define AuOpt_DIO (1 << 14) /* direct io */ ++#define AuOpt_DIRREN (1 << 15) /* directory rename */ ++ ++#ifndef CONFIG_AUFS_HNOTIFY ++#undef AuOpt_UDBA_HNOTIFY ++#define AuOpt_UDBA_HNOTIFY 0 ++#endif ++#ifndef CONFIG_AUFS_DIRREN ++#undef AuOpt_DIRREN ++#define AuOpt_DIRREN 0 ++#endif ++#ifndef CONFIG_AUFS_SHWH ++#undef AuOpt_SHWH ++#define AuOpt_SHWH 0 ++#endif ++ ++#define AuOpt_Def (AuOpt_XINO \ ++ | AuOpt_UDBA_REVAL \ ++ | AuOpt_PLINK \ ++ /* | AuOpt_DIRPERM1 */ \ ++ | AuOpt_WARN_PERM) ++#define AuOptMask_UDBA (AuOpt_UDBA_NONE \ ++ | AuOpt_UDBA_REVAL \ ++ | AuOpt_UDBA_HNOTIFY) ++ ++#define au_opt_test(flags, name) (flags & AuOpt_##name) ++#define au_opt_set(flags, name) do { \ ++ BUILD_BUG_ON(AuOpt_##name & AuOptMask_UDBA); \ ++ ((flags) |= AuOpt_##name); \ ++} while (0) ++#define au_opt_set_udba(flags, name) do { \ ++ (flags) &= ~AuOptMask_UDBA; \ ++ ((flags) |= AuOpt_##name); \ ++} while (0) ++#define au_opt_clr(flags, name) do { \ ++ ((flags) &= ~AuOpt_##name); \ ++} while (0) ++ ++static inline unsigned int au_opts_plink(unsigned int mntflags) ++{ ++#ifdef CONFIG_PROC_FS ++ return mntflags; ++#else ++ return mntflags & ~AuOpt_PLINK; ++#endif ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* policies to select one among multiple writable branches */ ++enum { ++ AuWbrCreate_TDP, /* top down parent */ ++ AuWbrCreate_RR, /* round robin */ ++ AuWbrCreate_MFS, /* most free space */ ++ AuWbrCreate_MFSV, /* mfs with seconds */ ++ AuWbrCreate_MFSRR, /* mfs then rr */ ++ AuWbrCreate_MFSRRV, /* mfs then rr with seconds */ ++ AuWbrCreate_TDMFS, /* top down regardless parent and mfs */ ++ AuWbrCreate_TDMFSV, /* top down regardless parent and mfs */ ++ AuWbrCreate_PMFS, /* parent and mfs */ ++ AuWbrCreate_PMFSV, /* parent and mfs with seconds */ ++ AuWbrCreate_PMFSRR, /* parent, mfs and round-robin */ ++ AuWbrCreate_PMFSRRV, /* plus seconds */ ++ ++ AuWbrCreate_Def = AuWbrCreate_TDP ++}; ++ ++enum { ++ AuWbrCopyup_TDP, /* top down parent */ ++ AuWbrCopyup_BUP, /* bottom up parent */ ++ AuWbrCopyup_BU, /* bottom up */ ++ ++ AuWbrCopyup_Def = AuWbrCopyup_TDP ++}; ++ ++/* ---------------------------------------------------------------------- */ ++ ++struct au_opt_add { ++ aufs_bindex_t bindex; ++ char *pathname; ++ int perm; ++ struct path path; ++}; ++ ++struct au_opt_del { ++ char *pathname; ++ struct path h_path; ++}; ++ ++struct au_opt_mod { ++ char *path; ++ int perm; ++ struct dentry *h_root; ++}; ++ ++struct au_opt_xino { ++ char *path; ++ struct file *file; ++}; ++ ++struct au_opt_xino_itrunc { ++ aufs_bindex_t bindex; ++}; ++ ++struct au_opt_wbr_create { ++ int wbr_create; ++ int mfs_second; ++ unsigned long long mfsrr_watermark; ++}; ++ ++struct au_opt { ++ int type; ++ union { ++ struct au_opt_xino xino; ++ struct au_opt_xino_itrunc xino_itrunc; ++ struct au_opt_add add; ++ struct au_opt_del del; ++ struct au_opt_mod mod; ++ int dirwh; ++ int rdcache; ++ unsigned int rdblk; ++ unsigned int rdhash; ++ int udba; ++ struct au_opt_wbr_create wbr_create; ++ int wbr_copyup; ++ unsigned int fhsm_second; ++ }; ++}; ++ ++/* opts flags */ ++#define AuOpts_REMOUNT 1 ++#define AuOpts_REFRESH (1 << 1) ++#define AuOpts_TRUNC_XIB (1 << 2) ++#define AuOpts_REFRESH_DYAOP (1 << 3) ++#define AuOpts_REFRESH_IDOP (1 << 4) ++#define AuOpts_DR_FLUSHED (1 << 5) ++#define au_ftest_opts(flags, name) ((flags) & AuOpts_##name) ++#define au_fset_opts(flags, name) \ ++ do { (flags) |= AuOpts_##name; } while (0) ++#define au_fclr_opts(flags, name) \ ++ do { (flags) &= ~AuOpts_##name; } while (0) ++ ++#ifndef CONFIG_AUFS_DIRREN ++#undef AuOpts_DR_FLUSHED ++#define AuOpts_DR_FLUSHED 0 ++#endif ++ ++struct au_opts { ++ struct au_opt *opt; ++ int max_opt; ++ ++ unsigned int given_udba; ++ unsigned int flags; ++ unsigned long sb_flags; ++}; ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* opts.c */ ++void au_optstr_br_perm(au_br_perm_str_t *str, int perm); ++const char *au_optstr_udba(int udba); ++const char *au_optstr_wbr_copyup(int wbr_copyup); ++const char *au_optstr_wbr_create(int wbr_create); ++ ++void au_opts_free(struct au_opts *opts); ++struct super_block; ++int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts); ++int au_opts_verify(struct super_block *sb, unsigned long sb_flags, ++ unsigned int pending); ++int au_opts_mount(struct super_block *sb, struct au_opts *opts); ++int au_opts_remount(struct super_block *sb, struct au_opts *opts); ++ ++unsigned int au_opt_udba(struct super_block *sb); ++ ++#endif /* __KERNEL__ */ ++#endif /* __AUFS_OPTS_H__ */ +diff -Nurp linux-5.4/fs/aufs/plink.c linux-5.4-aufs/fs/aufs/plink.c +--- linux-5.4/fs/aufs/plink.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/plink.c 2019-11-28 01:25:59.067925618 +0200 +@@ -0,0 +1,503 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * pseudo-link ++ */ ++ ++#include "aufs.h" ++ ++/* ++ * the pseudo-link maintenance mode. ++ * during a user process maintains the pseudo-links, ++ * prohibit adding a new plink and branch manipulation. ++ * ++ * Flags ++ * NOPLM: ++ * For entry functions which will handle plink, and i_mutex is already held ++ * in VFS. ++ * They cannot wait and should return an error at once. ++ * Callers has to check the error. ++ * NOPLMW: ++ * For entry functions which will handle plink, but i_mutex is not held ++ * in VFS. ++ * They can wait the plink maintenance mode to finish. ++ * ++ * They behave like F_SETLK and F_SETLKW. ++ * If the caller never handle plink, then both flags are unnecessary. ++ */ ++ ++int au_plink_maint(struct super_block *sb, int flags) ++{ ++ int err; ++ pid_t pid, ppid; ++ struct task_struct *parent, *prev; ++ struct au_sbinfo *sbi; ++ ++ SiMustAnyLock(sb); ++ ++ err = 0; ++ if (!au_opt_test(au_mntflags(sb), PLINK)) ++ goto out; ++ ++ sbi = au_sbi(sb); ++ pid = sbi->si_plink_maint_pid; ++ if (!pid || pid == current->pid) ++ goto out; ++ ++ /* todo: it highly depends upon /sbin/mount.aufs */ ++ prev = NULL; ++ parent = current; ++ ppid = 0; ++ rcu_read_lock(); ++ while (1) { ++ parent = rcu_dereference(parent->real_parent); ++ if (parent == prev) ++ break; ++ ppid = task_pid_vnr(parent); ++ if (pid == ppid) { ++ rcu_read_unlock(); ++ goto out; ++ } ++ prev = parent; ++ } ++ rcu_read_unlock(); ++ ++ if (au_ftest_lock(flags, NOPLMW)) { ++ /* if there is no i_mutex lock in VFS, we don't need to wait */ ++ /* AuDebugOn(!lockdep_depth(current)); */ ++ while (sbi->si_plink_maint_pid) { ++ si_read_unlock(sb); ++ /* gave up wake_up_bit() */ ++ wait_event(sbi->si_plink_wq, !sbi->si_plink_maint_pid); ++ ++ if (au_ftest_lock(flags, FLUSH)) ++ au_nwt_flush(&sbi->si_nowait); ++ si_noflush_read_lock(sb); ++ } ++ } else if (au_ftest_lock(flags, NOPLM)) { ++ AuDbg("ppid %d, pid %d\n", ppid, pid); ++ err = -EAGAIN; ++ } ++ ++out: ++ return err; ++} ++ ++void au_plink_maint_leave(struct au_sbinfo *sbinfo) ++{ ++ spin_lock(&sbinfo->si_plink_maint_lock); ++ sbinfo->si_plink_maint_pid = 0; ++ spin_unlock(&sbinfo->si_plink_maint_lock); ++ wake_up_all(&sbinfo->si_plink_wq); ++} ++ ++int au_plink_maint_enter(struct super_block *sb) ++{ ++ int err; ++ struct au_sbinfo *sbinfo; ++ ++ err = 0; ++ sbinfo = au_sbi(sb); ++ /* make sure i am the only one in this fs */ ++ si_write_lock(sb, AuLock_FLUSH); ++ if (au_opt_test(au_mntflags(sb), PLINK)) { ++ spin_lock(&sbinfo->si_plink_maint_lock); ++ if (!sbinfo->si_plink_maint_pid) ++ sbinfo->si_plink_maint_pid = current->pid; ++ else ++ err = -EBUSY; ++ spin_unlock(&sbinfo->si_plink_maint_lock); ++ } ++ si_write_unlock(sb); ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++#ifdef CONFIG_AUFS_DEBUG ++void au_plink_list(struct super_block *sb) ++{ ++ int i; ++ struct au_sbinfo *sbinfo; ++ struct hlist_bl_head *hbl; ++ struct hlist_bl_node *pos; ++ struct au_icntnr *icntnr; ++ ++ SiMustAnyLock(sb); ++ ++ sbinfo = au_sbi(sb); ++ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK)); ++ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM)); ++ ++ for (i = 0; i < AuPlink_NHASH; i++) { ++ hbl = sbinfo->si_plink + i; ++ hlist_bl_lock(hbl); ++ hlist_bl_for_each_entry(icntnr, pos, hbl, plink) ++ AuDbg("%lu\n", icntnr->vfs_inode.i_ino); ++ hlist_bl_unlock(hbl); ++ } ++} ++#endif ++ ++/* is the inode pseudo-linked? */ ++int au_plink_test(struct inode *inode) ++{ ++ int found, i; ++ struct au_sbinfo *sbinfo; ++ struct hlist_bl_head *hbl; ++ struct hlist_bl_node *pos; ++ struct au_icntnr *icntnr; ++ ++ sbinfo = au_sbi(inode->i_sb); ++ AuRwMustAnyLock(&sbinfo->si_rwsem); ++ AuDebugOn(!au_opt_test(au_mntflags(inode->i_sb), PLINK)); ++ AuDebugOn(au_plink_maint(inode->i_sb, AuLock_NOPLM)); ++ ++ found = 0; ++ i = au_plink_hash(inode->i_ino); ++ hbl = sbinfo->si_plink + i; ++ hlist_bl_lock(hbl); ++ hlist_bl_for_each_entry(icntnr, pos, hbl, plink) ++ if (&icntnr->vfs_inode == inode) { ++ found = 1; ++ break; ++ } ++ hlist_bl_unlock(hbl); ++ return found; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * generate a name for plink. ++ * the file will be stored under AUFS_WH_PLINKDIR. ++ */ ++/* 20 is max digits length of ulong 64 */ ++#define PLINK_NAME_LEN ((20 + 1) * 2) ++ ++static int plink_name(char *name, int len, struct inode *inode, ++ aufs_bindex_t bindex) ++{ ++ int rlen; ++ struct inode *h_inode; ++ ++ h_inode = au_h_iptr(inode, bindex); ++ rlen = snprintf(name, len, "%lu.%lu", inode->i_ino, h_inode->i_ino); ++ return rlen; ++} ++ ++struct au_do_plink_lkup_args { ++ struct dentry **errp; ++ struct qstr *tgtname; ++ struct dentry *h_parent; ++ struct au_branch *br; ++}; ++ ++static struct dentry *au_do_plink_lkup(struct qstr *tgtname, ++ struct dentry *h_parent, ++ struct au_branch *br) ++{ ++ struct dentry *h_dentry; ++ struct inode *h_inode; ++ ++ h_inode = d_inode(h_parent); ++ inode_lock_shared_nested(h_inode, AuLsc_I_CHILD2); ++ h_dentry = vfsub_lkup_one(tgtname, h_parent); ++ inode_unlock_shared(h_inode); ++ return h_dentry; ++} ++ ++static void au_call_do_plink_lkup(void *args) ++{ ++ struct au_do_plink_lkup_args *a = args; ++ *a->errp = au_do_plink_lkup(a->tgtname, a->h_parent, a->br); ++} ++ ++/* lookup the plink-ed @inode under the branch at @bindex */ ++struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex) ++{ ++ struct dentry *h_dentry, *h_parent; ++ struct au_branch *br; ++ int wkq_err; ++ char a[PLINK_NAME_LEN]; ++ struct qstr tgtname = QSTR_INIT(a, 0); ++ ++ AuDebugOn(au_plink_maint(inode->i_sb, AuLock_NOPLM)); ++ ++ br = au_sbr(inode->i_sb, bindex); ++ h_parent = br->br_wbr->wbr_plink; ++ tgtname.len = plink_name(a, sizeof(a), inode, bindex); ++ ++ if (!uid_eq(current_fsuid(), GLOBAL_ROOT_UID)) { ++ struct au_do_plink_lkup_args args = { ++ .errp = &h_dentry, ++ .tgtname = &tgtname, ++ .h_parent = h_parent, ++ .br = br ++ }; ++ ++ wkq_err = au_wkq_wait(au_call_do_plink_lkup, &args); ++ if (unlikely(wkq_err)) ++ h_dentry = ERR_PTR(wkq_err); ++ } else ++ h_dentry = au_do_plink_lkup(&tgtname, h_parent, br); ++ ++ return h_dentry; ++} ++ ++/* create a pseudo-link */ ++static int do_whplink(struct qstr *tgt, struct dentry *h_parent, ++ struct dentry *h_dentry, struct au_branch *br) ++{ ++ int err; ++ struct path h_path = { ++ .mnt = au_br_mnt(br) ++ }; ++ struct inode *h_dir, *delegated; ++ ++ h_dir = d_inode(h_parent); ++ inode_lock_nested(h_dir, AuLsc_I_CHILD2); ++again: ++ h_path.dentry = vfsub_lkup_one(tgt, h_parent); ++ err = PTR_ERR(h_path.dentry); ++ if (IS_ERR(h_path.dentry)) ++ goto out; ++ ++ err = 0; ++ /* wh.plink dir is not monitored */ ++ /* todo: is it really safe? */ ++ if (d_is_positive(h_path.dentry) ++ && d_inode(h_path.dentry) != d_inode(h_dentry)) { ++ delegated = NULL; ++ err = vfsub_unlink(h_dir, &h_path, &delegated, /*force*/0); ++ if (unlikely(err == -EWOULDBLOCK)) { ++ pr_warn("cannot retry for NFSv4 delegation" ++ " for an internal unlink\n"); ++ iput(delegated); ++ } ++ dput(h_path.dentry); ++ h_path.dentry = NULL; ++ if (!err) ++ goto again; ++ } ++ if (!err && d_is_negative(h_path.dentry)) { ++ delegated = NULL; ++ err = vfsub_link(h_dentry, h_dir, &h_path, &delegated); ++ if (unlikely(err == -EWOULDBLOCK)) { ++ pr_warn("cannot retry for NFSv4 delegation" ++ " for an internal link\n"); ++ iput(delegated); ++ } ++ } ++ dput(h_path.dentry); ++ ++out: ++ inode_unlock(h_dir); ++ return err; ++} ++ ++struct do_whplink_args { ++ int *errp; ++ struct qstr *tgt; ++ struct dentry *h_parent; ++ struct dentry *h_dentry; ++ struct au_branch *br; ++}; ++ ++static void call_do_whplink(void *args) ++{ ++ struct do_whplink_args *a = args; ++ *a->errp = do_whplink(a->tgt, a->h_parent, a->h_dentry, a->br); ++} ++ ++static int whplink(struct dentry *h_dentry, struct inode *inode, ++ aufs_bindex_t bindex, struct au_branch *br) ++{ ++ int err, wkq_err; ++ struct au_wbr *wbr; ++ struct dentry *h_parent; ++ char a[PLINK_NAME_LEN]; ++ struct qstr tgtname = QSTR_INIT(a, 0); ++ ++ wbr = au_sbr(inode->i_sb, bindex)->br_wbr; ++ h_parent = wbr->wbr_plink; ++ tgtname.len = plink_name(a, sizeof(a), inode, bindex); ++ ++ /* always superio. */ ++ if (!uid_eq(current_fsuid(), GLOBAL_ROOT_UID)) { ++ struct do_whplink_args args = { ++ .errp = &err, ++ .tgt = &tgtname, ++ .h_parent = h_parent, ++ .h_dentry = h_dentry, ++ .br = br ++ }; ++ wkq_err = au_wkq_wait(call_do_whplink, &args); ++ if (unlikely(wkq_err)) ++ err = wkq_err; ++ } else ++ err = do_whplink(&tgtname, h_parent, h_dentry, br); ++ ++ return err; ++} ++ ++/* ++ * create a new pseudo-link for @h_dentry on @bindex. ++ * the linked inode is held in aufs @inode. ++ */ ++void au_plink_append(struct inode *inode, aufs_bindex_t bindex, ++ struct dentry *h_dentry) ++{ ++ struct super_block *sb; ++ struct au_sbinfo *sbinfo; ++ struct hlist_bl_head *hbl; ++ struct hlist_bl_node *pos; ++ struct au_icntnr *icntnr; ++ int found, err, cnt, i; ++ ++ sb = inode->i_sb; ++ sbinfo = au_sbi(sb); ++ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK)); ++ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM)); ++ ++ found = au_plink_test(inode); ++ if (found) ++ return; ++ ++ i = au_plink_hash(inode->i_ino); ++ hbl = sbinfo->si_plink + i; ++ au_igrab(inode); ++ ++ hlist_bl_lock(hbl); ++ hlist_bl_for_each_entry(icntnr, pos, hbl, plink) { ++ if (&icntnr->vfs_inode == inode) { ++ found = 1; ++ break; ++ } ++ } ++ if (!found) { ++ icntnr = container_of(inode, struct au_icntnr, vfs_inode); ++ hlist_bl_add_head(&icntnr->plink, hbl); ++ } ++ hlist_bl_unlock(hbl); ++ if (!found) { ++ cnt = au_hbl_count(hbl); ++#define msg "unexpectedly unbalanced or too many pseudo-links" ++ if (cnt > AUFS_PLINK_WARN) ++ AuWarn1(msg ", %d\n", cnt); ++#undef msg ++ err = whplink(h_dentry, inode, bindex, au_sbr(sb, bindex)); ++ if (unlikely(err)) { ++ pr_warn("err %d, damaged pseudo link.\n", err); ++ au_hbl_del(&icntnr->plink, hbl); ++ iput(&icntnr->vfs_inode); ++ } ++ } else ++ iput(&icntnr->vfs_inode); ++} ++ ++/* free all plinks */ ++void au_plink_put(struct super_block *sb, int verbose) ++{ ++ int i, warned; ++ struct au_sbinfo *sbinfo; ++ struct hlist_bl_head *hbl; ++ struct hlist_bl_node *pos, *tmp; ++ struct au_icntnr *icntnr; ++ ++ SiMustWriteLock(sb); ++ ++ sbinfo = au_sbi(sb); ++ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK)); ++ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM)); ++ ++ /* no spin_lock since sbinfo is write-locked */ ++ warned = 0; ++ for (i = 0; i < AuPlink_NHASH; i++) { ++ hbl = sbinfo->si_plink + i; ++ if (!warned && verbose && !hlist_bl_empty(hbl)) { ++ pr_warn("pseudo-link is not flushed"); ++ warned = 1; ++ } ++ hlist_bl_for_each_entry_safe(icntnr, pos, tmp, hbl, plink) ++ iput(&icntnr->vfs_inode); ++ INIT_HLIST_BL_HEAD(hbl); ++ } ++} ++ ++void au_plink_clean(struct super_block *sb, int verbose) ++{ ++ struct dentry *root; ++ ++ root = sb->s_root; ++ aufs_write_lock(root); ++ if (au_opt_test(au_mntflags(sb), PLINK)) ++ au_plink_put(sb, verbose); ++ aufs_write_unlock(root); ++} ++ ++static int au_plink_do_half_refresh(struct inode *inode, aufs_bindex_t br_id) ++{ ++ int do_put; ++ aufs_bindex_t btop, bbot, bindex; ++ ++ do_put = 0; ++ btop = au_ibtop(inode); ++ bbot = au_ibbot(inode); ++ if (btop >= 0) { ++ for (bindex = btop; bindex <= bbot; bindex++) { ++ if (!au_h_iptr(inode, bindex) ++ || au_ii_br_id(inode, bindex) != br_id) ++ continue; ++ au_set_h_iptr(inode, bindex, NULL, 0); ++ do_put = 1; ++ break; ++ } ++ if (do_put) ++ for (bindex = btop; bindex <= bbot; bindex++) ++ if (au_h_iptr(inode, bindex)) { ++ do_put = 0; ++ break; ++ } ++ } else ++ do_put = 1; ++ ++ return do_put; ++} ++ ++/* free the plinks on a branch specified by @br_id */ ++void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id) ++{ ++ struct au_sbinfo *sbinfo; ++ struct hlist_bl_head *hbl; ++ struct hlist_bl_node *pos, *tmp; ++ struct au_icntnr *icntnr; ++ struct inode *inode; ++ int i, do_put; ++ ++ SiMustWriteLock(sb); ++ ++ sbinfo = au_sbi(sb); ++ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK)); ++ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM)); ++ ++ /* no bit_lock since sbinfo is write-locked */ ++ for (i = 0; i < AuPlink_NHASH; i++) { ++ hbl = sbinfo->si_plink + i; ++ hlist_bl_for_each_entry_safe(icntnr, pos, tmp, hbl, plink) { ++ inode = au_igrab(&icntnr->vfs_inode); ++ ii_write_lock_child(inode); ++ do_put = au_plink_do_half_refresh(inode, br_id); ++ if (do_put) { ++ hlist_bl_del(&icntnr->plink); ++ iput(inode); ++ } ++ ii_write_unlock(inode); ++ iput(inode); ++ } ++ } ++} +diff -Nurp linux-5.4/fs/aufs/poll.c linux-5.4-aufs/fs/aufs/poll.c +--- linux-5.4/fs/aufs/poll.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/poll.c 2019-11-28 01:25:59.067925618 +0200 +@@ -0,0 +1,38 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * poll operation ++ * There is only one filesystem which implements ->poll operation, currently. ++ */ ++ ++#include "aufs.h" ++ ++__poll_t aufs_poll(struct file *file, struct poll_table_struct *pt) ++{ ++ __poll_t mask; ++ struct file *h_file; ++ struct super_block *sb; ++ ++ /* We should pretend an error happened. */ ++ mask = EPOLLERR /* | EPOLLIN | EPOLLOUT */; ++ sb = file->f_path.dentry->d_sb; ++ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); ++ ++ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0); ++ if (IS_ERR(h_file)) { ++ AuDbg("h_file %ld\n", PTR_ERR(h_file)); ++ goto out; ++ } ++ ++ mask = vfs_poll(h_file, pt); ++ fput(h_file); /* instead of au_read_post() */ ++ ++out: ++ si_read_unlock(sb); ++ if (mask & EPOLLERR) ++ AuDbg("mask 0x%x\n", mask); ++ return mask; ++} +diff -Nurp linux-5.4/fs/aufs/posix_acl.c linux-5.4-aufs/fs/aufs/posix_acl.c +--- linux-5.4/fs/aufs/posix_acl.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/posix_acl.c 2019-11-28 01:25:59.067925618 +0200 +@@ -0,0 +1,92 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2014-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * posix acl operations ++ */ ++ ++#include ++#include "aufs.h" ++ ++struct posix_acl *aufs_get_acl(struct inode *inode, int type) ++{ ++ struct posix_acl *acl; ++ int err; ++ aufs_bindex_t bindex; ++ struct inode *h_inode; ++ struct super_block *sb; ++ ++ acl = NULL; ++ sb = inode->i_sb; ++ si_read_lock(sb, AuLock_FLUSH); ++ ii_read_lock_child(inode); ++ if (!(sb->s_flags & SB_POSIXACL)) ++ goto out; ++ ++ bindex = au_ibtop(inode); ++ h_inode = au_h_iptr(inode, bindex); ++ if (unlikely(!h_inode ++ || ((h_inode->i_mode & S_IFMT) ++ != (inode->i_mode & S_IFMT)))) { ++ err = au_busy_or_stale(); ++ acl = ERR_PTR(err); ++ goto out; ++ } ++ ++ /* always topmost only */ ++ acl = get_acl(h_inode, type); ++ if (IS_ERR(acl)) ++ forget_cached_acl(inode, type); ++ else ++ set_cached_acl(inode, type, acl); ++ ++out: ++ ii_read_unlock(inode); ++ si_read_unlock(sb); ++ ++ AuTraceErrPtr(acl); ++ return acl; ++} ++ ++int aufs_set_acl(struct inode *inode, struct posix_acl *acl, int type) ++{ ++ int err; ++ ssize_t ssz; ++ struct dentry *dentry; ++ struct au_sxattr arg = { ++ .type = AU_ACL_SET, ++ .u.acl_set = { ++ .acl = acl, ++ .type = type ++ }, ++ }; ++ ++ IMustLock(inode); ++ ++ if (inode->i_ino == AUFS_ROOT_INO) ++ dentry = dget(inode->i_sb->s_root); ++ else { ++ dentry = d_find_alias(inode); ++ if (!dentry) ++ dentry = d_find_any_alias(inode); ++ if (!dentry) { ++ pr_warn("cannot handle this inode, " ++ "please report to aufs-users ML\n"); ++ err = -ENOENT; ++ goto out; ++ } ++ } ++ ++ ssz = au_sxattr(dentry, inode, &arg); ++ /* forget even it if succeeds since the branch might set differently */ ++ forget_cached_acl(inode, type); ++ dput(dentry); ++ err = ssz; ++ if (ssz >= 0) ++ err = 0; ++ ++out: ++ return err; ++} +diff -Nurp linux-5.4/fs/aufs/procfs.c linux-5.4-aufs/fs/aufs/procfs.c +--- linux-5.4/fs/aufs/procfs.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/procfs.c 2019-11-28 01:25:59.067925618 +0200 +@@ -0,0 +1,158 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2010-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * procfs interfaces ++ */ ++ ++#include ++#include "aufs.h" ++ ++static int au_procfs_plm_release(struct inode *inode, struct file *file) ++{ ++ struct au_sbinfo *sbinfo; ++ ++ sbinfo = file->private_data; ++ if (sbinfo) { ++ au_plink_maint_leave(sbinfo); ++ kobject_put(&sbinfo->si_kobj); ++ } ++ ++ return 0; ++} ++ ++static void au_procfs_plm_write_clean(struct file *file) ++{ ++ struct au_sbinfo *sbinfo; ++ ++ sbinfo = file->private_data; ++ if (sbinfo) ++ au_plink_clean(sbinfo->si_sb, /*verbose*/0); ++} ++ ++static int au_procfs_plm_write_si(struct file *file, unsigned long id) ++{ ++ int err; ++ struct super_block *sb; ++ struct au_sbinfo *sbinfo; ++ struct hlist_bl_node *pos; ++ ++ err = -EBUSY; ++ if (unlikely(file->private_data)) ++ goto out; ++ ++ sb = NULL; ++ /* don't use au_sbilist_lock() here */ ++ hlist_bl_lock(&au_sbilist); ++ hlist_bl_for_each_entry(sbinfo, pos, &au_sbilist, si_list) ++ if (id == sysaufs_si_id(sbinfo)) { ++ if (kobject_get_unless_zero(&sbinfo->si_kobj)) ++ sb = sbinfo->si_sb; ++ break; ++ } ++ hlist_bl_unlock(&au_sbilist); ++ ++ err = -EINVAL; ++ if (unlikely(!sb)) ++ goto out; ++ ++ err = au_plink_maint_enter(sb); ++ if (!err) ++ /* keep kobject_get() */ ++ file->private_data = sbinfo; ++ else ++ kobject_put(&sbinfo->si_kobj); ++out: ++ return err; ++} ++ ++/* ++ * Accept a valid "si=xxxx" only. ++ * Once it is accepted successfully, accept "clean" too. ++ */ ++static ssize_t au_procfs_plm_write(struct file *file, const char __user *ubuf, ++ size_t count, loff_t *ppos) ++{ ++ ssize_t err; ++ unsigned long id; ++ /* last newline is allowed */ ++ char buf[3 + sizeof(unsigned long) * 2 + 1]; ++ ++ err = -EACCES; ++ if (unlikely(!capable(CAP_SYS_ADMIN))) ++ goto out; ++ ++ err = -EINVAL; ++ if (unlikely(count > sizeof(buf))) ++ goto out; ++ ++ err = copy_from_user(buf, ubuf, count); ++ if (unlikely(err)) { ++ err = -EFAULT; ++ goto out; ++ } ++ buf[count] = 0; ++ ++ err = -EINVAL; ++ if (!strcmp("clean", buf)) { ++ au_procfs_plm_write_clean(file); ++ goto out_success; ++ } else if (unlikely(strncmp("si=", buf, 3))) ++ goto out; ++ ++ err = kstrtoul(buf + 3, 16, &id); ++ if (unlikely(err)) ++ goto out; ++ ++ err = au_procfs_plm_write_si(file, id); ++ if (unlikely(err)) ++ goto out; ++ ++out_success: ++ err = count; /* success */ ++out: ++ return err; ++} ++ ++static const struct file_operations au_procfs_plm_fop = { ++ .write = au_procfs_plm_write, ++ .release = au_procfs_plm_release, ++ .owner = THIS_MODULE ++}; ++ ++/* ---------------------------------------------------------------------- */ ++ ++static struct proc_dir_entry *au_procfs_dir; ++ ++void au_procfs_fin(void) ++{ ++ remove_proc_entry(AUFS_PLINK_MAINT_NAME, au_procfs_dir); ++ remove_proc_entry(AUFS_PLINK_MAINT_DIR, NULL); ++} ++ ++int __init au_procfs_init(void) ++{ ++ int err; ++ struct proc_dir_entry *entry; ++ ++ err = -ENOMEM; ++ au_procfs_dir = proc_mkdir(AUFS_PLINK_MAINT_DIR, NULL); ++ if (unlikely(!au_procfs_dir)) ++ goto out; ++ ++ entry = proc_create(AUFS_PLINK_MAINT_NAME, S_IFREG | 0200, ++ au_procfs_dir, &au_procfs_plm_fop); ++ if (unlikely(!entry)) ++ goto out_dir; ++ ++ err = 0; ++ goto out; /* success */ ++ ++ ++out_dir: ++ remove_proc_entry(AUFS_PLINK_MAINT_DIR, NULL); ++out: ++ return err; ++} +diff -Nurp linux-5.4/fs/aufs/rdu.c linux-5.4-aufs/fs/aufs/rdu.c +--- linux-5.4/fs/aufs/rdu.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/rdu.c 2019-11-28 01:25:59.067925618 +0200 +@@ -0,0 +1,371 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * readdir in userspace. ++ */ ++ ++#include ++#include ++#include ++#include "aufs.h" ++ ++/* bits for struct aufs_rdu.flags */ ++#define AuRdu_CALLED 1 ++#define AuRdu_CONT (1 << 1) ++#define AuRdu_FULL (1 << 2) ++#define au_ftest_rdu(flags, name) ((flags) & AuRdu_##name) ++#define au_fset_rdu(flags, name) \ ++ do { (flags) |= AuRdu_##name; } while (0) ++#define au_fclr_rdu(flags, name) \ ++ do { (flags) &= ~AuRdu_##name; } while (0) ++ ++struct au_rdu_arg { ++ struct dir_context ctx; ++ struct aufs_rdu *rdu; ++ union au_rdu_ent_ul ent; ++ unsigned long end; ++ ++ struct super_block *sb; ++ int err; ++}; ++ ++static int au_rdu_fill(struct dir_context *ctx, const char *name, int nlen, ++ loff_t offset, u64 h_ino, unsigned int d_type) ++{ ++ int err, len; ++ struct au_rdu_arg *arg = container_of(ctx, struct au_rdu_arg, ctx); ++ struct aufs_rdu *rdu = arg->rdu; ++ struct au_rdu_ent ent; ++ ++ err = 0; ++ arg->err = 0; ++ au_fset_rdu(rdu->cookie.flags, CALLED); ++ len = au_rdu_len(nlen); ++ if (arg->ent.ul + len < arg->end) { ++ ent.ino = h_ino; ++ ent.bindex = rdu->cookie.bindex; ++ ent.type = d_type; ++ ent.nlen = nlen; ++ if (unlikely(nlen > AUFS_MAX_NAMELEN)) ++ ent.type = DT_UNKNOWN; ++ ++ /* unnecessary to support mmap_sem since this is a dir */ ++ err = -EFAULT; ++ if (copy_to_user(arg->ent.e, &ent, sizeof(ent))) ++ goto out; ++ if (copy_to_user(arg->ent.e->name, name, nlen)) ++ goto out; ++ /* the terminating NULL */ ++ if (__put_user(0, arg->ent.e->name + nlen)) ++ goto out; ++ err = 0; ++ /* AuDbg("%p, %.*s\n", arg->ent.p, nlen, name); */ ++ arg->ent.ul += len; ++ rdu->rent++; ++ } else { ++ err = -EFAULT; ++ au_fset_rdu(rdu->cookie.flags, FULL); ++ rdu->full = 1; ++ rdu->tail = arg->ent; ++ } ++ ++out: ++ /* AuTraceErr(err); */ ++ return err; ++} ++ ++static int au_rdu_do(struct file *h_file, struct au_rdu_arg *arg) ++{ ++ int err; ++ loff_t offset; ++ struct au_rdu_cookie *cookie = &arg->rdu->cookie; ++ ++ /* we don't have to care (FMODE_32BITHASH | FMODE_64BITHASH) for ext4 */ ++ offset = vfsub_llseek(h_file, cookie->h_pos, SEEK_SET); ++ err = offset; ++ if (unlikely(offset != cookie->h_pos)) ++ goto out; ++ ++ err = 0; ++ do { ++ arg->err = 0; ++ au_fclr_rdu(cookie->flags, CALLED); ++ /* smp_mb(); */ ++ err = vfsub_iterate_dir(h_file, &arg->ctx); ++ if (err >= 0) ++ err = arg->err; ++ } while (!err ++ && au_ftest_rdu(cookie->flags, CALLED) ++ && !au_ftest_rdu(cookie->flags, FULL)); ++ cookie->h_pos = h_file->f_pos; ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++static int au_rdu(struct file *file, struct aufs_rdu *rdu) ++{ ++ int err; ++ aufs_bindex_t bbot; ++ struct au_rdu_arg arg = { ++ .ctx = { ++ .actor = au_rdu_fill ++ } ++ }; ++ struct dentry *dentry; ++ struct inode *inode; ++ struct file *h_file; ++ struct au_rdu_cookie *cookie = &rdu->cookie; ++ ++ /* VERIFY_WRITE */ ++ err = !access_ok(rdu->ent.e, rdu->sz); ++ if (unlikely(err)) { ++ err = -EFAULT; ++ AuTraceErr(err); ++ goto out; ++ } ++ rdu->rent = 0; ++ rdu->tail = rdu->ent; ++ rdu->full = 0; ++ arg.rdu = rdu; ++ arg.ent = rdu->ent; ++ arg.end = arg.ent.ul; ++ arg.end += rdu->sz; ++ ++ err = -ENOTDIR; ++ if (unlikely(!file->f_op->iterate && !file->f_op->iterate_shared)) ++ goto out; ++ ++ err = security_file_permission(file, MAY_READ); ++ AuTraceErr(err); ++ if (unlikely(err)) ++ goto out; ++ ++ dentry = file->f_path.dentry; ++ inode = d_inode(dentry); ++ inode_lock_shared(inode); ++ ++ arg.sb = inode->i_sb; ++ err = si_read_lock(arg.sb, AuLock_FLUSH | AuLock_NOPLM); ++ if (unlikely(err)) ++ goto out_mtx; ++ err = au_alive_dir(dentry); ++ if (unlikely(err)) ++ goto out_si; ++ /* todo: reval? */ ++ fi_read_lock(file); ++ ++ err = -EAGAIN; ++ if (unlikely(au_ftest_rdu(cookie->flags, CONT) ++ && cookie->generation != au_figen(file))) ++ goto out_unlock; ++ ++ err = 0; ++ if (!rdu->blk) { ++ rdu->blk = au_sbi(arg.sb)->si_rdblk; ++ if (!rdu->blk) ++ rdu->blk = au_dir_size(file, /*dentry*/NULL); ++ } ++ bbot = au_fbtop(file); ++ if (cookie->bindex < bbot) ++ cookie->bindex = bbot; ++ bbot = au_fbbot_dir(file); ++ /* AuDbg("b%d, b%d\n", cookie->bindex, bbot); */ ++ for (; !err && cookie->bindex <= bbot; ++ cookie->bindex++, cookie->h_pos = 0) { ++ h_file = au_hf_dir(file, cookie->bindex); ++ if (!h_file) ++ continue; ++ ++ au_fclr_rdu(cookie->flags, FULL); ++ err = au_rdu_do(h_file, &arg); ++ AuTraceErr(err); ++ if (unlikely(au_ftest_rdu(cookie->flags, FULL) || err)) ++ break; ++ } ++ AuDbg("rent %llu\n", rdu->rent); ++ ++ if (!err && !au_ftest_rdu(cookie->flags, CONT)) { ++ rdu->shwh = !!au_opt_test(au_sbi(arg.sb)->si_mntflags, SHWH); ++ au_fset_rdu(cookie->flags, CONT); ++ cookie->generation = au_figen(file); ++ } ++ ++ ii_read_lock_child(inode); ++ fsstack_copy_attr_atime(inode, au_h_iptr(inode, au_ibtop(inode))); ++ ii_read_unlock(inode); ++ ++out_unlock: ++ fi_read_unlock(file); ++out_si: ++ si_read_unlock(arg.sb); ++out_mtx: ++ inode_unlock_shared(inode); ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++static int au_rdu_ino(struct file *file, struct aufs_rdu *rdu) ++{ ++ int err; ++ ino_t ino; ++ unsigned long long nent; ++ union au_rdu_ent_ul *u; ++ struct au_rdu_ent ent; ++ struct super_block *sb; ++ ++ err = 0; ++ nent = rdu->nent; ++ u = &rdu->ent; ++ sb = file->f_path.dentry->d_sb; ++ si_read_lock(sb, AuLock_FLUSH); ++ while (nent-- > 0) { ++ /* unnecessary to support mmap_sem since this is a dir */ ++ err = copy_from_user(&ent, u->e, sizeof(ent)); ++ if (!err) ++ /* VERIFY_WRITE */ ++ err = !access_ok(&u->e->ino, sizeof(ino)); ++ if (unlikely(err)) { ++ err = -EFAULT; ++ AuTraceErr(err); ++ break; ++ } ++ ++ /* AuDbg("b%d, i%llu\n", ent.bindex, ent.ino); */ ++ if (!ent.wh) ++ err = au_ino(sb, ent.bindex, ent.ino, ent.type, &ino); ++ else ++ err = au_wh_ino(sb, ent.bindex, ent.ino, ent.type, ++ &ino); ++ if (unlikely(err)) { ++ AuTraceErr(err); ++ break; ++ } ++ ++ err = __put_user(ino, &u->e->ino); ++ if (unlikely(err)) { ++ err = -EFAULT; ++ AuTraceErr(err); ++ break; ++ } ++ u->ul += au_rdu_len(ent.nlen); ++ } ++ si_read_unlock(sb); ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int au_rdu_verify(struct aufs_rdu *rdu) ++{ ++ AuDbg("rdu{%llu, %p, %u | %u | %llu, %u, %u | " ++ "%llu, b%d, 0x%x, g%u}\n", ++ rdu->sz, rdu->ent.e, rdu->verify[AufsCtlRduV_SZ], ++ rdu->blk, ++ rdu->rent, rdu->shwh, rdu->full, ++ rdu->cookie.h_pos, rdu->cookie.bindex, rdu->cookie.flags, ++ rdu->cookie.generation); ++ ++ if (rdu->verify[AufsCtlRduV_SZ] == sizeof(*rdu)) ++ return 0; ++ ++ AuDbg("%u:%u\n", ++ rdu->verify[AufsCtlRduV_SZ], (unsigned int)sizeof(*rdu)); ++ return -EINVAL; ++} ++ ++long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ++{ ++ long err, e; ++ struct aufs_rdu rdu; ++ void __user *p = (void __user *)arg; ++ ++ err = copy_from_user(&rdu, p, sizeof(rdu)); ++ if (unlikely(err)) { ++ err = -EFAULT; ++ AuTraceErr(err); ++ goto out; ++ } ++ err = au_rdu_verify(&rdu); ++ if (unlikely(err)) ++ goto out; ++ ++ switch (cmd) { ++ case AUFS_CTL_RDU: ++ err = au_rdu(file, &rdu); ++ if (unlikely(err)) ++ break; ++ ++ e = copy_to_user(p, &rdu, sizeof(rdu)); ++ if (unlikely(e)) { ++ err = -EFAULT; ++ AuTraceErr(err); ++ } ++ break; ++ case AUFS_CTL_RDU_INO: ++ err = au_rdu_ino(file, &rdu); ++ break; ++ ++ default: ++ /* err = -ENOTTY; */ ++ err = -EINVAL; ++ } ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++#ifdef CONFIG_COMPAT ++long au_rdu_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ++{ ++ long err, e; ++ struct aufs_rdu rdu; ++ void __user *p = compat_ptr(arg); ++ ++ /* todo: get_user()? */ ++ err = copy_from_user(&rdu, p, sizeof(rdu)); ++ if (unlikely(err)) { ++ err = -EFAULT; ++ AuTraceErr(err); ++ goto out; ++ } ++ rdu.ent.e = compat_ptr(rdu.ent.ul); ++ err = au_rdu_verify(&rdu); ++ if (unlikely(err)) ++ goto out; ++ ++ switch (cmd) { ++ case AUFS_CTL_RDU: ++ err = au_rdu(file, &rdu); ++ if (unlikely(err)) ++ break; ++ ++ rdu.ent.ul = ptr_to_compat(rdu.ent.e); ++ rdu.tail.ul = ptr_to_compat(rdu.tail.e); ++ e = copy_to_user(p, &rdu, sizeof(rdu)); ++ if (unlikely(e)) { ++ err = -EFAULT; ++ AuTraceErr(err); ++ } ++ break; ++ case AUFS_CTL_RDU_INO: ++ err = au_rdu_ino(file, &rdu); ++ break; ++ ++ default: ++ /* err = -ENOTTY; */ ++ err = -EINVAL; ++ } ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++#endif +diff -Nurp linux-5.4/fs/aufs/rwsem.h linux-5.4-aufs/fs/aufs/rwsem.h +--- linux-5.4/fs/aufs/rwsem.h 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/rwsem.h 2019-11-28 01:25:59.067925618 +0200 +@@ -0,0 +1,60 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * simple read-write semaphore wrappers ++ */ ++ ++#ifndef __AUFS_RWSEM_H__ ++#define __AUFS_RWSEM_H__ ++ ++#ifdef __KERNEL__ ++ ++#include "debug.h" ++ ++/* in the future, the name 'au_rwsem' will be totally gone */ ++#define au_rwsem rw_semaphore ++ ++/* to debug easier, do not make them inlined functions */ ++#define AuRwMustNoWaiters(rw) AuDebugOn(rwsem_is_contended(rw)) ++/* rwsem_is_locked() is unusable */ ++#define AuRwMustReadLock(rw) AuDebugOn(!lockdep_recursing(current) \ ++ && debug_locks \ ++ && !lockdep_is_held_type(rw, 1)) ++#define AuRwMustWriteLock(rw) AuDebugOn(!lockdep_recursing(current) \ ++ && debug_locks \ ++ && !lockdep_is_held_type(rw, 0)) ++#define AuRwMustAnyLock(rw) AuDebugOn(!lockdep_recursing(current) \ ++ && debug_locks \ ++ && !lockdep_is_held(rw)) ++#define AuRwDestroy(rw) AuDebugOn(!lockdep_recursing(current) \ ++ && debug_locks \ ++ && lockdep_is_held(rw)) ++ ++#define au_rw_init(rw) init_rwsem(rw) ++ ++#define au_rw_init_wlock(rw) do { \ ++ au_rw_init(rw); \ ++ down_write(rw); \ ++ } while (0) ++ ++#define au_rw_init_wlock_nested(rw, lsc) do { \ ++ au_rw_init(rw); \ ++ down_write_nested(rw, lsc); \ ++ } while (0) ++ ++#define au_rw_read_lock(rw) down_read(rw) ++#define au_rw_read_lock_nested(rw, lsc) down_read_nested(rw, lsc) ++#define au_rw_read_unlock(rw) up_read(rw) ++#define au_rw_dgrade_lock(rw) downgrade_write(rw) ++#define au_rw_write_lock(rw) down_write(rw) ++#define au_rw_write_lock_nested(rw, lsc) down_write_nested(rw, lsc) ++#define au_rw_write_unlock(rw) up_write(rw) ++/* why is not _nested version defined? */ ++#define au_rw_read_trylock(rw) down_read_trylock(rw) ++#define au_rw_write_trylock(rw) down_write_trylock(rw) ++ ++#endif /* __KERNEL__ */ ++#endif /* __AUFS_RWSEM_H__ */ +diff -Nurp linux-5.4/fs/aufs/sbinfo.c linux-5.4-aufs/fs/aufs/sbinfo.c +--- linux-5.4/fs/aufs/sbinfo.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/sbinfo.c 2019-11-28 01:25:59.067925618 +0200 +@@ -0,0 +1,301 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * superblock private data ++ */ ++ ++#include ++#include "aufs.h" ++ ++/* ++ * they are necessary regardless sysfs is disabled. ++ */ ++void au_si_free(struct kobject *kobj) ++{ ++ int i; ++ struct au_sbinfo *sbinfo; ++ char *locked __maybe_unused; /* debug only */ ++ ++ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj); ++ for (i = 0; i < AuPlink_NHASH; i++) ++ AuDebugOn(!hlist_bl_empty(sbinfo->si_plink + i)); ++ AuDebugOn(atomic_read(&sbinfo->si_nowait.nw_len)); ++ ++ AuLCntZero(au_lcnt_read(&sbinfo->si_ninodes, /*do_rev*/0)); ++ au_lcnt_fin(&sbinfo->si_ninodes, /*do_sync*/0); ++ AuLCntZero(au_lcnt_read(&sbinfo->si_nfiles, /*do_rev*/0)); ++ au_lcnt_fin(&sbinfo->si_nfiles, /*do_sync*/0); ++ ++ dbgaufs_si_fin(sbinfo); ++ au_rw_write_lock(&sbinfo->si_rwsem); ++ au_br_free(sbinfo); ++ au_rw_write_unlock(&sbinfo->si_rwsem); ++ ++ au_kfree_try_rcu(sbinfo->si_branch); ++ mutex_destroy(&sbinfo->si_xib_mtx); ++ AuRwDestroy(&sbinfo->si_rwsem); ++ ++ au_lcnt_wait_for_fin(&sbinfo->si_ninodes); ++ /* si_nfiles is waited too */ ++ au_kfree_rcu(sbinfo); ++} ++ ++int au_si_alloc(struct super_block *sb) ++{ ++ int err, i; ++ struct au_sbinfo *sbinfo; ++ ++ err = -ENOMEM; ++ sbinfo = kzalloc(sizeof(*sbinfo), GFP_NOFS); ++ if (unlikely(!sbinfo)) ++ goto out; ++ ++ /* will be reallocated separately */ ++ sbinfo->si_branch = kzalloc(sizeof(*sbinfo->si_branch), GFP_NOFS); ++ if (unlikely(!sbinfo->si_branch)) ++ goto out_sbinfo; ++ ++ err = sysaufs_si_init(sbinfo); ++ if (!err) { ++ dbgaufs_si_null(sbinfo); ++ err = dbgaufs_si_init(sbinfo); ++ if (unlikely(err)) ++ kobject_put(&sbinfo->si_kobj); ++ } ++ if (unlikely(err)) ++ goto out_br; ++ ++ au_nwt_init(&sbinfo->si_nowait); ++ au_rw_init_wlock(&sbinfo->si_rwsem); ++ ++ au_lcnt_init(&sbinfo->si_ninodes, /*release*/NULL); ++ au_lcnt_init(&sbinfo->si_nfiles, /*release*/NULL); ++ ++ sbinfo->si_bbot = -1; ++ sbinfo->si_last_br_id = AUFS_BRANCH_MAX / 2; ++ ++ sbinfo->si_wbr_copyup = AuWbrCopyup_Def; ++ sbinfo->si_wbr_create = AuWbrCreate_Def; ++ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + sbinfo->si_wbr_copyup; ++ sbinfo->si_wbr_create_ops = au_wbr_create_ops + sbinfo->si_wbr_create; ++ ++ au_fhsm_init(sbinfo); ++ ++ sbinfo->si_mntflags = au_opts_plink(AuOpt_Def); ++ ++ sbinfo->si_xino_jiffy = jiffies; ++ sbinfo->si_xino_expire ++ = msecs_to_jiffies(AUFS_XINO_DEF_SEC * MSEC_PER_SEC); ++ mutex_init(&sbinfo->si_xib_mtx); ++ /* leave si_xib_last_pindex and si_xib_next_bit */ ++ ++ INIT_HLIST_BL_HEAD(&sbinfo->si_aopen); ++ ++ sbinfo->si_rdcache = msecs_to_jiffies(AUFS_RDCACHE_DEF * MSEC_PER_SEC); ++ sbinfo->si_rdblk = AUFS_RDBLK_DEF; ++ sbinfo->si_rdhash = AUFS_RDHASH_DEF; ++ sbinfo->si_dirwh = AUFS_DIRWH_DEF; ++ ++ for (i = 0; i < AuPlink_NHASH; i++) ++ INIT_HLIST_BL_HEAD(sbinfo->si_plink + i); ++ init_waitqueue_head(&sbinfo->si_plink_wq); ++ spin_lock_init(&sbinfo->si_plink_maint_lock); ++ ++ INIT_HLIST_BL_HEAD(&sbinfo->si_files); ++ ++ /* with getattr by default */ ++ sbinfo->si_iop_array = aufs_iop; ++ ++ /* leave other members for sysaufs and si_mnt. */ ++ sbinfo->si_sb = sb; ++ sb->s_fs_info = sbinfo; ++ si_pid_set(sb); ++ return 0; /* success */ ++ ++out_br: ++ au_kfree_try_rcu(sbinfo->si_branch); ++out_sbinfo: ++ au_kfree_rcu(sbinfo); ++out: ++ return err; ++} ++ ++int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr, int may_shrink) ++{ ++ int err, sz; ++ struct au_branch **brp; ++ ++ AuRwMustWriteLock(&sbinfo->si_rwsem); ++ ++ err = -ENOMEM; ++ sz = sizeof(*brp) * (sbinfo->si_bbot + 1); ++ if (unlikely(!sz)) ++ sz = sizeof(*brp); ++ brp = au_kzrealloc(sbinfo->si_branch, sz, sizeof(*brp) * nbr, GFP_NOFS, ++ may_shrink); ++ if (brp) { ++ sbinfo->si_branch = brp; ++ err = 0; ++ } ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++unsigned int au_sigen_inc(struct super_block *sb) ++{ ++ unsigned int gen; ++ struct inode *inode; ++ ++ SiMustWriteLock(sb); ++ ++ gen = ++au_sbi(sb)->si_generation; ++ au_update_digen(sb->s_root); ++ inode = d_inode(sb->s_root); ++ au_update_iigen(inode, /*half*/0); ++ inode_inc_iversion(inode); ++ return gen; ++} ++ ++aufs_bindex_t au_new_br_id(struct super_block *sb) ++{ ++ aufs_bindex_t br_id; ++ int i; ++ struct au_sbinfo *sbinfo; ++ ++ SiMustWriteLock(sb); ++ ++ sbinfo = au_sbi(sb); ++ for (i = 0; i <= AUFS_BRANCH_MAX; i++) { ++ br_id = ++sbinfo->si_last_br_id; ++ AuDebugOn(br_id < 0); ++ if (br_id && au_br_index(sb, br_id) < 0) ++ return br_id; ++ } ++ ++ return -1; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* it is ok that new 'nwt' tasks are appended while we are sleeping */ ++int si_read_lock(struct super_block *sb, int flags) ++{ ++ int err; ++ ++ err = 0; ++ if (au_ftest_lock(flags, FLUSH)) ++ au_nwt_flush(&au_sbi(sb)->si_nowait); ++ ++ si_noflush_read_lock(sb); ++ err = au_plink_maint(sb, flags); ++ if (unlikely(err)) ++ si_read_unlock(sb); ++ ++ return err; ++} ++ ++int si_write_lock(struct super_block *sb, int flags) ++{ ++ int err; ++ ++ if (au_ftest_lock(flags, FLUSH)) ++ au_nwt_flush(&au_sbi(sb)->si_nowait); ++ ++ si_noflush_write_lock(sb); ++ err = au_plink_maint(sb, flags); ++ if (unlikely(err)) ++ si_write_unlock(sb); ++ ++ return err; ++} ++ ++/* dentry and super_block lock. call at entry point */ ++int aufs_read_lock(struct dentry *dentry, int flags) ++{ ++ int err; ++ struct super_block *sb; ++ ++ sb = dentry->d_sb; ++ err = si_read_lock(sb, flags); ++ if (unlikely(err)) ++ goto out; ++ ++ if (au_ftest_lock(flags, DW)) ++ di_write_lock_child(dentry); ++ else ++ di_read_lock_child(dentry, flags); ++ ++ if (au_ftest_lock(flags, GEN)) { ++ err = au_digen_test(dentry, au_sigen(sb)); ++ if (!au_opt_test(au_mntflags(sb), UDBA_NONE)) ++ AuDebugOn(!err && au_dbrange_test(dentry)); ++ else if (!err) ++ err = au_dbrange_test(dentry); ++ if (unlikely(err)) ++ aufs_read_unlock(dentry, flags); ++ } ++ ++out: ++ return err; ++} ++ ++void aufs_read_unlock(struct dentry *dentry, int flags) ++{ ++ if (au_ftest_lock(flags, DW)) ++ di_write_unlock(dentry); ++ else ++ di_read_unlock(dentry, flags); ++ si_read_unlock(dentry->d_sb); ++} ++ ++void aufs_write_lock(struct dentry *dentry) ++{ ++ si_write_lock(dentry->d_sb, AuLock_FLUSH | AuLock_NOPLMW); ++ di_write_lock_child(dentry); ++} ++ ++void aufs_write_unlock(struct dentry *dentry) ++{ ++ di_write_unlock(dentry); ++ si_write_unlock(dentry->d_sb); ++} ++ ++int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags) ++{ ++ int err; ++ unsigned int sigen; ++ struct super_block *sb; ++ ++ sb = d1->d_sb; ++ err = si_read_lock(sb, flags); ++ if (unlikely(err)) ++ goto out; ++ ++ di_write_lock2_child(d1, d2, au_ftest_lock(flags, DIRS)); ++ ++ if (au_ftest_lock(flags, GEN)) { ++ sigen = au_sigen(sb); ++ err = au_digen_test(d1, sigen); ++ AuDebugOn(!err && au_dbrange_test(d1)); ++ if (!err) { ++ err = au_digen_test(d2, sigen); ++ AuDebugOn(!err && au_dbrange_test(d2)); ++ } ++ if (unlikely(err)) ++ aufs_read_and_write_unlock2(d1, d2); ++ } ++ ++out: ++ return err; ++} ++ ++void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2) ++{ ++ di_write_unlock2(d1, d2); ++ si_read_unlock(d1->d_sb); ++} +diff -Nurp linux-5.4/fs/aufs/super.c linux-5.4-aufs/fs/aufs/super.c +--- linux-5.4/fs/aufs/super.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/super.c 2019-11-28 01:25:59.067925618 +0200 +@@ -0,0 +1,1034 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * mount and super_block operations ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include "aufs.h" ++ ++/* ++ * super_operations ++ */ ++static struct inode *aufs_alloc_inode(struct super_block *sb __maybe_unused) ++{ ++ struct au_icntnr *c; ++ ++ c = au_cache_alloc_icntnr(); ++ if (c) { ++ au_icntnr_init(c); ++ inode_set_iversion(&c->vfs_inode, 1); /* sigen(sb); */ ++ c->iinfo.ii_hinode = NULL; ++ return &c->vfs_inode; ++ } ++ return NULL; ++} ++ ++static void aufs_destroy_inode(struct inode *inode) ++{ ++ if (!au_is_bad_inode(inode)) ++ au_iinfo_fin(inode); ++} ++ ++static void aufs_free_inode(struct inode *inode) ++{ ++ au_cache_free_icntnr(container_of(inode, struct au_icntnr, vfs_inode)); ++} ++ ++struct inode *au_iget_locked(struct super_block *sb, ino_t ino) ++{ ++ struct inode *inode; ++ int err; ++ ++ inode = iget_locked(sb, ino); ++ if (unlikely(!inode)) { ++ inode = ERR_PTR(-ENOMEM); ++ goto out; ++ } ++ if (!(inode->i_state & I_NEW)) ++ goto out; ++ ++ err = au_xigen_new(inode); ++ if (!err) ++ err = au_iinfo_init(inode); ++ if (!err) ++ inode_inc_iversion(inode); ++ else { ++ iget_failed(inode); ++ inode = ERR_PTR(err); ++ } ++ ++out: ++ /* never return NULL */ ++ AuDebugOn(!inode); ++ AuTraceErrPtr(inode); ++ return inode; ++} ++ ++/* lock free root dinfo */ ++static int au_show_brs(struct seq_file *seq, struct super_block *sb) ++{ ++ int err; ++ aufs_bindex_t bindex, bbot; ++ struct path path; ++ struct au_hdentry *hdp; ++ struct au_branch *br; ++ au_br_perm_str_t perm; ++ ++ err = 0; ++ bbot = au_sbbot(sb); ++ bindex = 0; ++ hdp = au_hdentry(au_di(sb->s_root), bindex); ++ for (; !err && bindex <= bbot; bindex++, hdp++) { ++ br = au_sbr(sb, bindex); ++ path.mnt = au_br_mnt(br); ++ path.dentry = hdp->hd_dentry; ++ err = au_seq_path(seq, &path); ++ if (!err) { ++ au_optstr_br_perm(&perm, br->br_perm); ++ seq_printf(seq, "=%s", perm.a); ++ if (bindex != bbot) ++ seq_putc(seq, ':'); ++ } ++ } ++ if (unlikely(err || seq_has_overflowed(seq))) ++ err = -E2BIG; ++ ++ return err; ++} ++ ++static void au_gen_fmt(char *fmt, int len __maybe_unused, const char *pat, ++ const char *append) ++{ ++ char *p; ++ ++ p = fmt; ++ while (*pat != ':') ++ *p++ = *pat++; ++ *p++ = *pat++; ++ strcpy(p, append); ++ AuDebugOn(strlen(fmt) >= len); ++} ++ ++static void au_show_wbr_create(struct seq_file *m, int v, ++ struct au_sbinfo *sbinfo) ++{ ++ const char *pat; ++ char fmt[32]; ++ struct au_wbr_mfs *mfs; ++ ++ AuRwMustAnyLock(&sbinfo->si_rwsem); ++ ++ seq_puts(m, ",create="); ++ pat = au_optstr_wbr_create(v); ++ mfs = &sbinfo->si_wbr_mfs; ++ switch (v) { ++ case AuWbrCreate_TDP: ++ case AuWbrCreate_RR: ++ case AuWbrCreate_MFS: ++ case AuWbrCreate_PMFS: ++ seq_puts(m, pat); ++ break; ++ case AuWbrCreate_MFSRR: ++ case AuWbrCreate_TDMFS: ++ case AuWbrCreate_PMFSRR: ++ au_gen_fmt(fmt, sizeof(fmt), pat, "%llu"); ++ seq_printf(m, fmt, mfs->mfsrr_watermark); ++ break; ++ case AuWbrCreate_MFSV: ++ case AuWbrCreate_PMFSV: ++ au_gen_fmt(fmt, sizeof(fmt), pat, "%lu"); ++ seq_printf(m, fmt, ++ jiffies_to_msecs(mfs->mfs_expire) ++ / MSEC_PER_SEC); ++ break; ++ case AuWbrCreate_MFSRRV: ++ case AuWbrCreate_TDMFSV: ++ case AuWbrCreate_PMFSRRV: ++ au_gen_fmt(fmt, sizeof(fmt), pat, "%llu:%lu"); ++ seq_printf(m, fmt, mfs->mfsrr_watermark, ++ jiffies_to_msecs(mfs->mfs_expire) / MSEC_PER_SEC); ++ break; ++ default: ++ BUG(); ++ } ++} ++ ++static int au_show_xino(struct seq_file *seq, struct super_block *sb) ++{ ++#ifdef CONFIG_SYSFS ++ return 0; ++#else ++ int err; ++ const int len = sizeof(AUFS_XINO_FNAME) - 1; ++ aufs_bindex_t bindex, brid; ++ struct qstr *name; ++ struct file *f; ++ struct dentry *d, *h_root; ++ struct au_branch *br; ++ ++ AuRwMustAnyLock(&sbinfo->si_rwsem); ++ ++ err = 0; ++ f = au_sbi(sb)->si_xib; ++ if (!f) ++ goto out; ++ ++ /* stop printing the default xino path on the first writable branch */ ++ h_root = NULL; ++ bindex = au_xi_root(sb, f->f_path.dentry); ++ if (bindex >= 0) { ++ br = au_sbr_sb(sb, bindex); ++ h_root = au_br_dentry(br); ++ } ++ ++ d = f->f_path.dentry; ++ name = &d->d_name; ++ /* safe ->d_parent because the file is unlinked */ ++ if (d->d_parent == h_root ++ && name->len == len ++ && !memcmp(name->name, AUFS_XINO_FNAME, len)) ++ goto out; ++ ++ seq_puts(seq, ",xino="); ++ err = au_xino_path(seq, f); ++ ++out: ++ return err; ++#endif ++} ++ ++/* seq_file will re-call me in case of too long string */ ++static int aufs_show_options(struct seq_file *m, struct dentry *dentry) ++{ ++ int err; ++ unsigned int mnt_flags, v; ++ struct super_block *sb; ++ struct au_sbinfo *sbinfo; ++ ++#define AuBool(name, str) do { \ ++ v = au_opt_test(mnt_flags, name); \ ++ if (v != au_opt_test(AuOpt_Def, name)) \ ++ seq_printf(m, ",%s" #str, v ? "" : "no"); \ ++} while (0) ++ ++#define AuStr(name, str) do { \ ++ v = mnt_flags & AuOptMask_##name; \ ++ if (v != (AuOpt_Def & AuOptMask_##name)) \ ++ seq_printf(m, "," #str "=%s", au_optstr_##str(v)); \ ++} while (0) ++ ++#define AuUInt(name, str, val) do { \ ++ if (val != AUFS_##name##_DEF) \ ++ seq_printf(m, "," #str "=%u", val); \ ++} while (0) ++ ++ sb = dentry->d_sb; ++ if (sb->s_flags & SB_POSIXACL) ++ seq_puts(m, ",acl"); ++#if 0 ++ if (sb->s_flags & SB_I_VERSION) ++ seq_puts(m, ",i_version"); ++#endif ++ ++ /* lock free root dinfo */ ++ si_noflush_read_lock(sb); ++ sbinfo = au_sbi(sb); ++ seq_printf(m, ",si=%lx", sysaufs_si_id(sbinfo)); ++ ++ mnt_flags = au_mntflags(sb); ++ if (au_opt_test(mnt_flags, XINO)) { ++ err = au_show_xino(m, sb); ++ if (unlikely(err)) ++ goto out; ++ } else ++ seq_puts(m, ",noxino"); ++ ++ AuBool(TRUNC_XINO, trunc_xino); ++ AuStr(UDBA, udba); ++ AuBool(SHWH, shwh); ++ AuBool(PLINK, plink); ++ AuBool(DIO, dio); ++ AuBool(DIRPERM1, dirperm1); ++ ++ v = sbinfo->si_wbr_create; ++ if (v != AuWbrCreate_Def) ++ au_show_wbr_create(m, v, sbinfo); ++ ++ v = sbinfo->si_wbr_copyup; ++ if (v != AuWbrCopyup_Def) ++ seq_printf(m, ",cpup=%s", au_optstr_wbr_copyup(v)); ++ ++ v = au_opt_test(mnt_flags, ALWAYS_DIROPQ); ++ if (v != au_opt_test(AuOpt_Def, ALWAYS_DIROPQ)) ++ seq_printf(m, ",diropq=%c", v ? 'a' : 'w'); ++ ++ AuUInt(DIRWH, dirwh, sbinfo->si_dirwh); ++ ++ v = jiffies_to_msecs(sbinfo->si_rdcache) / MSEC_PER_SEC; ++ AuUInt(RDCACHE, rdcache, v); ++ ++ AuUInt(RDBLK, rdblk, sbinfo->si_rdblk); ++ AuUInt(RDHASH, rdhash, sbinfo->si_rdhash); ++ ++ au_fhsm_show(m, sbinfo); ++ ++ AuBool(DIRREN, dirren); ++ AuBool(SUM, sum); ++ /* AuBool(SUM_W, wsum); */ ++ AuBool(WARN_PERM, warn_perm); ++ AuBool(VERBOSE, verbose); ++ ++out: ++ /* be sure to print "br:" last */ ++ if (!sysaufs_brs) { ++ seq_puts(m, ",br:"); ++ au_show_brs(m, sb); ++ } ++ si_read_unlock(sb); ++ return 0; ++ ++#undef AuBool ++#undef AuStr ++#undef AuUInt ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* sum mode which returns the summation for statfs(2) */ ++ ++static u64 au_add_till_max(u64 a, u64 b) ++{ ++ u64 old; ++ ++ old = a; ++ a += b; ++ if (old <= a) ++ return a; ++ return ULLONG_MAX; ++} ++ ++static u64 au_mul_till_max(u64 a, long mul) ++{ ++ u64 old; ++ ++ old = a; ++ a *= mul; ++ if (old <= a) ++ return a; ++ return ULLONG_MAX; ++} ++ ++static int au_statfs_sum(struct super_block *sb, struct kstatfs *buf) ++{ ++ int err; ++ long bsize, factor; ++ u64 blocks, bfree, bavail, files, ffree; ++ aufs_bindex_t bbot, bindex, i; ++ unsigned char shared; ++ struct path h_path; ++ struct super_block *h_sb; ++ ++ err = 0; ++ bsize = LONG_MAX; ++ files = 0; ++ ffree = 0; ++ blocks = 0; ++ bfree = 0; ++ bavail = 0; ++ bbot = au_sbbot(sb); ++ for (bindex = 0; bindex <= bbot; bindex++) { ++ h_path.mnt = au_sbr_mnt(sb, bindex); ++ h_sb = h_path.mnt->mnt_sb; ++ shared = 0; ++ for (i = 0; !shared && i < bindex; i++) ++ shared = (au_sbr_sb(sb, i) == h_sb); ++ if (shared) ++ continue; ++ ++ /* sb->s_root for NFS is unreliable */ ++ h_path.dentry = h_path.mnt->mnt_root; ++ err = vfs_statfs(&h_path, buf); ++ if (unlikely(err)) ++ goto out; ++ ++ if (bsize > buf->f_bsize) { ++ /* ++ * we will reduce bsize, so we have to expand blocks ++ * etc. to match them again ++ */ ++ factor = (bsize / buf->f_bsize); ++ blocks = au_mul_till_max(blocks, factor); ++ bfree = au_mul_till_max(bfree, factor); ++ bavail = au_mul_till_max(bavail, factor); ++ bsize = buf->f_bsize; ++ } ++ ++ factor = (buf->f_bsize / bsize); ++ blocks = au_add_till_max(blocks, ++ au_mul_till_max(buf->f_blocks, factor)); ++ bfree = au_add_till_max(bfree, ++ au_mul_till_max(buf->f_bfree, factor)); ++ bavail = au_add_till_max(bavail, ++ au_mul_till_max(buf->f_bavail, factor)); ++ files = au_add_till_max(files, buf->f_files); ++ ffree = au_add_till_max(ffree, buf->f_ffree); ++ } ++ ++ buf->f_bsize = bsize; ++ buf->f_blocks = blocks; ++ buf->f_bfree = bfree; ++ buf->f_bavail = bavail; ++ buf->f_files = files; ++ buf->f_ffree = ffree; ++ buf->f_frsize = 0; ++ ++out: ++ return err; ++} ++ ++static int aufs_statfs(struct dentry *dentry, struct kstatfs *buf) ++{ ++ int err; ++ struct path h_path; ++ struct super_block *sb; ++ ++ /* lock free root dinfo */ ++ sb = dentry->d_sb; ++ si_noflush_read_lock(sb); ++ if (!au_opt_test(au_mntflags(sb), SUM)) { ++ /* sb->s_root for NFS is unreliable */ ++ h_path.mnt = au_sbr_mnt(sb, 0); ++ h_path.dentry = h_path.mnt->mnt_root; ++ err = vfs_statfs(&h_path, buf); ++ } else ++ err = au_statfs_sum(sb, buf); ++ si_read_unlock(sb); ++ ++ if (!err) { ++ buf->f_type = AUFS_SUPER_MAGIC; ++ buf->f_namelen = AUFS_MAX_NAMELEN; ++ memset(&buf->f_fsid, 0, sizeof(buf->f_fsid)); ++ } ++ /* buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1; */ ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int aufs_sync_fs(struct super_block *sb, int wait) ++{ ++ int err, e; ++ aufs_bindex_t bbot, bindex; ++ struct au_branch *br; ++ struct super_block *h_sb; ++ ++ err = 0; ++ si_noflush_read_lock(sb); ++ bbot = au_sbbot(sb); ++ for (bindex = 0; bindex <= bbot; bindex++) { ++ br = au_sbr(sb, bindex); ++ if (!au_br_writable(br->br_perm)) ++ continue; ++ ++ h_sb = au_sbr_sb(sb, bindex); ++ e = vfsub_sync_filesystem(h_sb, wait); ++ if (unlikely(e && !err)) ++ err = e; ++ /* go on even if an error happens */ ++ } ++ si_read_unlock(sb); ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* final actions when unmounting a file system */ ++static void aufs_put_super(struct super_block *sb) ++{ ++ struct au_sbinfo *sbinfo; ++ ++ sbinfo = au_sbi(sb); ++ if (sbinfo) ++ kobject_put(&sbinfo->si_kobj); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++void *au_array_alloc(unsigned long long *hint, au_arraycb_t cb, ++ struct super_block *sb, void *arg) ++{ ++ void *array; ++ unsigned long long n, sz; ++ ++ array = NULL; ++ n = 0; ++ if (!*hint) ++ goto out; ++ ++ if (*hint > ULLONG_MAX / sizeof(array)) { ++ array = ERR_PTR(-EMFILE); ++ pr_err("hint %llu\n", *hint); ++ goto out; ++ } ++ ++ sz = sizeof(array) * *hint; ++ array = kzalloc(sz, GFP_NOFS); ++ if (unlikely(!array)) ++ array = vzalloc(sz); ++ if (unlikely(!array)) { ++ array = ERR_PTR(-ENOMEM); ++ goto out; ++ } ++ ++ n = cb(sb, array, *hint, arg); ++ AuDebugOn(n > *hint); ++ ++out: ++ *hint = n; ++ return array; ++} ++ ++static unsigned long long au_iarray_cb(struct super_block *sb, void *a, ++ unsigned long long max __maybe_unused, ++ void *arg) ++{ ++ unsigned long long n; ++ struct inode **p, *inode; ++ struct list_head *head; ++ ++ n = 0; ++ p = a; ++ head = arg; ++ spin_lock(&sb->s_inode_list_lock); ++ list_for_each_entry(inode, head, i_sb_list) { ++ if (!au_is_bad_inode(inode) ++ && au_ii(inode)->ii_btop >= 0) { ++ spin_lock(&inode->i_lock); ++ if (atomic_read(&inode->i_count)) { ++ au_igrab(inode); ++ *p++ = inode; ++ n++; ++ AuDebugOn(n > max); ++ } ++ spin_unlock(&inode->i_lock); ++ } ++ } ++ spin_unlock(&sb->s_inode_list_lock); ++ ++ return n; ++} ++ ++struct inode **au_iarray_alloc(struct super_block *sb, unsigned long long *max) ++{ ++ struct au_sbinfo *sbi; ++ ++ sbi = au_sbi(sb); ++ *max = au_lcnt_read(&sbi->si_ninodes, /*do_rev*/1); ++ return au_array_alloc(max, au_iarray_cb, sb, &sb->s_inodes); ++} ++ ++void au_iarray_free(struct inode **a, unsigned long long max) ++{ ++ unsigned long long ull; ++ ++ for (ull = 0; ull < max; ull++) ++ iput(a[ull]); ++ kvfree(a); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * refresh dentry and inode at remount time. ++ */ ++/* todo: consolidate with simple_reval_dpath() and au_reval_for_attr() */ ++static int au_do_refresh(struct dentry *dentry, unsigned int dir_flags, ++ struct dentry *parent) ++{ ++ int err; ++ ++ di_write_lock_child(dentry); ++ di_read_lock_parent(parent, AuLock_IR); ++ err = au_refresh_dentry(dentry, parent); ++ if (!err && dir_flags) ++ au_hn_reset(d_inode(dentry), dir_flags); ++ di_read_unlock(parent, AuLock_IR); ++ di_write_unlock(dentry); ++ ++ return err; ++} ++ ++static int au_do_refresh_d(struct dentry *dentry, unsigned int sigen, ++ struct au_sbinfo *sbinfo, ++ const unsigned int dir_flags, unsigned int do_idop) ++{ ++ int err; ++ struct dentry *parent; ++ ++ err = 0; ++ parent = dget_parent(dentry); ++ if (!au_digen_test(parent, sigen) && au_digen_test(dentry, sigen)) { ++ if (d_really_is_positive(dentry)) { ++ if (!d_is_dir(dentry)) ++ err = au_do_refresh(dentry, /*dir_flags*/0, ++ parent); ++ else { ++ err = au_do_refresh(dentry, dir_flags, parent); ++ if (unlikely(err)) ++ au_fset_si(sbinfo, FAILED_REFRESH_DIR); ++ } ++ } else ++ err = au_do_refresh(dentry, /*dir_flags*/0, parent); ++ AuDbgDentry(dentry); ++ } ++ dput(parent); ++ ++ if (!err) { ++ if (do_idop) ++ au_refresh_dop(dentry, /*force_reval*/0); ++ } else ++ au_refresh_dop(dentry, /*force_reval*/1); ++ ++ AuTraceErr(err); ++ return err; ++} ++ ++static int au_refresh_d(struct super_block *sb, unsigned int do_idop) ++{ ++ int err, i, j, ndentry, e; ++ unsigned int sigen; ++ struct au_dcsub_pages dpages; ++ struct au_dpage *dpage; ++ struct dentry **dentries, *d; ++ struct au_sbinfo *sbinfo; ++ struct dentry *root = sb->s_root; ++ const unsigned int dir_flags = au_hi_flags(d_inode(root), /*isdir*/1); ++ ++ if (do_idop) ++ au_refresh_dop(root, /*force_reval*/0); ++ ++ err = au_dpages_init(&dpages, GFP_NOFS); ++ if (unlikely(err)) ++ goto out; ++ err = au_dcsub_pages(&dpages, root, NULL, NULL); ++ if (unlikely(err)) ++ goto out_dpages; ++ ++ sigen = au_sigen(sb); ++ sbinfo = au_sbi(sb); ++ for (i = 0; i < dpages.ndpage; i++) { ++ dpage = dpages.dpages + i; ++ dentries = dpage->dentries; ++ ndentry = dpage->ndentry; ++ for (j = 0; j < ndentry; j++) { ++ d = dentries[j]; ++ e = au_do_refresh_d(d, sigen, sbinfo, dir_flags, ++ do_idop); ++ if (unlikely(e && !err)) ++ err = e; ++ /* go on even err */ ++ } ++ } ++ ++out_dpages: ++ au_dpages_free(&dpages); ++out: ++ return err; ++} ++ ++static int au_refresh_i(struct super_block *sb, unsigned int do_idop) ++{ ++ int err, e; ++ unsigned int sigen; ++ unsigned long long max, ull; ++ struct inode *inode, **array; ++ ++ array = au_iarray_alloc(sb, &max); ++ err = PTR_ERR(array); ++ if (IS_ERR(array)) ++ goto out; ++ ++ err = 0; ++ sigen = au_sigen(sb); ++ for (ull = 0; ull < max; ull++) { ++ inode = array[ull]; ++ if (unlikely(!inode)) ++ break; ++ ++ e = 0; ++ ii_write_lock_child(inode); ++ if (au_iigen(inode, NULL) != sigen) { ++ e = au_refresh_hinode_self(inode); ++ if (unlikely(e)) { ++ au_refresh_iop(inode, /*force_getattr*/1); ++ pr_err("error %d, i%lu\n", e, inode->i_ino); ++ if (!err) ++ err = e; ++ /* go on even if err */ ++ } ++ } ++ if (!e && do_idop) ++ au_refresh_iop(inode, /*force_getattr*/0); ++ ii_write_unlock(inode); ++ } ++ ++ au_iarray_free(array, max); ++ ++out: ++ return err; ++} ++ ++static void au_remount_refresh(struct super_block *sb, unsigned int do_idop) ++{ ++ int err, e; ++ unsigned int udba; ++ aufs_bindex_t bindex, bbot; ++ struct dentry *root; ++ struct inode *inode; ++ struct au_branch *br; ++ struct au_sbinfo *sbi; ++ ++ au_sigen_inc(sb); ++ sbi = au_sbi(sb); ++ au_fclr_si(sbi, FAILED_REFRESH_DIR); ++ ++ root = sb->s_root; ++ DiMustNoWaiters(root); ++ inode = d_inode(root); ++ IiMustNoWaiters(inode); ++ ++ udba = au_opt_udba(sb); ++ bbot = au_sbbot(sb); ++ for (bindex = 0; bindex <= bbot; bindex++) { ++ br = au_sbr(sb, bindex); ++ err = au_hnotify_reset_br(udba, br, br->br_perm); ++ if (unlikely(err)) ++ AuIOErr("hnotify failed on br %d, %d, ignored\n", ++ bindex, err); ++ /* go on even if err */ ++ } ++ au_hn_reset(inode, au_hi_flags(inode, /*isdir*/1)); ++ ++ if (do_idop) { ++ if (au_ftest_si(sbi, NO_DREVAL)) { ++ AuDebugOn(sb->s_d_op == &aufs_dop_noreval); ++ sb->s_d_op = &aufs_dop_noreval; ++ AuDebugOn(sbi->si_iop_array == aufs_iop_nogetattr); ++ sbi->si_iop_array = aufs_iop_nogetattr; ++ } else { ++ AuDebugOn(sb->s_d_op == &aufs_dop); ++ sb->s_d_op = &aufs_dop; ++ AuDebugOn(sbi->si_iop_array == aufs_iop); ++ sbi->si_iop_array = aufs_iop; ++ } ++ pr_info("reset to %ps and %ps\n", ++ sb->s_d_op, sbi->si_iop_array); ++ } ++ ++ di_write_unlock(root); ++ err = au_refresh_d(sb, do_idop); ++ e = au_refresh_i(sb, do_idop); ++ if (unlikely(e && !err)) ++ err = e; ++ /* aufs_write_lock() calls ..._child() */ ++ di_write_lock_child(root); ++ ++ au_cpup_attr_all(inode, /*force*/1); ++ ++ if (unlikely(err)) ++ AuIOErr("refresh failed, ignored, %d\n", err); ++} ++ ++/* stop extra interpretation of errno in mount(8), and strange error messages */ ++static int cvt_err(int err) ++{ ++ AuTraceErr(err); ++ ++ switch (err) { ++ case -ENOENT: ++ case -ENOTDIR: ++ case -EEXIST: ++ case -EIO: ++ err = -EINVAL; ++ } ++ return err; ++} ++ ++static int aufs_remount_fs(struct super_block *sb, int *flags, char *data) ++{ ++ int err, do_dx; ++ unsigned int mntflags; ++ struct au_opts opts = { ++ .opt = NULL ++ }; ++ struct dentry *root; ++ struct inode *inode; ++ struct au_sbinfo *sbinfo; ++ ++ err = 0; ++ root = sb->s_root; ++ if (!data || !*data) { ++ err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM); ++ if (!err) { ++ di_write_lock_child(root); ++ err = au_opts_verify(sb, *flags, /*pending*/0); ++ aufs_write_unlock(root); ++ } ++ goto out; ++ } ++ ++ err = -ENOMEM; ++ opts.opt = (void *)__get_free_page(GFP_NOFS); ++ if (unlikely(!opts.opt)) ++ goto out; ++ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt); ++ opts.flags = AuOpts_REMOUNT; ++ opts.sb_flags = *flags; ++ ++ /* parse it before aufs lock */ ++ err = au_opts_parse(sb, data, &opts); ++ if (unlikely(err)) ++ goto out_opts; ++ ++ sbinfo = au_sbi(sb); ++ inode = d_inode(root); ++ inode_lock(inode); ++ err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM); ++ if (unlikely(err)) ++ goto out_mtx; ++ di_write_lock_child(root); ++ ++ /* au_opts_remount() may return an error */ ++ err = au_opts_remount(sb, &opts); ++ au_opts_free(&opts); ++ ++ if (au_ftest_opts(opts.flags, REFRESH)) ++ au_remount_refresh(sb, au_ftest_opts(opts.flags, REFRESH_IDOP)); ++ ++ if (au_ftest_opts(opts.flags, REFRESH_DYAOP)) { ++ mntflags = au_mntflags(sb); ++ do_dx = !!au_opt_test(mntflags, DIO); ++ au_dy_arefresh(do_dx); ++ } ++ ++ au_fhsm_wrote_all(sb, /*force*/1); /* ?? */ ++ aufs_write_unlock(root); ++ ++out_mtx: ++ inode_unlock(inode); ++out_opts: ++ free_page((unsigned long)opts.opt); ++out: ++ err = cvt_err(err); ++ AuTraceErr(err); ++ return err; ++} ++ ++static const struct super_operations aufs_sop = { ++ .alloc_inode = aufs_alloc_inode, ++ .destroy_inode = aufs_destroy_inode, ++ .free_inode = aufs_free_inode, ++ /* always deleting, no clearing */ ++ .drop_inode = generic_delete_inode, ++ .show_options = aufs_show_options, ++ .statfs = aufs_statfs, ++ .put_super = aufs_put_super, ++ .sync_fs = aufs_sync_fs, ++ .remount_fs = aufs_remount_fs ++}; ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int alloc_root(struct super_block *sb) ++{ ++ int err; ++ struct inode *inode; ++ struct dentry *root; ++ ++ err = -ENOMEM; ++ inode = au_iget_locked(sb, AUFS_ROOT_INO); ++ err = PTR_ERR(inode); ++ if (IS_ERR(inode)) ++ goto out; ++ ++ inode->i_op = aufs_iop + AuIop_DIR; /* with getattr by default */ ++ inode->i_fop = &aufs_dir_fop; ++ inode->i_mode = S_IFDIR; ++ set_nlink(inode, 2); ++ unlock_new_inode(inode); ++ ++ root = d_make_root(inode); ++ if (unlikely(!root)) ++ goto out; ++ err = PTR_ERR(root); ++ if (IS_ERR(root)) ++ goto out; ++ ++ err = au_di_init(root); ++ if (!err) { ++ sb->s_root = root; ++ return 0; /* success */ ++ } ++ dput(root); ++ ++out: ++ return err; ++} ++ ++static int aufs_fill_super(struct super_block *sb, void *raw_data, ++ int silent __maybe_unused) ++{ ++ int err; ++ struct au_opts opts = { ++ .opt = NULL ++ }; ++ struct au_sbinfo *sbinfo; ++ struct dentry *root; ++ struct inode *inode; ++ char *arg = raw_data; ++ ++ if (unlikely(!arg || !*arg)) { ++ err = -EINVAL; ++ pr_err("no arg\n"); ++ goto out; ++ } ++ ++ err = -ENOMEM; ++ opts.opt = (void *)__get_free_page(GFP_NOFS); ++ if (unlikely(!opts.opt)) ++ goto out; ++ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt); ++ opts.sb_flags = sb->s_flags; ++ ++ err = au_si_alloc(sb); ++ if (unlikely(err)) ++ goto out_opts; ++ sbinfo = au_sbi(sb); ++ ++ /* all timestamps always follow the ones on the branch */ ++ sb->s_flags |= SB_NOATIME | SB_NODIRATIME; ++ sb->s_flags |= SB_I_VERSION; /* do we really need this? */ ++ sb->s_op = &aufs_sop; ++ sb->s_d_op = &aufs_dop; ++ sb->s_magic = AUFS_SUPER_MAGIC; ++ sb->s_maxbytes = 0; ++ sb->s_stack_depth = 1; ++ au_export_init(sb); ++ au_xattr_init(sb); ++ ++ err = alloc_root(sb); ++ if (unlikely(err)) { ++ si_write_unlock(sb); ++ goto out_info; ++ } ++ root = sb->s_root; ++ inode = d_inode(root); ++ ++ /* ++ * actually we can parse options regardless aufs lock here. ++ * but at remount time, parsing must be done before aufs lock. ++ * so we follow the same rule. ++ */ ++ ii_write_lock_parent(inode); ++ aufs_write_unlock(root); ++ err = au_opts_parse(sb, arg, &opts); ++ if (unlikely(err)) ++ goto out_root; ++ ++ /* lock vfs_inode first, then aufs. */ ++ inode_lock(inode); ++ aufs_write_lock(root); ++ err = au_opts_mount(sb, &opts); ++ au_opts_free(&opts); ++ if (!err && au_ftest_si(sbinfo, NO_DREVAL)) { ++ sb->s_d_op = &aufs_dop_noreval; ++ pr_info("%ps\n", sb->s_d_op); ++ au_refresh_dop(root, /*force_reval*/0); ++ sbinfo->si_iop_array = aufs_iop_nogetattr; ++ au_refresh_iop(inode, /*force_getattr*/0); ++ } ++ aufs_write_unlock(root); ++ inode_unlock(inode); ++ if (!err) ++ goto out_opts; /* success */ ++ ++out_root: ++ dput(root); ++ sb->s_root = NULL; ++out_info: ++ kobject_put(&sbinfo->si_kobj); ++ sb->s_fs_info = NULL; ++out_opts: ++ free_page((unsigned long)opts.opt); ++out: ++ AuTraceErr(err); ++ err = cvt_err(err); ++ AuTraceErr(err); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static struct dentry *aufs_mount(struct file_system_type *fs_type, int flags, ++ const char *dev_name __maybe_unused, ++ void *raw_data) ++{ ++ struct dentry *root; ++ ++ /* all timestamps always follow the ones on the branch */ ++ /* mnt->mnt_flags |= MNT_NOATIME | MNT_NODIRATIME; */ ++ root = mount_nodev(fs_type, flags, raw_data, aufs_fill_super); ++ if (IS_ERR(root)) ++ goto out; ++ ++ au_sbilist_add(root->d_sb); ++ ++out: ++ return root; ++} ++ ++static void aufs_kill_sb(struct super_block *sb) ++{ ++ struct au_sbinfo *sbinfo; ++ ++ sbinfo = au_sbi(sb); ++ if (sbinfo) { ++ au_sbilist_del(sb); ++ aufs_write_lock(sb->s_root); ++ au_fhsm_fin(sb); ++ if (sbinfo->si_wbr_create_ops->fin) ++ sbinfo->si_wbr_create_ops->fin(sb); ++ if (au_opt_test(sbinfo->si_mntflags, UDBA_HNOTIFY)) { ++ au_opt_set_udba(sbinfo->si_mntflags, UDBA_NONE); ++ au_remount_refresh(sb, /*do_idop*/0); ++ } ++ if (au_opt_test(sbinfo->si_mntflags, PLINK)) ++ au_plink_put(sb, /*verbose*/1); ++ au_xino_clr(sb); ++ au_dr_opt_flush(sb); ++ sbinfo->si_sb = NULL; ++ aufs_write_unlock(sb->s_root); ++ au_nwt_flush(&sbinfo->si_nowait); ++ } ++ kill_anon_super(sb); ++} ++ ++struct file_system_type aufs_fs_type = { ++ .name = AUFS_FSTYPE, ++ /* a race between rename and others */ ++ .fs_flags = FS_RENAME_DOES_D_MOVE, ++ .mount = aufs_mount, ++ .kill_sb = aufs_kill_sb, ++ /* no need to __module_get() and module_put(). */ ++ .owner = THIS_MODULE, ++}; +diff -Nurp linux-5.4/fs/aufs/super.h linux-5.4-aufs/fs/aufs/super.h +--- linux-5.4/fs/aufs/super.h 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/super.h 2019-11-28 01:25:59.068925618 +0200 +@@ -0,0 +1,576 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * super_block operations ++ */ ++ ++#ifndef __AUFS_SUPER_H__ ++#define __AUFS_SUPER_H__ ++ ++#ifdef __KERNEL__ ++ ++#include ++#include ++#include "hbl.h" ++#include "lcnt.h" ++#include "rwsem.h" ++#include "wkq.h" ++ ++/* policies to select one among multiple writable branches */ ++struct au_wbr_copyup_operations { ++ int (*copyup)(struct dentry *dentry); ++}; ++ ++#define AuWbr_DIR 1 /* target is a dir */ ++#define AuWbr_PARENT (1 << 1) /* always require a parent */ ++ ++#define au_ftest_wbr(flags, name) ((flags) & AuWbr_##name) ++#define au_fset_wbr(flags, name) { (flags) |= AuWbr_##name; } ++#define au_fclr_wbr(flags, name) { (flags) &= ~AuWbr_##name; } ++ ++struct au_wbr_create_operations { ++ int (*create)(struct dentry *dentry, unsigned int flags); ++ int (*init)(struct super_block *sb); ++ int (*fin)(struct super_block *sb); ++}; ++ ++struct au_wbr_mfs { ++ struct mutex mfs_lock; /* protect this structure */ ++ unsigned long mfs_jiffy; ++ unsigned long mfs_expire; ++ aufs_bindex_t mfs_bindex; ++ ++ unsigned long long mfsrr_bytes; ++ unsigned long long mfsrr_watermark; ++}; ++ ++#define AuPlink_NHASH 100 ++static inline int au_plink_hash(ino_t ino) ++{ ++ return ino % AuPlink_NHASH; ++} ++ ++/* File-based Hierarchical Storage Management */ ++struct au_fhsm { ++#ifdef CONFIG_AUFS_FHSM ++ /* allow only one process who can receive the notification */ ++ spinlock_t fhsm_spin; ++ pid_t fhsm_pid; ++ wait_queue_head_t fhsm_wqh; ++ atomic_t fhsm_readable; ++ ++ /* these are protected by si_rwsem */ ++ unsigned long fhsm_expire; ++ aufs_bindex_t fhsm_bottom; ++#endif ++}; ++ ++struct au_branch; ++struct au_sbinfo { ++ /* nowait tasks in the system-wide workqueue */ ++ struct au_nowait_tasks si_nowait; ++ ++ /* ++ * tried sb->s_umount, but failed due to the dependency between i_mutex. ++ * rwsem for au_sbinfo is necessary. ++ */ ++ struct au_rwsem si_rwsem; ++ ++ /* ++ * dirty approach to protect sb->sb_inodes and ->s_files (gone) from ++ * remount. ++ */ ++ au_lcnt_t si_ninodes, si_nfiles; ++ ++ /* branch management */ ++ unsigned int si_generation; ++ ++ /* see AuSi_ flags */ ++ unsigned char au_si_status; ++ ++ aufs_bindex_t si_bbot; ++ ++ /* dirty trick to keep br_id plus */ ++ unsigned int si_last_br_id : ++ sizeof(aufs_bindex_t) * BITS_PER_BYTE - 1; ++ struct au_branch **si_branch; ++ ++ /* policy to select a writable branch */ ++ unsigned char si_wbr_copyup; ++ unsigned char si_wbr_create; ++ struct au_wbr_copyup_operations *si_wbr_copyup_ops; ++ struct au_wbr_create_operations *si_wbr_create_ops; ++ ++ /* round robin */ ++ atomic_t si_wbr_rr_next; ++ ++ /* most free space */ ++ struct au_wbr_mfs si_wbr_mfs; ++ ++ /* File-based Hierarchical Storage Management */ ++ struct au_fhsm si_fhsm; ++ ++ /* mount flags */ ++ /* include/asm-ia64/siginfo.h defines a macro named si_flags */ ++ unsigned int si_mntflags; ++ ++ /* external inode number (bitmap and translation table) */ ++ vfs_readf_t si_xread; ++ vfs_writef_t si_xwrite; ++ loff_t si_ximaxent; /* max entries in a xino */ ++ ++ struct file *si_xib; ++ struct mutex si_xib_mtx; /* protect xib members */ ++ unsigned long *si_xib_buf; ++ unsigned long si_xib_last_pindex; ++ int si_xib_next_bit; ++ ++ unsigned long si_xino_jiffy; ++ unsigned long si_xino_expire; ++ /* reserved for future use */ ++ /* unsigned long long si_xib_limit; */ /* Max xib file size */ ++ ++#ifdef CONFIG_AUFS_EXPORT ++ /* i_generation */ ++ /* todo: make xigen file an array to support many inode numbers */ ++ struct file *si_xigen; ++ atomic_t si_xigen_next; ++#endif ++ ++ /* dirty trick to support atomic_open */ ++ struct hlist_bl_head si_aopen; ++ ++ /* vdir parameters */ ++ unsigned long si_rdcache; /* max cache time in jiffies */ ++ unsigned int si_rdblk; /* deblk size */ ++ unsigned int si_rdhash; /* hash size */ ++ ++ /* ++ * If the number of whiteouts are larger than si_dirwh, leave all of ++ * them after au_whtmp_ren to reduce the cost of rmdir(2). ++ * future fsck.aufs or kernel thread will remove them later. ++ * Otherwise, remove all whiteouts and the dir in rmdir(2). ++ */ ++ unsigned int si_dirwh; ++ ++ /* pseudo_link list */ ++ struct hlist_bl_head si_plink[AuPlink_NHASH]; ++ wait_queue_head_t si_plink_wq; ++ spinlock_t si_plink_maint_lock; ++ pid_t si_plink_maint_pid; ++ ++ /* file list */ ++ struct hlist_bl_head si_files; ++ ++ /* with/without getattr, brother of sb->s_d_op */ ++ struct inode_operations *si_iop_array; ++ ++ /* ++ * sysfs and lifetime management. ++ * this is not a small structure and it may be a waste of memory in case ++ * of sysfs is disabled, particularly when many aufs-es are mounted. ++ * but using sysfs is majority. ++ */ ++ struct kobject si_kobj; ++#ifdef CONFIG_DEBUG_FS ++ struct dentry *si_dbgaufs; ++ struct dentry *si_dbgaufs_plink; ++ struct dentry *si_dbgaufs_xib; ++#ifdef CONFIG_AUFS_EXPORT ++ struct dentry *si_dbgaufs_xigen; ++#endif ++#endif ++ ++#ifdef CONFIG_AUFS_SBILIST ++ struct hlist_bl_node si_list; ++#endif ++ ++ /* dirty, necessary for unmounting, sysfs and sysrq */ ++ struct super_block *si_sb; ++}; ++ ++/* sbinfo status flags */ ++/* ++ * set true when refresh_dirs() failed at remount time. ++ * then try refreshing dirs at access time again. ++ * if it is false, refreshing dirs at access time is unnecessary ++ */ ++#define AuSi_FAILED_REFRESH_DIR 1 ++#define AuSi_FHSM (1 << 1) /* fhsm is active now */ ++#define AuSi_NO_DREVAL (1 << 2) /* disable all d_revalidate */ ++ ++#ifndef CONFIG_AUFS_FHSM ++#undef AuSi_FHSM ++#define AuSi_FHSM 0 ++#endif ++ ++static inline unsigned char au_do_ftest_si(struct au_sbinfo *sbi, ++ unsigned int flag) ++{ ++ AuRwMustAnyLock(&sbi->si_rwsem); ++ return sbi->au_si_status & flag; ++} ++#define au_ftest_si(sbinfo, name) au_do_ftest_si(sbinfo, AuSi_##name) ++#define au_fset_si(sbinfo, name) do { \ ++ AuRwMustWriteLock(&(sbinfo)->si_rwsem); \ ++ (sbinfo)->au_si_status |= AuSi_##name; \ ++} while (0) ++#define au_fclr_si(sbinfo, name) do { \ ++ AuRwMustWriteLock(&(sbinfo)->si_rwsem); \ ++ (sbinfo)->au_si_status &= ~AuSi_##name; \ ++} while (0) ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* policy to select one among writable branches */ ++#define AuWbrCopyup(sbinfo, ...) \ ++ ((sbinfo)->si_wbr_copyup_ops->copyup(__VA_ARGS__)) ++#define AuWbrCreate(sbinfo, ...) \ ++ ((sbinfo)->si_wbr_create_ops->create(__VA_ARGS__)) ++ ++/* flags for si_read_lock()/aufs_read_lock()/di_read_lock() */ ++#define AuLock_DW 1 /* write-lock dentry */ ++#define AuLock_IR (1 << 1) /* read-lock inode */ ++#define AuLock_IW (1 << 2) /* write-lock inode */ ++#define AuLock_FLUSH (1 << 3) /* wait for 'nowait' tasks */ ++#define AuLock_DIRS (1 << 4) /* target is a pair of dirs */ ++ /* except RENAME_EXCHANGE */ ++#define AuLock_NOPLM (1 << 5) /* return err in plm mode */ ++#define AuLock_NOPLMW (1 << 6) /* wait for plm mode ends */ ++#define AuLock_GEN (1 << 7) /* test digen/iigen */ ++#define au_ftest_lock(flags, name) ((flags) & AuLock_##name) ++#define au_fset_lock(flags, name) \ ++ do { (flags) |= AuLock_##name; } while (0) ++#define au_fclr_lock(flags, name) \ ++ do { (flags) &= ~AuLock_##name; } while (0) ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* super.c */ ++extern struct file_system_type aufs_fs_type; ++struct inode *au_iget_locked(struct super_block *sb, ino_t ino); ++typedef unsigned long long (*au_arraycb_t)(struct super_block *sb, void *array, ++ unsigned long long max, void *arg); ++void *au_array_alloc(unsigned long long *hint, au_arraycb_t cb, ++ struct super_block *sb, void *arg); ++struct inode **au_iarray_alloc(struct super_block *sb, unsigned long long *max); ++void au_iarray_free(struct inode **a, unsigned long long max); ++ ++/* sbinfo.c */ ++void au_si_free(struct kobject *kobj); ++int au_si_alloc(struct super_block *sb); ++int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr, int may_shrink); ++ ++unsigned int au_sigen_inc(struct super_block *sb); ++aufs_bindex_t au_new_br_id(struct super_block *sb); ++ ++int si_read_lock(struct super_block *sb, int flags); ++int si_write_lock(struct super_block *sb, int flags); ++int aufs_read_lock(struct dentry *dentry, int flags); ++void aufs_read_unlock(struct dentry *dentry, int flags); ++void aufs_write_lock(struct dentry *dentry); ++void aufs_write_unlock(struct dentry *dentry); ++int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags); ++void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2); ++ ++/* wbr_policy.c */ ++extern struct au_wbr_copyup_operations au_wbr_copyup_ops[]; ++extern struct au_wbr_create_operations au_wbr_create_ops[]; ++int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst); ++int au_wbr_nonopq(struct dentry *dentry, aufs_bindex_t bindex); ++int au_wbr_do_copyup_bu(struct dentry *dentry, aufs_bindex_t btop); ++ ++/* mvdown.c */ ++int au_mvdown(struct dentry *dentry, struct aufs_mvdown __user *arg); ++ ++#ifdef CONFIG_AUFS_FHSM ++/* fhsm.c */ ++ ++static inline pid_t au_fhsm_pid(struct au_fhsm *fhsm) ++{ ++ pid_t pid; ++ ++ spin_lock(&fhsm->fhsm_spin); ++ pid = fhsm->fhsm_pid; ++ spin_unlock(&fhsm->fhsm_spin); ++ ++ return pid; ++} ++ ++void au_fhsm_wrote(struct super_block *sb, aufs_bindex_t bindex, int force); ++void au_fhsm_wrote_all(struct super_block *sb, int force); ++int au_fhsm_fd(struct super_block *sb, int oflags); ++int au_fhsm_br_alloc(struct au_branch *br); ++void au_fhsm_set_bottom(struct super_block *sb, aufs_bindex_t bindex); ++void au_fhsm_fin(struct super_block *sb); ++void au_fhsm_init(struct au_sbinfo *sbinfo); ++void au_fhsm_set(struct au_sbinfo *sbinfo, unsigned int sec); ++void au_fhsm_show(struct seq_file *seq, struct au_sbinfo *sbinfo); ++#else ++AuStubVoid(au_fhsm_wrote, struct super_block *sb, aufs_bindex_t bindex, ++ int force) ++AuStubVoid(au_fhsm_wrote_all, struct super_block *sb, int force) ++AuStub(int, au_fhsm_fd, return -EOPNOTSUPP, struct super_block *sb, int oflags) ++AuStub(pid_t, au_fhsm_pid, return 0, struct au_fhsm *fhsm) ++AuStubInt0(au_fhsm_br_alloc, struct au_branch *br) ++AuStubVoid(au_fhsm_set_bottom, struct super_block *sb, aufs_bindex_t bindex) ++AuStubVoid(au_fhsm_fin, struct super_block *sb) ++AuStubVoid(au_fhsm_init, struct au_sbinfo *sbinfo) ++AuStubVoid(au_fhsm_set, struct au_sbinfo *sbinfo, unsigned int sec) ++AuStubVoid(au_fhsm_show, struct seq_file *seq, struct au_sbinfo *sbinfo) ++#endif ++ ++/* ---------------------------------------------------------------------- */ ++ ++static inline struct au_sbinfo *au_sbi(struct super_block *sb) ++{ ++ return sb->s_fs_info; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++#ifdef CONFIG_AUFS_EXPORT ++int au_test_nfsd(void); ++void au_export_init(struct super_block *sb); ++void au_xigen_inc(struct inode *inode); ++int au_xigen_new(struct inode *inode); ++int au_xigen_set(struct super_block *sb, struct path *path); ++void au_xigen_clr(struct super_block *sb); ++ ++static inline int au_busy_or_stale(void) ++{ ++ if (!au_test_nfsd()) ++ return -EBUSY; ++ return -ESTALE; ++} ++#else ++AuStubInt0(au_test_nfsd, void) ++AuStubVoid(au_export_init, struct super_block *sb) ++AuStubVoid(au_xigen_inc, struct inode *inode) ++AuStubInt0(au_xigen_new, struct inode *inode) ++AuStubInt0(au_xigen_set, struct super_block *sb, struct path *path) ++AuStubVoid(au_xigen_clr, struct super_block *sb) ++AuStub(int, au_busy_or_stale, return -EBUSY, void) ++#endif /* CONFIG_AUFS_EXPORT */ ++ ++/* ---------------------------------------------------------------------- */ ++ ++#ifdef CONFIG_AUFS_SBILIST ++/* module.c */ ++extern struct hlist_bl_head au_sbilist; ++ ++static inline void au_sbilist_init(void) ++{ ++ INIT_HLIST_BL_HEAD(&au_sbilist); ++} ++ ++static inline void au_sbilist_add(struct super_block *sb) ++{ ++ au_hbl_add(&au_sbi(sb)->si_list, &au_sbilist); ++} ++ ++static inline void au_sbilist_del(struct super_block *sb) ++{ ++ au_hbl_del(&au_sbi(sb)->si_list, &au_sbilist); ++} ++ ++#ifdef CONFIG_AUFS_MAGIC_SYSRQ ++static inline void au_sbilist_lock(void) ++{ ++ hlist_bl_lock(&au_sbilist); ++} ++ ++static inline void au_sbilist_unlock(void) ++{ ++ hlist_bl_unlock(&au_sbilist); ++} ++#define AuGFP_SBILIST GFP_ATOMIC ++#else ++AuStubVoid(au_sbilist_lock, void) ++AuStubVoid(au_sbilist_unlock, void) ++#define AuGFP_SBILIST GFP_NOFS ++#endif /* CONFIG_AUFS_MAGIC_SYSRQ */ ++#else ++AuStubVoid(au_sbilist_init, void) ++AuStubVoid(au_sbilist_add, struct super_block *sb) ++AuStubVoid(au_sbilist_del, struct super_block *sb) ++AuStubVoid(au_sbilist_lock, void) ++AuStubVoid(au_sbilist_unlock, void) ++#define AuGFP_SBILIST GFP_NOFS ++#endif ++ ++/* ---------------------------------------------------------------------- */ ++ ++static inline void dbgaufs_si_null(struct au_sbinfo *sbinfo) ++{ ++ /* ++ * This function is a dynamic '__init' function actually, ++ * so the tiny check for si_rwsem is unnecessary. ++ */ ++ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */ ++#ifdef CONFIG_DEBUG_FS ++ sbinfo->si_dbgaufs = NULL; ++ sbinfo->si_dbgaufs_plink = NULL; ++ sbinfo->si_dbgaufs_xib = NULL; ++#ifdef CONFIG_AUFS_EXPORT ++ sbinfo->si_dbgaufs_xigen = NULL; ++#endif ++#endif ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* current->atomic_flags */ ++/* this value should never corrupt the ones defined in linux/sched.h */ ++#define PFA_AUFS 0x10 ++ ++TASK_PFA_TEST(AUFS, test_aufs) /* task_test_aufs */ ++TASK_PFA_SET(AUFS, aufs) /* task_set_aufs */ ++TASK_PFA_CLEAR(AUFS, aufs) /* task_clear_aufs */ ++ ++static inline int si_pid_test(struct super_block *sb) ++{ ++ return !!task_test_aufs(current); ++} ++ ++static inline void si_pid_clr(struct super_block *sb) ++{ ++ AuDebugOn(!task_test_aufs(current)); ++ task_clear_aufs(current); ++} ++ ++static inline void si_pid_set(struct super_block *sb) ++{ ++ AuDebugOn(task_test_aufs(current)); ++ task_set_aufs(current); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* lock superblock. mainly for entry point functions */ ++#define __si_read_lock(sb) au_rw_read_lock(&au_sbi(sb)->si_rwsem) ++#define __si_write_lock(sb) au_rw_write_lock(&au_sbi(sb)->si_rwsem) ++#define __si_read_trylock(sb) au_rw_read_trylock(&au_sbi(sb)->si_rwsem) ++#define __si_write_trylock(sb) au_rw_write_trylock(&au_sbi(sb)->si_rwsem) ++/* ++#define __si_read_trylock_nested(sb) \ ++ au_rw_read_trylock_nested(&au_sbi(sb)->si_rwsem) ++#define __si_write_trylock_nested(sb) \ ++ au_rw_write_trylock_nested(&au_sbi(sb)->si_rwsem) ++*/ ++ ++#define __si_read_unlock(sb) au_rw_read_unlock(&au_sbi(sb)->si_rwsem) ++#define __si_write_unlock(sb) au_rw_write_unlock(&au_sbi(sb)->si_rwsem) ++#define __si_downgrade_lock(sb) au_rw_dgrade_lock(&au_sbi(sb)->si_rwsem) ++ ++#define SiMustNoWaiters(sb) AuRwMustNoWaiters(&au_sbi(sb)->si_rwsem) ++#define SiMustAnyLock(sb) AuRwMustAnyLock(&au_sbi(sb)->si_rwsem) ++#define SiMustWriteLock(sb) AuRwMustWriteLock(&au_sbi(sb)->si_rwsem) ++ ++static inline void si_noflush_read_lock(struct super_block *sb) ++{ ++ __si_read_lock(sb); ++ si_pid_set(sb); ++} ++ ++static inline int si_noflush_read_trylock(struct super_block *sb) ++{ ++ int locked; ++ ++ locked = __si_read_trylock(sb); ++ if (locked) ++ si_pid_set(sb); ++ return locked; ++} ++ ++static inline void si_noflush_write_lock(struct super_block *sb) ++{ ++ __si_write_lock(sb); ++ si_pid_set(sb); ++} ++ ++static inline int si_noflush_write_trylock(struct super_block *sb) ++{ ++ int locked; ++ ++ locked = __si_write_trylock(sb); ++ if (locked) ++ si_pid_set(sb); ++ return locked; ++} ++ ++#if 0 /* reserved */ ++static inline int si_read_trylock(struct super_block *sb, int flags) ++{ ++ if (au_ftest_lock(flags, FLUSH)) ++ au_nwt_flush(&au_sbi(sb)->si_nowait); ++ return si_noflush_read_trylock(sb); ++} ++#endif ++ ++static inline void si_read_unlock(struct super_block *sb) ++{ ++ si_pid_clr(sb); ++ __si_read_unlock(sb); ++} ++ ++#if 0 /* reserved */ ++static inline int si_write_trylock(struct super_block *sb, int flags) ++{ ++ if (au_ftest_lock(flags, FLUSH)) ++ au_nwt_flush(&au_sbi(sb)->si_nowait); ++ return si_noflush_write_trylock(sb); ++} ++#endif ++ ++static inline void si_write_unlock(struct super_block *sb) ++{ ++ si_pid_clr(sb); ++ __si_write_unlock(sb); ++} ++ ++#if 0 /* reserved */ ++static inline void si_downgrade_lock(struct super_block *sb) ++{ ++ __si_downgrade_lock(sb); ++} ++#endif ++ ++/* ---------------------------------------------------------------------- */ ++ ++static inline aufs_bindex_t au_sbbot(struct super_block *sb) ++{ ++ SiMustAnyLock(sb); ++ return au_sbi(sb)->si_bbot; ++} ++ ++static inline unsigned int au_mntflags(struct super_block *sb) ++{ ++ SiMustAnyLock(sb); ++ return au_sbi(sb)->si_mntflags; ++} ++ ++static inline unsigned int au_sigen(struct super_block *sb) ++{ ++ SiMustAnyLock(sb); ++ return au_sbi(sb)->si_generation; ++} ++ ++static inline struct au_branch *au_sbr(struct super_block *sb, ++ aufs_bindex_t bindex) ++{ ++ SiMustAnyLock(sb); ++ return au_sbi(sb)->si_branch[0 + bindex]; ++} ++ ++static inline loff_t au_xi_maxent(struct super_block *sb) ++{ ++ SiMustAnyLock(sb); ++ return au_sbi(sb)->si_ximaxent; ++} ++ ++#endif /* __KERNEL__ */ ++#endif /* __AUFS_SUPER_H__ */ +diff -Nurp linux-5.4/fs/aufs/sysaufs.c linux-5.4-aufs/fs/aufs/sysaufs.c +--- linux-5.4/fs/aufs/sysaufs.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/sysaufs.c 2019-11-28 01:25:59.068925618 +0200 +@@ -0,0 +1,80 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * sysfs interface and lifetime management ++ * they are necessary regardless sysfs is disabled. ++ */ ++ ++#include ++#include "aufs.h" ++ ++unsigned long sysaufs_si_mask; ++struct kset *sysaufs_kset; ++ ++#define AuSiAttr(_name) { \ ++ .attr = { .name = __stringify(_name), .mode = 0444 }, \ ++ .show = sysaufs_si_##_name, \ ++} ++ ++static struct sysaufs_si_attr sysaufs_si_attr_xi_path = AuSiAttr(xi_path); ++struct attribute *sysaufs_si_attrs[] = { ++ &sysaufs_si_attr_xi_path.attr, ++ NULL, ++}; ++ ++static const struct sysfs_ops au_sbi_ops = { ++ .show = sysaufs_si_show ++}; ++ ++static struct kobj_type au_sbi_ktype = { ++ .release = au_si_free, ++ .sysfs_ops = &au_sbi_ops, ++ .default_attrs = sysaufs_si_attrs ++}; ++ ++/* ---------------------------------------------------------------------- */ ++ ++int sysaufs_si_init(struct au_sbinfo *sbinfo) ++{ ++ int err; ++ ++ sbinfo->si_kobj.kset = sysaufs_kset; ++ /* cf. sysaufs_name() */ ++ err = kobject_init_and_add ++ (&sbinfo->si_kobj, &au_sbi_ktype, /*&sysaufs_kset->kobj*/NULL, ++ SysaufsSiNamePrefix "%lx", sysaufs_si_id(sbinfo)); ++ ++ return err; ++} ++ ++void sysaufs_fin(void) ++{ ++ sysfs_remove_group(&sysaufs_kset->kobj, sysaufs_attr_group); ++ kset_unregister(sysaufs_kset); ++} ++ ++int __init sysaufs_init(void) ++{ ++ int err; ++ ++ do { ++ get_random_bytes(&sysaufs_si_mask, sizeof(sysaufs_si_mask)); ++ } while (!sysaufs_si_mask); ++ ++ err = -EINVAL; ++ sysaufs_kset = kset_create_and_add(AUFS_NAME, NULL, fs_kobj); ++ if (unlikely(!sysaufs_kset)) ++ goto out; ++ err = PTR_ERR(sysaufs_kset); ++ if (IS_ERR(sysaufs_kset)) ++ goto out; ++ err = sysfs_create_group(&sysaufs_kset->kobj, sysaufs_attr_group); ++ if (unlikely(err)) ++ kset_unregister(sysaufs_kset); ++ ++out: ++ return err; ++} +diff -Nurp linux-5.4/fs/aufs/sysaufs.h linux-5.4-aufs/fs/aufs/sysaufs.h +--- linux-5.4/fs/aufs/sysaufs.h 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/sysaufs.h 2019-11-28 01:25:59.068925618 +0200 +@@ -0,0 +1,89 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * sysfs interface and mount lifetime management ++ */ ++ ++#ifndef __SYSAUFS_H__ ++#define __SYSAUFS_H__ ++ ++#ifdef __KERNEL__ ++ ++#include ++#include "module.h" ++ ++struct super_block; ++struct au_sbinfo; ++ ++struct sysaufs_si_attr { ++ struct attribute attr; ++ int (*show)(struct seq_file *seq, struct super_block *sb); ++}; ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* sysaufs.c */ ++extern unsigned long sysaufs_si_mask; ++extern struct kset *sysaufs_kset; ++extern struct attribute *sysaufs_si_attrs[]; ++int sysaufs_si_init(struct au_sbinfo *sbinfo); ++int __init sysaufs_init(void); ++void sysaufs_fin(void); ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* some people doesn't like to show a pointer in kernel */ ++static inline unsigned long sysaufs_si_id(struct au_sbinfo *sbinfo) ++{ ++ return sysaufs_si_mask ^ (unsigned long)sbinfo; ++} ++ ++#define SysaufsSiNamePrefix "si_" ++#define SysaufsSiNameLen (sizeof(SysaufsSiNamePrefix) + 16) ++static inline void sysaufs_name(struct au_sbinfo *sbinfo, char *name) ++{ ++ snprintf(name, SysaufsSiNameLen, SysaufsSiNamePrefix "%lx", ++ sysaufs_si_id(sbinfo)); ++} ++ ++struct au_branch; ++#ifdef CONFIG_SYSFS ++/* sysfs.c */ ++extern struct attribute_group *sysaufs_attr_group; ++ ++int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb); ++ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr, ++ char *buf); ++long au_brinfo_ioctl(struct file *file, unsigned long arg); ++#ifdef CONFIG_COMPAT ++long au_brinfo_compat_ioctl(struct file *file, unsigned long arg); ++#endif ++ ++void sysaufs_br_init(struct au_branch *br); ++void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex); ++void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex); ++ ++#define sysaufs_brs_init() do {} while (0) ++ ++#else ++#define sysaufs_attr_group NULL ++ ++AuStubInt0(sysaufs_si_xi_path, struct seq_file *seq, struct super_block *sb) ++AuStub(ssize_t, sysaufs_si_show, return 0, struct kobject *kobj, ++ struct attribute *attr, char *buf) ++AuStubVoid(sysaufs_br_init, struct au_branch *br) ++AuStubVoid(sysaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex) ++AuStubVoid(sysaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex) ++ ++static inline void sysaufs_brs_init(void) ++{ ++ sysaufs_brs = 0; ++} ++ ++#endif /* CONFIG_SYSFS */ ++ ++#endif /* __KERNEL__ */ ++#endif /* __SYSAUFS_H__ */ +diff -Nurp linux-5.4/fs/aufs/sysfs.c linux-5.4-aufs/fs/aufs/sysfs.c +--- linux-5.4/fs/aufs/sysfs.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/sysfs.c 2019-11-28 01:25:59.068925618 +0200 +@@ -0,0 +1,338 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * sysfs interface ++ */ ++ ++#include ++#include ++#include "aufs.h" ++ ++static struct attribute *au_attr[] = { ++ NULL, /* need to NULL terminate the list of attributes */ ++}; ++ ++static struct attribute_group sysaufs_attr_group_body = { ++ .attrs = au_attr ++}; ++ ++struct attribute_group *sysaufs_attr_group = &sysaufs_attr_group_body; ++ ++/* ---------------------------------------------------------------------- */ ++ ++int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb) ++{ ++ int err; ++ ++ SiMustAnyLock(sb); ++ ++ err = 0; ++ if (au_opt_test(au_mntflags(sb), XINO)) { ++ err = au_xino_path(seq, au_sbi(sb)->si_xib); ++ seq_putc(seq, '\n'); ++ } ++ return err; ++} ++ ++/* ++ * the lifetime of branch is independent from the entry under sysfs. ++ * sysfs handles the lifetime of the entry, and never call ->show() after it is ++ * unlinked. ++ */ ++static int sysaufs_si_br(struct seq_file *seq, struct super_block *sb, ++ aufs_bindex_t bindex, int idx) ++{ ++ int err; ++ struct path path; ++ struct dentry *root; ++ struct au_branch *br; ++ au_br_perm_str_t perm; ++ ++ AuDbg("b%d\n", bindex); ++ ++ err = 0; ++ root = sb->s_root; ++ di_read_lock_parent(root, !AuLock_IR); ++ br = au_sbr(sb, bindex); ++ ++ switch (idx) { ++ case AuBrSysfs_BR: ++ path.mnt = au_br_mnt(br); ++ path.dentry = au_h_dptr(root, bindex); ++ err = au_seq_path(seq, &path); ++ if (!err) { ++ au_optstr_br_perm(&perm, br->br_perm); ++ seq_printf(seq, "=%s\n", perm.a); ++ } ++ break; ++ case AuBrSysfs_BRID: ++ seq_printf(seq, "%d\n", br->br_id); ++ break; ++ } ++ di_read_unlock(root, !AuLock_IR); ++ if (unlikely(err || seq_has_overflowed(seq))) ++ err = -E2BIG; ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static struct seq_file *au_seq(char *p, ssize_t len) ++{ ++ struct seq_file *seq; ++ ++ seq = kzalloc(sizeof(*seq), GFP_NOFS); ++ if (seq) { ++ /* mutex_init(&seq.lock); */ ++ seq->buf = p; ++ seq->size = len; ++ return seq; /* success */ ++ } ++ ++ seq = ERR_PTR(-ENOMEM); ++ return seq; ++} ++ ++#define SysaufsBr_PREFIX "br" ++#define SysaufsBrid_PREFIX "brid" ++ ++/* todo: file size may exceed PAGE_SIZE */ ++ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr, ++ char *buf) ++{ ++ ssize_t err; ++ int idx; ++ long l; ++ aufs_bindex_t bbot; ++ struct au_sbinfo *sbinfo; ++ struct super_block *sb; ++ struct seq_file *seq; ++ char *name; ++ struct attribute **cattr; ++ ++ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj); ++ sb = sbinfo->si_sb; ++ ++ /* ++ * prevent a race condition between sysfs and aufs. ++ * for instance, sysfs_file_read() calls sysfs_get_active_two() which ++ * prohibits maintaining the sysfs entries. ++ * hew we acquire read lock after sysfs_get_active_two(). ++ * on the other hand, the remount process may maintain the sysfs/aufs ++ * entries after acquiring write lock. ++ * it can cause a deadlock. ++ * simply we gave up processing read here. ++ */ ++ err = -EBUSY; ++ if (unlikely(!si_noflush_read_trylock(sb))) ++ goto out; ++ ++ seq = au_seq(buf, PAGE_SIZE); ++ err = PTR_ERR(seq); ++ if (IS_ERR(seq)) ++ goto out_unlock; ++ ++ name = (void *)attr->name; ++ cattr = sysaufs_si_attrs; ++ while (*cattr) { ++ if (!strcmp(name, (*cattr)->name)) { ++ err = container_of(*cattr, struct sysaufs_si_attr, attr) ++ ->show(seq, sb); ++ goto out_seq; ++ } ++ cattr++; ++ } ++ ++ if (!strncmp(name, SysaufsBrid_PREFIX, ++ sizeof(SysaufsBrid_PREFIX) - 1)) { ++ idx = AuBrSysfs_BRID; ++ name += sizeof(SysaufsBrid_PREFIX) - 1; ++ } else if (!strncmp(name, SysaufsBr_PREFIX, ++ sizeof(SysaufsBr_PREFIX) - 1)) { ++ idx = AuBrSysfs_BR; ++ name += sizeof(SysaufsBr_PREFIX) - 1; ++ } else ++ BUG(); ++ ++ err = kstrtol(name, 10, &l); ++ if (!err) { ++ bbot = au_sbbot(sb); ++ if (l <= bbot) ++ err = sysaufs_si_br(seq, sb, (aufs_bindex_t)l, idx); ++ else ++ err = -ENOENT; ++ } ++ ++out_seq: ++ if (!err) { ++ err = seq->count; ++ /* sysfs limit */ ++ if (unlikely(err == PAGE_SIZE)) ++ err = -EFBIG; ++ } ++ au_kfree_rcu(seq); ++out_unlock: ++ si_read_unlock(sb); ++out: ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int au_brinfo(struct super_block *sb, union aufs_brinfo __user *arg) ++{ ++ int err; ++ int16_t brid; ++ aufs_bindex_t bindex, bbot; ++ size_t sz; ++ char *buf; ++ struct seq_file *seq; ++ struct au_branch *br; ++ ++ si_read_lock(sb, AuLock_FLUSH); ++ bbot = au_sbbot(sb); ++ err = bbot + 1; ++ if (!arg) ++ goto out; ++ ++ err = -ENOMEM; ++ buf = (void *)__get_free_page(GFP_NOFS); ++ if (unlikely(!buf)) ++ goto out; ++ ++ seq = au_seq(buf, PAGE_SIZE); ++ err = PTR_ERR(seq); ++ if (IS_ERR(seq)) ++ goto out_buf; ++ ++ sz = sizeof(*arg) - offsetof(union aufs_brinfo, path); ++ for (bindex = 0; bindex <= bbot; bindex++, arg++) { ++ /* VERIFY_WRITE */ ++ err = !access_ok(arg, sizeof(*arg)); ++ if (unlikely(err)) ++ break; ++ ++ br = au_sbr(sb, bindex); ++ brid = br->br_id; ++ BUILD_BUG_ON(sizeof(brid) != sizeof(arg->id)); ++ err = __put_user(brid, &arg->id); ++ if (unlikely(err)) ++ break; ++ ++ BUILD_BUG_ON(sizeof(br->br_perm) != sizeof(arg->perm)); ++ err = __put_user(br->br_perm, &arg->perm); ++ if (unlikely(err)) ++ break; ++ ++ err = au_seq_path(seq, &br->br_path); ++ if (unlikely(err)) ++ break; ++ seq_putc(seq, '\0'); ++ if (!seq_has_overflowed(seq)) { ++ err = copy_to_user(arg->path, seq->buf, seq->count); ++ seq->count = 0; ++ if (unlikely(err)) ++ break; ++ } else { ++ err = -E2BIG; ++ goto out_seq; ++ } ++ } ++ if (unlikely(err)) ++ err = -EFAULT; ++ ++out_seq: ++ au_kfree_rcu(seq); ++out_buf: ++ free_page((unsigned long)buf); ++out: ++ si_read_unlock(sb); ++ return err; ++} ++ ++long au_brinfo_ioctl(struct file *file, unsigned long arg) ++{ ++ return au_brinfo(file->f_path.dentry->d_sb, (void __user *)arg); ++} ++ ++#ifdef CONFIG_COMPAT ++long au_brinfo_compat_ioctl(struct file *file, unsigned long arg) ++{ ++ return au_brinfo(file->f_path.dentry->d_sb, compat_ptr(arg)); ++} ++#endif ++ ++/* ---------------------------------------------------------------------- */ ++ ++void sysaufs_br_init(struct au_branch *br) ++{ ++ int i; ++ struct au_brsysfs *br_sysfs; ++ struct attribute *attr; ++ ++ br_sysfs = br->br_sysfs; ++ for (i = 0; i < ARRAY_SIZE(br->br_sysfs); i++) { ++ attr = &br_sysfs->attr; ++ sysfs_attr_init(attr); ++ attr->name = br_sysfs->name; ++ attr->mode = 0444; ++ br_sysfs++; ++ } ++} ++ ++void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex) ++{ ++ struct au_branch *br; ++ struct kobject *kobj; ++ struct au_brsysfs *br_sysfs; ++ int i; ++ aufs_bindex_t bbot; ++ ++ if (!sysaufs_brs) ++ return; ++ ++ kobj = &au_sbi(sb)->si_kobj; ++ bbot = au_sbbot(sb); ++ for (; bindex <= bbot; bindex++) { ++ br = au_sbr(sb, bindex); ++ br_sysfs = br->br_sysfs; ++ for (i = 0; i < ARRAY_SIZE(br->br_sysfs); i++) { ++ sysfs_remove_file(kobj, &br_sysfs->attr); ++ br_sysfs++; ++ } ++ } ++} ++ ++void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex) ++{ ++ int err, i; ++ aufs_bindex_t bbot; ++ struct kobject *kobj; ++ struct au_branch *br; ++ struct au_brsysfs *br_sysfs; ++ ++ if (!sysaufs_brs) ++ return; ++ ++ kobj = &au_sbi(sb)->si_kobj; ++ bbot = au_sbbot(sb); ++ for (; bindex <= bbot; bindex++) { ++ br = au_sbr(sb, bindex); ++ br_sysfs = br->br_sysfs; ++ snprintf(br_sysfs[AuBrSysfs_BR].name, sizeof(br_sysfs->name), ++ SysaufsBr_PREFIX "%d", bindex); ++ snprintf(br_sysfs[AuBrSysfs_BRID].name, sizeof(br_sysfs->name), ++ SysaufsBrid_PREFIX "%d", bindex); ++ for (i = 0; i < ARRAY_SIZE(br->br_sysfs); i++) { ++ err = sysfs_create_file(kobj, &br_sysfs->attr); ++ if (unlikely(err)) ++ pr_warn("failed %s under sysfs(%d)\n", ++ br_sysfs->name, err); ++ br_sysfs++; ++ } ++ } ++} +diff -Nurp linux-5.4/fs/aufs/sysrq.c linux-5.4-aufs/fs/aufs/sysrq.c +--- linux-5.4/fs/aufs/sysrq.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/sysrq.c 2019-11-28 01:25:59.068925618 +0200 +@@ -0,0 +1,147 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * magic sysrq handler ++ */ ++ ++/* #include */ ++#include ++#include "aufs.h" ++ ++/* ---------------------------------------------------------------------- */ ++ ++static void sysrq_sb(struct super_block *sb) ++{ ++ char *plevel; ++ struct au_sbinfo *sbinfo; ++ struct file *file; ++ struct hlist_bl_head *files; ++ struct hlist_bl_node *pos; ++ struct au_finfo *finfo; ++ ++ plevel = au_plevel; ++ au_plevel = KERN_WARNING; ++ ++ /* since we define pr_fmt, call printk directly */ ++#define pr(str) printk(KERN_WARNING AUFS_NAME ": " str) ++ ++ sbinfo = au_sbi(sb); ++ printk(KERN_WARNING "si=%lx\n", sysaufs_si_id(sbinfo)); ++ pr("superblock\n"); ++ au_dpri_sb(sb); ++ ++#if 0 ++ pr("root dentry\n"); ++ au_dpri_dentry(sb->s_root); ++ pr("root inode\n"); ++ au_dpri_inode(d_inode(sb->s_root)); ++#endif ++ ++#if 0 ++ do { ++ int err, i, j, ndentry; ++ struct au_dcsub_pages dpages; ++ struct au_dpage *dpage; ++ ++ err = au_dpages_init(&dpages, GFP_ATOMIC); ++ if (unlikely(err)) ++ break; ++ err = au_dcsub_pages(&dpages, sb->s_root, NULL, NULL); ++ if (!err) ++ for (i = 0; i < dpages.ndpage; i++) { ++ dpage = dpages.dpages + i; ++ ndentry = dpage->ndentry; ++ for (j = 0; j < ndentry; j++) ++ au_dpri_dentry(dpage->dentries[j]); ++ } ++ au_dpages_free(&dpages); ++ } while (0); ++#endif ++ ++#if 1 ++ { ++ struct inode *i; ++ ++ pr("isolated inode\n"); ++ spin_lock(&sb->s_inode_list_lock); ++ list_for_each_entry(i, &sb->s_inodes, i_sb_list) { ++ spin_lock(&i->i_lock); ++ if (1 || hlist_empty(&i->i_dentry)) ++ au_dpri_inode(i); ++ spin_unlock(&i->i_lock); ++ } ++ spin_unlock(&sb->s_inode_list_lock); ++ } ++#endif ++ pr("files\n"); ++ files = &au_sbi(sb)->si_files; ++ hlist_bl_lock(files); ++ hlist_bl_for_each_entry(finfo, pos, files, fi_hlist) { ++ umode_t mode; ++ ++ file = finfo->fi_file; ++ mode = file_inode(file)->i_mode; ++ if (!special_file(mode)) ++ au_dpri_file(file); ++ } ++ hlist_bl_unlock(files); ++ pr("done\n"); ++ ++#undef pr ++ au_plevel = plevel; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* module parameter */ ++static char *aufs_sysrq_key = "a"; ++module_param_named(sysrq, aufs_sysrq_key, charp, 0444); ++MODULE_PARM_DESC(sysrq, "MagicSysRq key for " AUFS_NAME); ++ ++static void au_sysrq(int key __maybe_unused) ++{ ++ struct au_sbinfo *sbinfo; ++ struct hlist_bl_node *pos; ++ ++ lockdep_off(); ++ au_sbilist_lock(); ++ hlist_bl_for_each_entry(sbinfo, pos, &au_sbilist, si_list) ++ sysrq_sb(sbinfo->si_sb); ++ au_sbilist_unlock(); ++ lockdep_on(); ++} ++ ++static struct sysrq_key_op au_sysrq_op = { ++ .handler = au_sysrq, ++ .help_msg = "Aufs", ++ .action_msg = "Aufs", ++ .enable_mask = SYSRQ_ENABLE_DUMP ++}; ++ ++/* ---------------------------------------------------------------------- */ ++ ++int __init au_sysrq_init(void) ++{ ++ int err; ++ char key; ++ ++ err = -1; ++ key = *aufs_sysrq_key; ++ if ('a' <= key && key <= 'z') ++ err = register_sysrq_key(key, &au_sysrq_op); ++ if (unlikely(err)) ++ pr_err("err %d, sysrq=%c\n", err, key); ++ return err; ++} ++ ++void au_sysrq_fin(void) ++{ ++ int err; ++ ++ err = unregister_sysrq_key(*aufs_sysrq_key, &au_sysrq_op); ++ if (unlikely(err)) ++ pr_err("err %d (ignored)\n", err); ++} +diff -Nurp linux-5.4/fs/aufs/wbr_policy.c linux-5.4-aufs/fs/aufs/wbr_policy.c +--- linux-5.4/fs/aufs/wbr_policy.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/wbr_policy.c 2019-11-28 01:25:59.068925618 +0200 +@@ -0,0 +1,817 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * policies for selecting one among multiple writable branches ++ */ ++ ++#include ++#include "aufs.h" ++ ++/* subset of cpup_attr() */ ++static noinline_for_stack ++int au_cpdown_attr(struct path *h_path, struct dentry *h_src) ++{ ++ int err, sbits; ++ struct iattr ia; ++ struct inode *h_isrc; ++ ++ h_isrc = d_inode(h_src); ++ ia.ia_valid = ATTR_FORCE | ATTR_MODE | ATTR_UID | ATTR_GID; ++ ia.ia_mode = h_isrc->i_mode; ++ ia.ia_uid = h_isrc->i_uid; ++ ia.ia_gid = h_isrc->i_gid; ++ sbits = !!(ia.ia_mode & (S_ISUID | S_ISGID)); ++ au_cpup_attr_flags(d_inode(h_path->dentry), h_isrc->i_flags); ++ /* no delegation since it is just created */ ++ err = vfsub_sio_notify_change(h_path, &ia, /*delegated*/NULL); ++ ++ /* is this nfs only? */ ++ if (!err && sbits && au_test_nfs(h_path->dentry->d_sb)) { ++ ia.ia_valid = ATTR_FORCE | ATTR_MODE; ++ ia.ia_mode = h_isrc->i_mode; ++ err = vfsub_sio_notify_change(h_path, &ia, /*delegated*/NULL); ++ } ++ ++ return err; ++} ++ ++#define AuCpdown_PARENT_OPQ 1 ++#define AuCpdown_WHED (1 << 1) ++#define AuCpdown_MADE_DIR (1 << 2) ++#define AuCpdown_DIROPQ (1 << 3) ++#define au_ftest_cpdown(flags, name) ((flags) & AuCpdown_##name) ++#define au_fset_cpdown(flags, name) \ ++ do { (flags) |= AuCpdown_##name; } while (0) ++#define au_fclr_cpdown(flags, name) \ ++ do { (flags) &= ~AuCpdown_##name; } while (0) ++ ++static int au_cpdown_dir_opq(struct dentry *dentry, aufs_bindex_t bdst, ++ unsigned int *flags) ++{ ++ int err; ++ struct dentry *opq_dentry; ++ ++ opq_dentry = au_diropq_create(dentry, bdst); ++ err = PTR_ERR(opq_dentry); ++ if (IS_ERR(opq_dentry)) ++ goto out; ++ dput(opq_dentry); ++ au_fset_cpdown(*flags, DIROPQ); ++ ++out: ++ return err; ++} ++ ++static int au_cpdown_dir_wh(struct dentry *dentry, struct dentry *h_parent, ++ struct inode *dir, aufs_bindex_t bdst) ++{ ++ int err; ++ struct path h_path; ++ struct au_branch *br; ++ ++ br = au_sbr(dentry->d_sb, bdst); ++ h_path.dentry = au_wh_lkup(h_parent, &dentry->d_name, br); ++ err = PTR_ERR(h_path.dentry); ++ if (IS_ERR(h_path.dentry)) ++ goto out; ++ ++ err = 0; ++ if (d_is_positive(h_path.dentry)) { ++ h_path.mnt = au_br_mnt(br); ++ err = au_wh_unlink_dentry(au_h_iptr(dir, bdst), &h_path, ++ dentry); ++ } ++ dput(h_path.dentry); ++ ++out: ++ return err; ++} ++ ++static int au_cpdown_dir(struct dentry *dentry, aufs_bindex_t bdst, ++ struct au_pin *pin, ++ struct dentry *h_parent, void *arg) ++{ ++ int err, rerr; ++ aufs_bindex_t bopq, btop; ++ struct path h_path; ++ struct dentry *parent; ++ struct inode *h_dir, *h_inode, *inode, *dir; ++ unsigned int *flags = arg; ++ ++ btop = au_dbtop(dentry); ++ /* dentry is di-locked */ ++ parent = dget_parent(dentry); ++ dir = d_inode(parent); ++ h_dir = d_inode(h_parent); ++ AuDebugOn(h_dir != au_h_iptr(dir, bdst)); ++ IMustLock(h_dir); ++ ++ err = au_lkup_neg(dentry, bdst, /*wh*/0); ++ if (unlikely(err < 0)) ++ goto out; ++ h_path.dentry = au_h_dptr(dentry, bdst); ++ h_path.mnt = au_sbr_mnt(dentry->d_sb, bdst); ++ err = vfsub_sio_mkdir(au_h_iptr(dir, bdst), &h_path, 0755); ++ if (unlikely(err)) ++ goto out_put; ++ au_fset_cpdown(*flags, MADE_DIR); ++ ++ bopq = au_dbdiropq(dentry); ++ au_fclr_cpdown(*flags, WHED); ++ au_fclr_cpdown(*flags, DIROPQ); ++ if (au_dbwh(dentry) == bdst) ++ au_fset_cpdown(*flags, WHED); ++ if (!au_ftest_cpdown(*flags, PARENT_OPQ) && bopq <= bdst) ++ au_fset_cpdown(*flags, PARENT_OPQ); ++ h_inode = d_inode(h_path.dentry); ++ inode_lock_nested(h_inode, AuLsc_I_CHILD); ++ if (au_ftest_cpdown(*flags, WHED)) { ++ err = au_cpdown_dir_opq(dentry, bdst, flags); ++ if (unlikely(err)) { ++ inode_unlock(h_inode); ++ goto out_dir; ++ } ++ } ++ ++ err = au_cpdown_attr(&h_path, au_h_dptr(dentry, btop)); ++ inode_unlock(h_inode); ++ if (unlikely(err)) ++ goto out_opq; ++ ++ if (au_ftest_cpdown(*flags, WHED)) { ++ err = au_cpdown_dir_wh(dentry, h_parent, dir, bdst); ++ if (unlikely(err)) ++ goto out_opq; ++ } ++ ++ inode = d_inode(dentry); ++ if (au_ibbot(inode) < bdst) ++ au_set_ibbot(inode, bdst); ++ au_set_h_iptr(inode, bdst, au_igrab(h_inode), ++ au_hi_flags(inode, /*isdir*/1)); ++ au_fhsm_wrote(dentry->d_sb, bdst, /*force*/0); ++ goto out; /* success */ ++ ++ /* revert */ ++out_opq: ++ if (au_ftest_cpdown(*flags, DIROPQ)) { ++ inode_lock_nested(h_inode, AuLsc_I_CHILD); ++ rerr = au_diropq_remove(dentry, bdst); ++ inode_unlock(h_inode); ++ if (unlikely(rerr)) { ++ AuIOErr("failed removing diropq for %pd b%d (%d)\n", ++ dentry, bdst, rerr); ++ err = -EIO; ++ goto out; ++ } ++ } ++out_dir: ++ if (au_ftest_cpdown(*flags, MADE_DIR)) { ++ rerr = vfsub_sio_rmdir(au_h_iptr(dir, bdst), &h_path); ++ if (unlikely(rerr)) { ++ AuIOErr("failed removing %pd b%d (%d)\n", ++ dentry, bdst, rerr); ++ err = -EIO; ++ } ++ } ++out_put: ++ au_set_h_dptr(dentry, bdst, NULL); ++ if (au_dbbot(dentry) == bdst) ++ au_update_dbbot(dentry); ++out: ++ dput(parent); ++ return err; ++} ++ ++int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst) ++{ ++ int err; ++ unsigned int flags; ++ ++ flags = 0; ++ err = au_cp_dirs(dentry, bdst, au_cpdown_dir, &flags); ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* policies for create */ ++ ++int au_wbr_nonopq(struct dentry *dentry, aufs_bindex_t bindex) ++{ ++ int err, i, j, ndentry; ++ aufs_bindex_t bopq; ++ struct au_dcsub_pages dpages; ++ struct au_dpage *dpage; ++ struct dentry **dentries, *parent, *d; ++ ++ err = au_dpages_init(&dpages, GFP_NOFS); ++ if (unlikely(err)) ++ goto out; ++ parent = dget_parent(dentry); ++ err = au_dcsub_pages_rev_aufs(&dpages, parent, /*do_include*/0); ++ if (unlikely(err)) ++ goto out_free; ++ ++ err = bindex; ++ for (i = 0; i < dpages.ndpage; i++) { ++ dpage = dpages.dpages + i; ++ dentries = dpage->dentries; ++ ndentry = dpage->ndentry; ++ for (j = 0; j < ndentry; j++) { ++ d = dentries[j]; ++ di_read_lock_parent2(d, !AuLock_IR); ++ bopq = au_dbdiropq(d); ++ di_read_unlock(d, !AuLock_IR); ++ if (bopq >= 0 && bopq < err) ++ err = bopq; ++ } ++ } ++ ++out_free: ++ dput(parent); ++ au_dpages_free(&dpages); ++out: ++ return err; ++} ++ ++static int au_wbr_bu(struct super_block *sb, aufs_bindex_t bindex) ++{ ++ for (; bindex >= 0; bindex--) ++ if (!au_br_rdonly(au_sbr(sb, bindex))) ++ return bindex; ++ return -EROFS; ++} ++ ++/* top down parent */ ++static int au_wbr_create_tdp(struct dentry *dentry, ++ unsigned int flags __maybe_unused) ++{ ++ int err; ++ aufs_bindex_t btop, bindex; ++ struct super_block *sb; ++ struct dentry *parent, *h_parent; ++ ++ sb = dentry->d_sb; ++ btop = au_dbtop(dentry); ++ err = btop; ++ if (!au_br_rdonly(au_sbr(sb, btop))) ++ goto out; ++ ++ err = -EROFS; ++ parent = dget_parent(dentry); ++ for (bindex = au_dbtop(parent); bindex < btop; bindex++) { ++ h_parent = au_h_dptr(parent, bindex); ++ if (!h_parent || d_is_negative(h_parent)) ++ continue; ++ ++ if (!au_br_rdonly(au_sbr(sb, bindex))) { ++ err = bindex; ++ break; ++ } ++ } ++ dput(parent); ++ ++ /* bottom up here */ ++ if (unlikely(err < 0)) { ++ err = au_wbr_bu(sb, btop - 1); ++ if (err >= 0) ++ err = au_wbr_nonopq(dentry, err); ++ } ++ ++out: ++ AuDbg("b%d\n", err); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* an exception for the policy other than tdp */ ++static int au_wbr_create_exp(struct dentry *dentry) ++{ ++ int err; ++ aufs_bindex_t bwh, bdiropq; ++ struct dentry *parent; ++ ++ err = -1; ++ bwh = au_dbwh(dentry); ++ parent = dget_parent(dentry); ++ bdiropq = au_dbdiropq(parent); ++ if (bwh >= 0) { ++ if (bdiropq >= 0) ++ err = min(bdiropq, bwh); ++ else ++ err = bwh; ++ AuDbg("%d\n", err); ++ } else if (bdiropq >= 0) { ++ err = bdiropq; ++ AuDbg("%d\n", err); ++ } ++ dput(parent); ++ ++ if (err >= 0) ++ err = au_wbr_nonopq(dentry, err); ++ ++ if (err >= 0 && au_br_rdonly(au_sbr(dentry->d_sb, err))) ++ err = -1; ++ ++ AuDbg("%d\n", err); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* round robin */ ++static int au_wbr_create_init_rr(struct super_block *sb) ++{ ++ int err; ++ ++ err = au_wbr_bu(sb, au_sbbot(sb)); ++ atomic_set(&au_sbi(sb)->si_wbr_rr_next, -err); /* less important */ ++ /* smp_mb(); */ ++ ++ AuDbg("b%d\n", err); ++ return err; ++} ++ ++static int au_wbr_create_rr(struct dentry *dentry, unsigned int flags) ++{ ++ int err, nbr; ++ unsigned int u; ++ aufs_bindex_t bindex, bbot; ++ struct super_block *sb; ++ atomic_t *next; ++ ++ err = au_wbr_create_exp(dentry); ++ if (err >= 0) ++ goto out; ++ ++ sb = dentry->d_sb; ++ next = &au_sbi(sb)->si_wbr_rr_next; ++ bbot = au_sbbot(sb); ++ nbr = bbot + 1; ++ for (bindex = 0; bindex <= bbot; bindex++) { ++ if (!au_ftest_wbr(flags, DIR)) { ++ err = atomic_dec_return(next) + 1; ++ /* modulo for 0 is meaningless */ ++ if (unlikely(!err)) ++ err = atomic_dec_return(next) + 1; ++ } else ++ err = atomic_read(next); ++ AuDbg("%d\n", err); ++ u = err; ++ err = u % nbr; ++ AuDbg("%d\n", err); ++ if (!au_br_rdonly(au_sbr(sb, err))) ++ break; ++ err = -EROFS; ++ } ++ ++ if (err >= 0) ++ err = au_wbr_nonopq(dentry, err); ++ ++out: ++ AuDbg("%d\n", err); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* most free space */ ++static void au_mfs(struct dentry *dentry, struct dentry *parent) ++{ ++ struct super_block *sb; ++ struct au_branch *br; ++ struct au_wbr_mfs *mfs; ++ struct dentry *h_parent; ++ aufs_bindex_t bindex, bbot; ++ int err; ++ unsigned long long b, bavail; ++ struct path h_path; ++ /* reduce the stack usage */ ++ struct kstatfs *st; ++ ++ st = kmalloc(sizeof(*st), GFP_NOFS); ++ if (unlikely(!st)) { ++ AuWarn1("failed updating mfs(%d), ignored\n", -ENOMEM); ++ return; ++ } ++ ++ bavail = 0; ++ sb = dentry->d_sb; ++ mfs = &au_sbi(sb)->si_wbr_mfs; ++ MtxMustLock(&mfs->mfs_lock); ++ mfs->mfs_bindex = -EROFS; ++ mfs->mfsrr_bytes = 0; ++ if (!parent) { ++ bindex = 0; ++ bbot = au_sbbot(sb); ++ } else { ++ bindex = au_dbtop(parent); ++ bbot = au_dbtaildir(parent); ++ } ++ ++ for (; bindex <= bbot; bindex++) { ++ if (parent) { ++ h_parent = au_h_dptr(parent, bindex); ++ if (!h_parent || d_is_negative(h_parent)) ++ continue; ++ } ++ br = au_sbr(sb, bindex); ++ if (au_br_rdonly(br)) ++ continue; ++ ++ /* sb->s_root for NFS is unreliable */ ++ h_path.mnt = au_br_mnt(br); ++ h_path.dentry = h_path.mnt->mnt_root; ++ err = vfs_statfs(&h_path, st); ++ if (unlikely(err)) { ++ AuWarn1("failed statfs, b%d, %d\n", bindex, err); ++ continue; ++ } ++ ++ /* when the available size is equal, select the lower one */ ++ BUILD_BUG_ON(sizeof(b) < sizeof(st->f_bavail) ++ || sizeof(b) < sizeof(st->f_bsize)); ++ b = st->f_bavail * st->f_bsize; ++ br->br_wbr->wbr_bytes = b; ++ if (b >= bavail) { ++ bavail = b; ++ mfs->mfs_bindex = bindex; ++ mfs->mfs_jiffy = jiffies; ++ } ++ } ++ ++ mfs->mfsrr_bytes = bavail; ++ AuDbg("b%d\n", mfs->mfs_bindex); ++ au_kfree_rcu(st); ++} ++ ++static int au_wbr_create_mfs(struct dentry *dentry, unsigned int flags) ++{ ++ int err; ++ struct dentry *parent; ++ struct super_block *sb; ++ struct au_wbr_mfs *mfs; ++ ++ err = au_wbr_create_exp(dentry); ++ if (err >= 0) ++ goto out; ++ ++ sb = dentry->d_sb; ++ parent = NULL; ++ if (au_ftest_wbr(flags, PARENT)) ++ parent = dget_parent(dentry); ++ mfs = &au_sbi(sb)->si_wbr_mfs; ++ mutex_lock(&mfs->mfs_lock); ++ if (time_after(jiffies, mfs->mfs_jiffy + mfs->mfs_expire) ++ || mfs->mfs_bindex < 0 ++ || au_br_rdonly(au_sbr(sb, mfs->mfs_bindex))) ++ au_mfs(dentry, parent); ++ mutex_unlock(&mfs->mfs_lock); ++ err = mfs->mfs_bindex; ++ dput(parent); ++ ++ if (err >= 0) ++ err = au_wbr_nonopq(dentry, err); ++ ++out: ++ AuDbg("b%d\n", err); ++ return err; ++} ++ ++static int au_wbr_create_init_mfs(struct super_block *sb) ++{ ++ struct au_wbr_mfs *mfs; ++ ++ mfs = &au_sbi(sb)->si_wbr_mfs; ++ mutex_init(&mfs->mfs_lock); ++ mfs->mfs_jiffy = 0; ++ mfs->mfs_bindex = -EROFS; ++ ++ return 0; ++} ++ ++static int au_wbr_create_fin_mfs(struct super_block *sb __maybe_unused) ++{ ++ mutex_destroy(&au_sbi(sb)->si_wbr_mfs.mfs_lock); ++ return 0; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* top down regardless parent, and then mfs */ ++static int au_wbr_create_tdmfs(struct dentry *dentry, ++ unsigned int flags __maybe_unused) ++{ ++ int err; ++ aufs_bindex_t bwh, btail, bindex, bfound, bmfs; ++ unsigned long long watermark; ++ struct super_block *sb; ++ struct au_wbr_mfs *mfs; ++ struct au_branch *br; ++ struct dentry *parent; ++ ++ sb = dentry->d_sb; ++ mfs = &au_sbi(sb)->si_wbr_mfs; ++ mutex_lock(&mfs->mfs_lock); ++ if (time_after(jiffies, mfs->mfs_jiffy + mfs->mfs_expire) ++ || mfs->mfs_bindex < 0) ++ au_mfs(dentry, /*parent*/NULL); ++ watermark = mfs->mfsrr_watermark; ++ bmfs = mfs->mfs_bindex; ++ mutex_unlock(&mfs->mfs_lock); ++ ++ /* another style of au_wbr_create_exp() */ ++ bwh = au_dbwh(dentry); ++ parent = dget_parent(dentry); ++ btail = au_dbtaildir(parent); ++ if (bwh >= 0 && bwh < btail) ++ btail = bwh; ++ ++ err = au_wbr_nonopq(dentry, btail); ++ if (unlikely(err < 0)) ++ goto out; ++ btail = err; ++ bfound = -1; ++ for (bindex = 0; bindex <= btail; bindex++) { ++ br = au_sbr(sb, bindex); ++ if (au_br_rdonly(br)) ++ continue; ++ if (br->br_wbr->wbr_bytes > watermark) { ++ bfound = bindex; ++ break; ++ } ++ } ++ err = bfound; ++ if (err < 0) ++ err = bmfs; ++ ++out: ++ dput(parent); ++ AuDbg("b%d\n", err); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* most free space and then round robin */ ++static int au_wbr_create_mfsrr(struct dentry *dentry, unsigned int flags) ++{ ++ int err; ++ struct au_wbr_mfs *mfs; ++ ++ err = au_wbr_create_mfs(dentry, flags); ++ if (err >= 0) { ++ mfs = &au_sbi(dentry->d_sb)->si_wbr_mfs; ++ mutex_lock(&mfs->mfs_lock); ++ if (mfs->mfsrr_bytes < mfs->mfsrr_watermark) ++ err = au_wbr_create_rr(dentry, flags); ++ mutex_unlock(&mfs->mfs_lock); ++ } ++ ++ AuDbg("b%d\n", err); ++ return err; ++} ++ ++static int au_wbr_create_init_mfsrr(struct super_block *sb) ++{ ++ int err; ++ ++ au_wbr_create_init_mfs(sb); /* ignore */ ++ err = au_wbr_create_init_rr(sb); ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* top down parent and most free space */ ++static int au_wbr_create_pmfs(struct dentry *dentry, unsigned int flags) ++{ ++ int err, e2; ++ unsigned long long b; ++ aufs_bindex_t bindex, btop, bbot; ++ struct super_block *sb; ++ struct dentry *parent, *h_parent; ++ struct au_branch *br; ++ ++ err = au_wbr_create_tdp(dentry, flags); ++ if (unlikely(err < 0)) ++ goto out; ++ parent = dget_parent(dentry); ++ btop = au_dbtop(parent); ++ bbot = au_dbtaildir(parent); ++ if (btop == bbot) ++ goto out_parent; /* success */ ++ ++ e2 = au_wbr_create_mfs(dentry, flags); ++ if (e2 < 0) ++ goto out_parent; /* success */ ++ ++ /* when the available size is equal, select upper one */ ++ sb = dentry->d_sb; ++ br = au_sbr(sb, err); ++ b = br->br_wbr->wbr_bytes; ++ AuDbg("b%d, %llu\n", err, b); ++ ++ for (bindex = btop; bindex <= bbot; bindex++) { ++ h_parent = au_h_dptr(parent, bindex); ++ if (!h_parent || d_is_negative(h_parent)) ++ continue; ++ ++ br = au_sbr(sb, bindex); ++ if (!au_br_rdonly(br) && br->br_wbr->wbr_bytes > b) { ++ b = br->br_wbr->wbr_bytes; ++ err = bindex; ++ AuDbg("b%d, %llu\n", err, b); ++ } ++ } ++ ++ if (err >= 0) ++ err = au_wbr_nonopq(dentry, err); ++ ++out_parent: ++ dput(parent); ++out: ++ AuDbg("b%d\n", err); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * - top down parent ++ * - most free space with parent ++ * - most free space round-robin regardless parent ++ */ ++static int au_wbr_create_pmfsrr(struct dentry *dentry, unsigned int flags) ++{ ++ int err; ++ unsigned long long watermark; ++ struct super_block *sb; ++ struct au_branch *br; ++ struct au_wbr_mfs *mfs; ++ ++ err = au_wbr_create_pmfs(dentry, flags | AuWbr_PARENT); ++ if (unlikely(err < 0)) ++ goto out; ++ ++ sb = dentry->d_sb; ++ br = au_sbr(sb, err); ++ mfs = &au_sbi(sb)->si_wbr_mfs; ++ mutex_lock(&mfs->mfs_lock); ++ watermark = mfs->mfsrr_watermark; ++ mutex_unlock(&mfs->mfs_lock); ++ if (br->br_wbr->wbr_bytes < watermark) ++ /* regardless the parent dir */ ++ err = au_wbr_create_mfsrr(dentry, flags); ++ ++out: ++ AuDbg("b%d\n", err); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* policies for copyup */ ++ ++/* top down parent */ ++static int au_wbr_copyup_tdp(struct dentry *dentry) ++{ ++ return au_wbr_create_tdp(dentry, /*flags, anything is ok*/0); ++} ++ ++/* bottom up parent */ ++static int au_wbr_copyup_bup(struct dentry *dentry) ++{ ++ int err; ++ aufs_bindex_t bindex, btop; ++ struct dentry *parent, *h_parent; ++ struct super_block *sb; ++ ++ err = -EROFS; ++ sb = dentry->d_sb; ++ parent = dget_parent(dentry); ++ btop = au_dbtop(parent); ++ for (bindex = au_dbtop(dentry); bindex >= btop; bindex--) { ++ h_parent = au_h_dptr(parent, bindex); ++ if (!h_parent || d_is_negative(h_parent)) ++ continue; ++ ++ if (!au_br_rdonly(au_sbr(sb, bindex))) { ++ err = bindex; ++ break; ++ } ++ } ++ dput(parent); ++ ++ /* bottom up here */ ++ if (unlikely(err < 0)) ++ err = au_wbr_bu(sb, btop - 1); ++ ++ AuDbg("b%d\n", err); ++ return err; ++} ++ ++/* bottom up */ ++int au_wbr_do_copyup_bu(struct dentry *dentry, aufs_bindex_t btop) ++{ ++ int err; ++ ++ err = au_wbr_bu(dentry->d_sb, btop); ++ AuDbg("b%d\n", err); ++ if (err > btop) ++ err = au_wbr_nonopq(dentry, err); ++ ++ AuDbg("b%d\n", err); ++ return err; ++} ++ ++static int au_wbr_copyup_bu(struct dentry *dentry) ++{ ++ int err; ++ aufs_bindex_t btop; ++ ++ btop = au_dbtop(dentry); ++ err = au_wbr_do_copyup_bu(dentry, btop); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++struct au_wbr_copyup_operations au_wbr_copyup_ops[] = { ++ [AuWbrCopyup_TDP] = { ++ .copyup = au_wbr_copyup_tdp ++ }, ++ [AuWbrCopyup_BUP] = { ++ .copyup = au_wbr_copyup_bup ++ }, ++ [AuWbrCopyup_BU] = { ++ .copyup = au_wbr_copyup_bu ++ } ++}; ++ ++struct au_wbr_create_operations au_wbr_create_ops[] = { ++ [AuWbrCreate_TDP] = { ++ .create = au_wbr_create_tdp ++ }, ++ [AuWbrCreate_RR] = { ++ .create = au_wbr_create_rr, ++ .init = au_wbr_create_init_rr ++ }, ++ [AuWbrCreate_MFS] = { ++ .create = au_wbr_create_mfs, ++ .init = au_wbr_create_init_mfs, ++ .fin = au_wbr_create_fin_mfs ++ }, ++ [AuWbrCreate_MFSV] = { ++ .create = au_wbr_create_mfs, ++ .init = au_wbr_create_init_mfs, ++ .fin = au_wbr_create_fin_mfs ++ }, ++ [AuWbrCreate_MFSRR] = { ++ .create = au_wbr_create_mfsrr, ++ .init = au_wbr_create_init_mfsrr, ++ .fin = au_wbr_create_fin_mfs ++ }, ++ [AuWbrCreate_MFSRRV] = { ++ .create = au_wbr_create_mfsrr, ++ .init = au_wbr_create_init_mfsrr, ++ .fin = au_wbr_create_fin_mfs ++ }, ++ [AuWbrCreate_TDMFS] = { ++ .create = au_wbr_create_tdmfs, ++ .init = au_wbr_create_init_mfs, ++ .fin = au_wbr_create_fin_mfs ++ }, ++ [AuWbrCreate_TDMFSV] = { ++ .create = au_wbr_create_tdmfs, ++ .init = au_wbr_create_init_mfs, ++ .fin = au_wbr_create_fin_mfs ++ }, ++ [AuWbrCreate_PMFS] = { ++ .create = au_wbr_create_pmfs, ++ .init = au_wbr_create_init_mfs, ++ .fin = au_wbr_create_fin_mfs ++ }, ++ [AuWbrCreate_PMFSV] = { ++ .create = au_wbr_create_pmfs, ++ .init = au_wbr_create_init_mfs, ++ .fin = au_wbr_create_fin_mfs ++ }, ++ [AuWbrCreate_PMFSRR] = { ++ .create = au_wbr_create_pmfsrr, ++ .init = au_wbr_create_init_mfsrr, ++ .fin = au_wbr_create_fin_mfs ++ }, ++ [AuWbrCreate_PMFSRRV] = { ++ .create = au_wbr_create_pmfsrr, ++ .init = au_wbr_create_init_mfsrr, ++ .fin = au_wbr_create_fin_mfs ++ } ++}; +diff -Nurp linux-5.4/fs/aufs/vdir.c linux-5.4-aufs/fs/aufs/vdir.c +--- linux-5.4/fs/aufs/vdir.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/vdir.c 2019-11-28 01:25:59.068925618 +0200 +@@ -0,0 +1,883 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * virtual or vertical directory ++ */ ++ ++#include ++#include "aufs.h" ++ ++static unsigned int calc_size(int nlen) ++{ ++ return ALIGN(sizeof(struct au_vdir_de) + nlen, sizeof(ino_t)); ++} ++ ++static int set_deblk_end(union au_vdir_deblk_p *p, ++ union au_vdir_deblk_p *deblk_end) ++{ ++ if (calc_size(0) <= deblk_end->deblk - p->deblk) { ++ p->de->de_str.len = 0; ++ /* smp_mb(); */ ++ return 0; ++ } ++ return -1; /* error */ ++} ++ ++/* returns true or false */ ++static int is_deblk_end(union au_vdir_deblk_p *p, ++ union au_vdir_deblk_p *deblk_end) ++{ ++ if (calc_size(0) <= deblk_end->deblk - p->deblk) ++ return !p->de->de_str.len; ++ return 1; ++} ++ ++static unsigned char *last_deblk(struct au_vdir *vdir) ++{ ++ return vdir->vd_deblk[vdir->vd_nblk - 1]; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* estimate the appropriate size for name hash table */ ++unsigned int au_rdhash_est(loff_t sz) ++{ ++ unsigned int n; ++ ++ n = UINT_MAX; ++ sz >>= 10; ++ if (sz < n) ++ n = sz; ++ if (sz < AUFS_RDHASH_DEF) ++ n = AUFS_RDHASH_DEF; ++ /* pr_info("n %u\n", n); */ ++ return n; ++} ++ ++/* ++ * the allocated memory has to be freed by ++ * au_nhash_wh_free() or au_nhash_de_free(). ++ */ ++int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp) ++{ ++ struct hlist_head *head; ++ unsigned int u; ++ size_t sz; ++ ++ sz = sizeof(*nhash->nh_head) * num_hash; ++ head = kmalloc(sz, gfp); ++ if (head) { ++ nhash->nh_num = num_hash; ++ nhash->nh_head = head; ++ for (u = 0; u < num_hash; u++) ++ INIT_HLIST_HEAD(head++); ++ return 0; /* success */ ++ } ++ ++ return -ENOMEM; ++} ++ ++static void nhash_count(struct hlist_head *head) ++{ ++#if 0 ++ unsigned long n; ++ struct hlist_node *pos; ++ ++ n = 0; ++ hlist_for_each(pos, head) ++ n++; ++ pr_info("%lu\n", n); ++#endif ++} ++ ++static void au_nhash_wh_do_free(struct hlist_head *head) ++{ ++ struct au_vdir_wh *pos; ++ struct hlist_node *node; ++ ++ hlist_for_each_entry_safe(pos, node, head, wh_hash) ++ au_kfree_rcu(pos); ++} ++ ++static void au_nhash_de_do_free(struct hlist_head *head) ++{ ++ struct au_vdir_dehstr *pos; ++ struct hlist_node *node; ++ ++ hlist_for_each_entry_safe(pos, node, head, hash) ++ au_cache_free_vdir_dehstr(pos); ++} ++ ++static void au_nhash_do_free(struct au_nhash *nhash, ++ void (*free)(struct hlist_head *head)) ++{ ++ unsigned int n; ++ struct hlist_head *head; ++ ++ n = nhash->nh_num; ++ if (!n) ++ return; ++ ++ head = nhash->nh_head; ++ while (n-- > 0) { ++ nhash_count(head); ++ free(head++); ++ } ++ au_kfree_try_rcu(nhash->nh_head); ++} ++ ++void au_nhash_wh_free(struct au_nhash *whlist) ++{ ++ au_nhash_do_free(whlist, au_nhash_wh_do_free); ++} ++ ++static void au_nhash_de_free(struct au_nhash *delist) ++{ ++ au_nhash_do_free(delist, au_nhash_de_do_free); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt, ++ int limit) ++{ ++ int num; ++ unsigned int u, n; ++ struct hlist_head *head; ++ struct au_vdir_wh *pos; ++ ++ num = 0; ++ n = whlist->nh_num; ++ head = whlist->nh_head; ++ for (u = 0; u < n; u++, head++) ++ hlist_for_each_entry(pos, head, wh_hash) ++ if (pos->wh_bindex == btgt && ++num > limit) ++ return 1; ++ return 0; ++} ++ ++static struct hlist_head *au_name_hash(struct au_nhash *nhash, ++ unsigned char *name, ++ unsigned int len) ++{ ++ unsigned int v; ++ /* const unsigned int magic_bit = 12; */ ++ ++ AuDebugOn(!nhash->nh_num || !nhash->nh_head); ++ ++ v = 0; ++ if (len > 8) ++ len = 8; ++ while (len--) ++ v += *name++; ++ /* v = hash_long(v, magic_bit); */ ++ v %= nhash->nh_num; ++ return nhash->nh_head + v; ++} ++ ++static int au_nhash_test_name(struct au_vdir_destr *str, const char *name, ++ int nlen) ++{ ++ return str->len == nlen && !memcmp(str->name, name, nlen); ++} ++ ++/* returns found or not */ ++int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen) ++{ ++ struct hlist_head *head; ++ struct au_vdir_wh *pos; ++ struct au_vdir_destr *str; ++ ++ head = au_name_hash(whlist, name, nlen); ++ hlist_for_each_entry(pos, head, wh_hash) { ++ str = &pos->wh_str; ++ AuDbg("%.*s\n", str->len, str->name); ++ if (au_nhash_test_name(str, name, nlen)) ++ return 1; ++ } ++ return 0; ++} ++ ++/* returns found(true) or not */ ++static int test_known(struct au_nhash *delist, char *name, int nlen) ++{ ++ struct hlist_head *head; ++ struct au_vdir_dehstr *pos; ++ struct au_vdir_destr *str; ++ ++ head = au_name_hash(delist, name, nlen); ++ hlist_for_each_entry(pos, head, hash) { ++ str = pos->str; ++ AuDbg("%.*s\n", str->len, str->name); ++ if (au_nhash_test_name(str, name, nlen)) ++ return 1; ++ } ++ return 0; ++} ++ ++static void au_shwh_init_wh(struct au_vdir_wh *wh, ino_t ino, ++ unsigned char d_type) ++{ ++#ifdef CONFIG_AUFS_SHWH ++ wh->wh_ino = ino; ++ wh->wh_type = d_type; ++#endif ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino, ++ unsigned int d_type, aufs_bindex_t bindex, ++ unsigned char shwh) ++{ ++ int err; ++ struct au_vdir_destr *str; ++ struct au_vdir_wh *wh; ++ ++ AuDbg("%.*s\n", nlen, name); ++ AuDebugOn(!whlist->nh_num || !whlist->nh_head); ++ ++ err = -ENOMEM; ++ wh = kmalloc(sizeof(*wh) + nlen, GFP_NOFS); ++ if (unlikely(!wh)) ++ goto out; ++ ++ err = 0; ++ wh->wh_bindex = bindex; ++ if (shwh) ++ au_shwh_init_wh(wh, ino, d_type); ++ str = &wh->wh_str; ++ str->len = nlen; ++ memcpy(str->name, name, nlen); ++ hlist_add_head(&wh->wh_hash, au_name_hash(whlist, name, nlen)); ++ /* smp_mb(); */ ++ ++out: ++ return err; ++} ++ ++static int append_deblk(struct au_vdir *vdir) ++{ ++ int err; ++ unsigned long ul; ++ const unsigned int deblk_sz = vdir->vd_deblk_sz; ++ union au_vdir_deblk_p p, deblk_end; ++ unsigned char **o; ++ ++ err = -ENOMEM; ++ o = au_krealloc(vdir->vd_deblk, sizeof(*o) * (vdir->vd_nblk + 1), ++ GFP_NOFS, /*may_shrink*/0); ++ if (unlikely(!o)) ++ goto out; ++ ++ vdir->vd_deblk = o; ++ p.deblk = kmalloc(deblk_sz, GFP_NOFS); ++ if (p.deblk) { ++ ul = vdir->vd_nblk++; ++ vdir->vd_deblk[ul] = p.deblk; ++ vdir->vd_last.ul = ul; ++ vdir->vd_last.p.deblk = p.deblk; ++ deblk_end.deblk = p.deblk + deblk_sz; ++ err = set_deblk_end(&p, &deblk_end); ++ } ++ ++out: ++ return err; ++} ++ ++static int append_de(struct au_vdir *vdir, char *name, int nlen, ino_t ino, ++ unsigned int d_type, struct au_nhash *delist) ++{ ++ int err; ++ unsigned int sz; ++ const unsigned int deblk_sz = vdir->vd_deblk_sz; ++ union au_vdir_deblk_p p, *room, deblk_end; ++ struct au_vdir_dehstr *dehstr; ++ ++ p.deblk = last_deblk(vdir); ++ deblk_end.deblk = p.deblk + deblk_sz; ++ room = &vdir->vd_last.p; ++ AuDebugOn(room->deblk < p.deblk || deblk_end.deblk <= room->deblk ++ || !is_deblk_end(room, &deblk_end)); ++ ++ sz = calc_size(nlen); ++ if (unlikely(sz > deblk_end.deblk - room->deblk)) { ++ err = append_deblk(vdir); ++ if (unlikely(err)) ++ goto out; ++ ++ p.deblk = last_deblk(vdir); ++ deblk_end.deblk = p.deblk + deblk_sz; ++ /* smp_mb(); */ ++ AuDebugOn(room->deblk != p.deblk); ++ } ++ ++ err = -ENOMEM; ++ dehstr = au_cache_alloc_vdir_dehstr(); ++ if (unlikely(!dehstr)) ++ goto out; ++ ++ dehstr->str = &room->de->de_str; ++ hlist_add_head(&dehstr->hash, au_name_hash(delist, name, nlen)); ++ room->de->de_ino = ino; ++ room->de->de_type = d_type; ++ room->de->de_str.len = nlen; ++ memcpy(room->de->de_str.name, name, nlen); ++ ++ err = 0; ++ room->deblk += sz; ++ if (unlikely(set_deblk_end(room, &deblk_end))) ++ err = append_deblk(vdir); ++ /* smp_mb(); */ ++ ++out: ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++void au_vdir_free(struct au_vdir *vdir) ++{ ++ unsigned char **deblk; ++ ++ deblk = vdir->vd_deblk; ++ while (vdir->vd_nblk--) ++ au_kfree_try_rcu(*deblk++); ++ au_kfree_try_rcu(vdir->vd_deblk); ++ au_cache_free_vdir(vdir); ++} ++ ++static struct au_vdir *alloc_vdir(struct file *file) ++{ ++ struct au_vdir *vdir; ++ struct super_block *sb; ++ int err; ++ ++ sb = file->f_path.dentry->d_sb; ++ SiMustAnyLock(sb); ++ ++ err = -ENOMEM; ++ vdir = au_cache_alloc_vdir(); ++ if (unlikely(!vdir)) ++ goto out; ++ ++ vdir->vd_deblk = kzalloc(sizeof(*vdir->vd_deblk), GFP_NOFS); ++ if (unlikely(!vdir->vd_deblk)) ++ goto out_free; ++ ++ vdir->vd_deblk_sz = au_sbi(sb)->si_rdblk; ++ if (!vdir->vd_deblk_sz) { ++ /* estimate the appropriate size for deblk */ ++ vdir->vd_deblk_sz = au_dir_size(file, /*dentry*/NULL); ++ /* pr_info("vd_deblk_sz %u\n", vdir->vd_deblk_sz); */ ++ } ++ vdir->vd_nblk = 0; ++ vdir->vd_version = 0; ++ vdir->vd_jiffy = 0; ++ err = append_deblk(vdir); ++ if (!err) ++ return vdir; /* success */ ++ ++ au_kfree_try_rcu(vdir->vd_deblk); ++ ++out_free: ++ au_cache_free_vdir(vdir); ++out: ++ vdir = ERR_PTR(err); ++ return vdir; ++} ++ ++static int reinit_vdir(struct au_vdir *vdir) ++{ ++ int err; ++ union au_vdir_deblk_p p, deblk_end; ++ ++ while (vdir->vd_nblk > 1) { ++ au_kfree_try_rcu(vdir->vd_deblk[vdir->vd_nblk - 1]); ++ /* vdir->vd_deblk[vdir->vd_nblk - 1] = NULL; */ ++ vdir->vd_nblk--; ++ } ++ p.deblk = vdir->vd_deblk[0]; ++ deblk_end.deblk = p.deblk + vdir->vd_deblk_sz; ++ err = set_deblk_end(&p, &deblk_end); ++ /* keep vd_dblk_sz */ ++ vdir->vd_last.ul = 0; ++ vdir->vd_last.p.deblk = vdir->vd_deblk[0]; ++ vdir->vd_version = 0; ++ vdir->vd_jiffy = 0; ++ /* smp_mb(); */ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++#define AuFillVdir_CALLED 1 ++#define AuFillVdir_WHABLE (1 << 1) ++#define AuFillVdir_SHWH (1 << 2) ++#define au_ftest_fillvdir(flags, name) ((flags) & AuFillVdir_##name) ++#define au_fset_fillvdir(flags, name) \ ++ do { (flags) |= AuFillVdir_##name; } while (0) ++#define au_fclr_fillvdir(flags, name) \ ++ do { (flags) &= ~AuFillVdir_##name; } while (0) ++ ++#ifndef CONFIG_AUFS_SHWH ++#undef AuFillVdir_SHWH ++#define AuFillVdir_SHWH 0 ++#endif ++ ++struct fillvdir_arg { ++ struct dir_context ctx; ++ struct file *file; ++ struct au_vdir *vdir; ++ struct au_nhash delist; ++ struct au_nhash whlist; ++ aufs_bindex_t bindex; ++ unsigned int flags; ++ int err; ++}; ++ ++static int fillvdir(struct dir_context *ctx, const char *__name, int nlen, ++ loff_t offset __maybe_unused, u64 h_ino, ++ unsigned int d_type) ++{ ++ struct fillvdir_arg *arg = container_of(ctx, struct fillvdir_arg, ctx); ++ char *name = (void *)__name; ++ struct super_block *sb; ++ ino_t ino; ++ const unsigned char shwh = !!au_ftest_fillvdir(arg->flags, SHWH); ++ ++ arg->err = 0; ++ sb = arg->file->f_path.dentry->d_sb; ++ au_fset_fillvdir(arg->flags, CALLED); ++ /* smp_mb(); */ ++ if (nlen <= AUFS_WH_PFX_LEN ++ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) { ++ if (test_known(&arg->delist, name, nlen) ++ || au_nhash_test_known_wh(&arg->whlist, name, nlen)) ++ goto out; /* already exists or whiteouted */ ++ ++ arg->err = au_ino(sb, arg->bindex, h_ino, d_type, &ino); ++ if (!arg->err) { ++ if (unlikely(nlen > AUFS_MAX_NAMELEN)) ++ d_type = DT_UNKNOWN; ++ arg->err = append_de(arg->vdir, name, nlen, ino, ++ d_type, &arg->delist); ++ } ++ } else if (au_ftest_fillvdir(arg->flags, WHABLE)) { ++ name += AUFS_WH_PFX_LEN; ++ nlen -= AUFS_WH_PFX_LEN; ++ if (au_nhash_test_known_wh(&arg->whlist, name, nlen)) ++ goto out; /* already whiteouted */ ++ ++ ino = 0; /* just to suppress a warning */ ++ if (shwh) ++ arg->err = au_wh_ino(sb, arg->bindex, h_ino, d_type, ++ &ino); ++ if (!arg->err) { ++ if (nlen <= AUFS_MAX_NAMELEN + AUFS_WH_PFX_LEN) ++ d_type = DT_UNKNOWN; ++ arg->err = au_nhash_append_wh ++ (&arg->whlist, name, nlen, ino, d_type, ++ arg->bindex, shwh); ++ } ++ } ++ ++out: ++ if (!arg->err) ++ arg->vdir->vd_jiffy = jiffies; ++ /* smp_mb(); */ ++ AuTraceErr(arg->err); ++ return arg->err; ++} ++ ++static int au_handle_shwh(struct super_block *sb, struct au_vdir *vdir, ++ struct au_nhash *whlist, struct au_nhash *delist) ++{ ++#ifdef CONFIG_AUFS_SHWH ++ int err; ++ unsigned int nh, u; ++ struct hlist_head *head; ++ struct au_vdir_wh *pos; ++ struct hlist_node *n; ++ char *p, *o; ++ struct au_vdir_destr *destr; ++ ++ AuDebugOn(!au_opt_test(au_mntflags(sb), SHWH)); ++ ++ err = -ENOMEM; ++ o = p = (void *)__get_free_page(GFP_NOFS); ++ if (unlikely(!p)) ++ goto out; ++ ++ err = 0; ++ nh = whlist->nh_num; ++ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN); ++ p += AUFS_WH_PFX_LEN; ++ for (u = 0; u < nh; u++) { ++ head = whlist->nh_head + u; ++ hlist_for_each_entry_safe(pos, n, head, wh_hash) { ++ destr = &pos->wh_str; ++ memcpy(p, destr->name, destr->len); ++ err = append_de(vdir, o, destr->len + AUFS_WH_PFX_LEN, ++ pos->wh_ino, pos->wh_type, delist); ++ if (unlikely(err)) ++ break; ++ } ++ } ++ ++ free_page((unsigned long)o); ++ ++out: ++ AuTraceErr(err); ++ return err; ++#else ++ return 0; ++#endif ++} ++ ++static int au_do_read_vdir(struct fillvdir_arg *arg) ++{ ++ int err; ++ unsigned int rdhash; ++ loff_t offset; ++ aufs_bindex_t bbot, bindex, btop; ++ unsigned char shwh; ++ struct file *hf, *file; ++ struct super_block *sb; ++ ++ file = arg->file; ++ sb = file->f_path.dentry->d_sb; ++ SiMustAnyLock(sb); ++ ++ rdhash = au_sbi(sb)->si_rdhash; ++ if (!rdhash) ++ rdhash = au_rdhash_est(au_dir_size(file, /*dentry*/NULL)); ++ err = au_nhash_alloc(&arg->delist, rdhash, GFP_NOFS); ++ if (unlikely(err)) ++ goto out; ++ err = au_nhash_alloc(&arg->whlist, rdhash, GFP_NOFS); ++ if (unlikely(err)) ++ goto out_delist; ++ ++ err = 0; ++ arg->flags = 0; ++ shwh = 0; ++ if (au_opt_test(au_mntflags(sb), SHWH)) { ++ shwh = 1; ++ au_fset_fillvdir(arg->flags, SHWH); ++ } ++ btop = au_fbtop(file); ++ bbot = au_fbbot_dir(file); ++ for (bindex = btop; !err && bindex <= bbot; bindex++) { ++ hf = au_hf_dir(file, bindex); ++ if (!hf) ++ continue; ++ ++ offset = vfsub_llseek(hf, 0, SEEK_SET); ++ err = offset; ++ if (unlikely(offset)) ++ break; ++ ++ arg->bindex = bindex; ++ au_fclr_fillvdir(arg->flags, WHABLE); ++ if (shwh ++ || (bindex != bbot ++ && au_br_whable(au_sbr_perm(sb, bindex)))) ++ au_fset_fillvdir(arg->flags, WHABLE); ++ do { ++ arg->err = 0; ++ au_fclr_fillvdir(arg->flags, CALLED); ++ /* smp_mb(); */ ++ err = vfsub_iterate_dir(hf, &arg->ctx); ++ if (err >= 0) ++ err = arg->err; ++ } while (!err && au_ftest_fillvdir(arg->flags, CALLED)); ++ ++ /* ++ * dir_relax() may be good for concurrency, but aufs should not ++ * use it since it will cause a lockdep problem. ++ */ ++ } ++ ++ if (!err && shwh) ++ err = au_handle_shwh(sb, arg->vdir, &arg->whlist, &arg->delist); ++ ++ au_nhash_wh_free(&arg->whlist); ++ ++out_delist: ++ au_nhash_de_free(&arg->delist); ++out: ++ return err; ++} ++ ++static int read_vdir(struct file *file, int may_read) ++{ ++ int err; ++ unsigned long expire; ++ unsigned char do_read; ++ struct fillvdir_arg arg = { ++ .ctx = { ++ .actor = fillvdir ++ } ++ }; ++ struct inode *inode; ++ struct au_vdir *vdir, *allocated; ++ ++ err = 0; ++ inode = file_inode(file); ++ IMustLock(inode); ++ IiMustWriteLock(inode); ++ SiMustAnyLock(inode->i_sb); ++ ++ allocated = NULL; ++ do_read = 0; ++ expire = au_sbi(inode->i_sb)->si_rdcache; ++ vdir = au_ivdir(inode); ++ if (!vdir) { ++ do_read = 1; ++ vdir = alloc_vdir(file); ++ err = PTR_ERR(vdir); ++ if (IS_ERR(vdir)) ++ goto out; ++ err = 0; ++ allocated = vdir; ++ } else if (may_read ++ && (!inode_eq_iversion(inode, vdir->vd_version) ++ || time_after(jiffies, vdir->vd_jiffy + expire))) { ++ do_read = 1; ++ err = reinit_vdir(vdir); ++ if (unlikely(err)) ++ goto out; ++ } ++ ++ if (!do_read) ++ return 0; /* success */ ++ ++ arg.file = file; ++ arg.vdir = vdir; ++ err = au_do_read_vdir(&arg); ++ if (!err) { ++ /* file->f_pos = 0; */ /* todo: ctx->pos? */ ++ vdir->vd_version = inode_query_iversion(inode); ++ vdir->vd_last.ul = 0; ++ vdir->vd_last.p.deblk = vdir->vd_deblk[0]; ++ if (allocated) ++ au_set_ivdir(inode, allocated); ++ } else if (allocated) ++ au_vdir_free(allocated); ++ ++out: ++ return err; ++} ++ ++static int copy_vdir(struct au_vdir *tgt, struct au_vdir *src) ++{ ++ int err, rerr; ++ unsigned long ul, n; ++ const unsigned int deblk_sz = src->vd_deblk_sz; ++ ++ AuDebugOn(tgt->vd_nblk != 1); ++ ++ err = -ENOMEM; ++ if (tgt->vd_nblk < src->vd_nblk) { ++ unsigned char **p; ++ ++ p = au_krealloc(tgt->vd_deblk, sizeof(*p) * src->vd_nblk, ++ GFP_NOFS, /*may_shrink*/0); ++ if (unlikely(!p)) ++ goto out; ++ tgt->vd_deblk = p; ++ } ++ ++ if (tgt->vd_deblk_sz != deblk_sz) { ++ unsigned char *p; ++ ++ tgt->vd_deblk_sz = deblk_sz; ++ p = au_krealloc(tgt->vd_deblk[0], deblk_sz, GFP_NOFS, ++ /*may_shrink*/1); ++ if (unlikely(!p)) ++ goto out; ++ tgt->vd_deblk[0] = p; ++ } ++ memcpy(tgt->vd_deblk[0], src->vd_deblk[0], deblk_sz); ++ tgt->vd_version = src->vd_version; ++ tgt->vd_jiffy = src->vd_jiffy; ++ ++ n = src->vd_nblk; ++ for (ul = 1; ul < n; ul++) { ++ tgt->vd_deblk[ul] = kmemdup(src->vd_deblk[ul], deblk_sz, ++ GFP_NOFS); ++ if (unlikely(!tgt->vd_deblk[ul])) ++ goto out; ++ tgt->vd_nblk++; ++ } ++ tgt->vd_nblk = n; ++ tgt->vd_last.ul = tgt->vd_last.ul; ++ tgt->vd_last.p.deblk = tgt->vd_deblk[tgt->vd_last.ul]; ++ tgt->vd_last.p.deblk += src->vd_last.p.deblk ++ - src->vd_deblk[src->vd_last.ul]; ++ /* smp_mb(); */ ++ return 0; /* success */ ++ ++out: ++ rerr = reinit_vdir(tgt); ++ BUG_ON(rerr); ++ return err; ++} ++ ++int au_vdir_init(struct file *file) ++{ ++ int err; ++ struct inode *inode; ++ struct au_vdir *vdir_cache, *allocated; ++ ++ /* test file->f_pos here instead of ctx->pos */ ++ err = read_vdir(file, !file->f_pos); ++ if (unlikely(err)) ++ goto out; ++ ++ allocated = NULL; ++ vdir_cache = au_fvdir_cache(file); ++ if (!vdir_cache) { ++ vdir_cache = alloc_vdir(file); ++ err = PTR_ERR(vdir_cache); ++ if (IS_ERR(vdir_cache)) ++ goto out; ++ allocated = vdir_cache; ++ } else if (!file->f_pos && vdir_cache->vd_version != file->f_version) { ++ /* test file->f_pos here instead of ctx->pos */ ++ err = reinit_vdir(vdir_cache); ++ if (unlikely(err)) ++ goto out; ++ } else ++ return 0; /* success */ ++ ++ inode = file_inode(file); ++ err = copy_vdir(vdir_cache, au_ivdir(inode)); ++ if (!err) { ++ file->f_version = inode_query_iversion(inode); ++ if (allocated) ++ au_set_fvdir_cache(file, allocated); ++ } else if (allocated) ++ au_vdir_free(allocated); ++ ++out: ++ return err; ++} ++ ++static loff_t calc_offset(struct au_vdir *vdir) ++{ ++ loff_t offset; ++ union au_vdir_deblk_p p; ++ ++ p.deblk = vdir->vd_deblk[vdir->vd_last.ul]; ++ offset = vdir->vd_last.p.deblk - p.deblk; ++ offset += vdir->vd_deblk_sz * vdir->vd_last.ul; ++ return offset; ++} ++ ++/* returns true or false */ ++static int seek_vdir(struct file *file, struct dir_context *ctx) ++{ ++ int valid; ++ unsigned int deblk_sz; ++ unsigned long ul, n; ++ loff_t offset; ++ union au_vdir_deblk_p p, deblk_end; ++ struct au_vdir *vdir_cache; ++ ++ valid = 1; ++ vdir_cache = au_fvdir_cache(file); ++ offset = calc_offset(vdir_cache); ++ AuDbg("offset %lld\n", offset); ++ if (ctx->pos == offset) ++ goto out; ++ ++ vdir_cache->vd_last.ul = 0; ++ vdir_cache->vd_last.p.deblk = vdir_cache->vd_deblk[0]; ++ if (!ctx->pos) ++ goto out; ++ ++ valid = 0; ++ deblk_sz = vdir_cache->vd_deblk_sz; ++ ul = div64_u64(ctx->pos, deblk_sz); ++ AuDbg("ul %lu\n", ul); ++ if (ul >= vdir_cache->vd_nblk) ++ goto out; ++ ++ n = vdir_cache->vd_nblk; ++ for (; ul < n; ul++) { ++ p.deblk = vdir_cache->vd_deblk[ul]; ++ deblk_end.deblk = p.deblk + deblk_sz; ++ offset = ul; ++ offset *= deblk_sz; ++ while (!is_deblk_end(&p, &deblk_end) && offset < ctx->pos) { ++ unsigned int l; ++ ++ l = calc_size(p.de->de_str.len); ++ offset += l; ++ p.deblk += l; ++ } ++ if (!is_deblk_end(&p, &deblk_end)) { ++ valid = 1; ++ vdir_cache->vd_last.ul = ul; ++ vdir_cache->vd_last.p = p; ++ break; ++ } ++ } ++ ++out: ++ /* smp_mb(); */ ++ if (!valid) ++ AuDbg("valid %d\n", !valid); ++ return valid; ++} ++ ++int au_vdir_fill_de(struct file *file, struct dir_context *ctx) ++{ ++ unsigned int l, deblk_sz; ++ union au_vdir_deblk_p deblk_end; ++ struct au_vdir *vdir_cache; ++ struct au_vdir_de *de; ++ ++ if (!seek_vdir(file, ctx)) ++ return 0; ++ ++ vdir_cache = au_fvdir_cache(file); ++ deblk_sz = vdir_cache->vd_deblk_sz; ++ while (1) { ++ deblk_end.deblk = vdir_cache->vd_deblk[vdir_cache->vd_last.ul]; ++ deblk_end.deblk += deblk_sz; ++ while (!is_deblk_end(&vdir_cache->vd_last.p, &deblk_end)) { ++ de = vdir_cache->vd_last.p.de; ++ AuDbg("%.*s, off%lld, i%lu, dt%d\n", ++ de->de_str.len, de->de_str.name, ctx->pos, ++ (unsigned long)de->de_ino, de->de_type); ++ if (unlikely(!dir_emit(ctx, de->de_str.name, ++ de->de_str.len, de->de_ino, ++ de->de_type))) { ++ /* todo: ignore the error caused by udba? */ ++ /* return err; */ ++ return 0; ++ } ++ ++ l = calc_size(de->de_str.len); ++ vdir_cache->vd_last.p.deblk += l; ++ ctx->pos += l; ++ } ++ if (vdir_cache->vd_last.ul < vdir_cache->vd_nblk - 1) { ++ vdir_cache->vd_last.ul++; ++ vdir_cache->vd_last.p.deblk ++ = vdir_cache->vd_deblk[vdir_cache->vd_last.ul]; ++ ctx->pos = deblk_sz * vdir_cache->vd_last.ul; ++ continue; ++ } ++ break; ++ } ++ ++ /* smp_mb(); */ ++ return 0; ++} +diff -Nurp linux-5.4/fs/aufs/vfsub.c linux-5.4-aufs/fs/aufs/vfsub.c +--- linux-5.4/fs/aufs/vfsub.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/vfsub.c 2019-11-28 01:25:59.068925618 +0200 +@@ -0,0 +1,889 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * sub-routines for VFS ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include "aufs.h" ++ ++#ifdef CONFIG_AUFS_BR_FUSE ++int vfsub_test_mntns(struct vfsmount *mnt, struct super_block *h_sb) ++{ ++ if (!au_test_fuse(h_sb) || !au_userns) ++ return 0; ++ ++ return is_current_mnt_ns(mnt) ? 0 : -EACCES; ++} ++#endif ++ ++int vfsub_sync_filesystem(struct super_block *h_sb, int wait) ++{ ++ int err; ++ ++ lockdep_off(); ++ down_read(&h_sb->s_umount); ++ err = __sync_filesystem(h_sb, wait); ++ up_read(&h_sb->s_umount); ++ lockdep_on(); ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++int vfsub_update_h_iattr(struct path *h_path, int *did) ++{ ++ int err; ++ struct kstat st; ++ struct super_block *h_sb; ++ ++ /* for remote fs, leave work for its getattr or d_revalidate */ ++ /* for bad i_attr fs, handle them in aufs_getattr() */ ++ /* still some fs may acquire i_mutex. we need to skip them */ ++ err = 0; ++ if (!did) ++ did = &err; ++ h_sb = h_path->dentry->d_sb; ++ *did = (!au_test_fs_remote(h_sb) && au_test_fs_refresh_iattr(h_sb)); ++ if (*did) ++ err = vfsub_getattr(h_path, &st); ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++struct file *vfsub_dentry_open(struct path *path, int flags) ++{ ++ struct file *file; ++ ++ file = dentry_open(path, flags /* | __FMODE_NONOTIFY */, ++ current_cred()); ++ if (!IS_ERR_OR_NULL(file) ++ && (file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) ++ i_readcount_inc(d_inode(path->dentry)); ++ ++ return file; ++} ++ ++struct file *vfsub_filp_open(const char *path, int oflags, int mode) ++{ ++ struct file *file; ++ ++ lockdep_off(); ++ file = filp_open(path, ++ oflags /* | __FMODE_NONOTIFY */, ++ mode); ++ lockdep_on(); ++ if (IS_ERR(file)) ++ goto out; ++ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/ ++ ++out: ++ return file; ++} ++ ++/* ++ * Ideally this function should call VFS:do_last() in order to keep all its ++ * checkings. But it is very hard for aufs to regenerate several VFS internal ++ * structure such as nameidata. This is a second (or third) best approach. ++ * cf. linux/fs/namei.c:do_last(), lookup_open() and atomic_open(). ++ */ ++int vfsub_atomic_open(struct inode *dir, struct dentry *dentry, ++ struct vfsub_aopen_args *args) ++{ ++ int err; ++ struct au_branch *br = args->br; ++ struct file *file = args->file; ++ /* copied from linux/fs/namei.c:atomic_open() */ ++ struct dentry *const DENTRY_NOT_SET = (void *)-1UL; ++ ++ IMustLock(dir); ++ AuDebugOn(!dir->i_op->atomic_open); ++ ++ err = au_br_test_oflag(args->open_flag, br); ++ if (unlikely(err)) ++ goto out; ++ ++ au_lcnt_inc(&br->br_nfiles); ++ file->f_path.dentry = DENTRY_NOT_SET; ++ file->f_path.mnt = au_br_mnt(br); ++ AuDbg("%ps\n", dir->i_op->atomic_open); ++ err = dir->i_op->atomic_open(dir, dentry, file, args->open_flag, ++ args->create_mode); ++ if (unlikely(err < 0)) { ++ au_lcnt_dec(&br->br_nfiles); ++ goto out; ++ } ++ ++ /* temporary workaround for nfsv4 branch */ ++ if (au_test_nfs(dir->i_sb)) ++ nfs_mark_for_revalidate(dir); ++ ++ if (file->f_mode & FMODE_CREATED) ++ fsnotify_create(dir, dentry); ++ if (!(file->f_mode & FMODE_OPENED)) { ++ au_lcnt_dec(&br->br_nfiles); ++ goto out; ++ } ++ ++ /* todo: call VFS:may_open() here */ ++ /* todo: ima_file_check() too? */ ++ if (!err && (args->open_flag & __FMODE_EXEC)) ++ err = deny_write_access(file); ++ if (!err) ++ fsnotify_open(file); ++ else ++ au_lcnt_dec(&br->br_nfiles); ++ /* note that the file is created and still opened */ ++ ++out: ++ return err; ++} ++ ++int vfsub_kern_path(const char *name, unsigned int flags, struct path *path) ++{ ++ int err; ++ ++ err = kern_path(name, flags, path); ++ if (!err && d_is_positive(path->dentry)) ++ vfsub_update_h_iattr(path, /*did*/NULL); /*ignore*/ ++ return err; ++} ++ ++struct dentry *vfsub_lookup_one_len_unlocked(const char *name, ++ struct dentry *parent, int len) ++{ ++ struct path path = { ++ .mnt = NULL ++ }; ++ ++ path.dentry = lookup_one_len_unlocked(name, parent, len); ++ if (IS_ERR(path.dentry)) ++ goto out; ++ if (d_is_positive(path.dentry)) ++ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/ ++ ++out: ++ AuTraceErrPtr(path.dentry); ++ return path.dentry; ++} ++ ++struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent, ++ int len) ++{ ++ struct path path = { ++ .mnt = NULL ++ }; ++ ++ /* VFS checks it too, but by WARN_ON_ONCE() */ ++ IMustLock(d_inode(parent)); ++ ++ path.dentry = lookup_one_len(name, parent, len); ++ if (IS_ERR(path.dentry)) ++ goto out; ++ if (d_is_positive(path.dentry)) ++ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/ ++ ++out: ++ AuTraceErrPtr(path.dentry); ++ return path.dentry; ++} ++ ++void vfsub_call_lkup_one(void *args) ++{ ++ struct vfsub_lkup_one_args *a = args; ++ *a->errp = vfsub_lkup_one(a->name, a->parent); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1, ++ struct dentry *d2, struct au_hinode *hdir2) ++{ ++ struct dentry *d; ++ ++ lockdep_off(); ++ d = lock_rename(d1, d2); ++ lockdep_on(); ++ au_hn_suspend(hdir1); ++ if (hdir1 != hdir2) ++ au_hn_suspend(hdir2); ++ ++ return d; ++} ++ ++void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1, ++ struct dentry *d2, struct au_hinode *hdir2) ++{ ++ au_hn_resume(hdir1); ++ if (hdir1 != hdir2) ++ au_hn_resume(hdir2); ++ lockdep_off(); ++ unlock_rename(d1, d2); ++ lockdep_on(); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++int vfsub_create(struct inode *dir, struct path *path, int mode, bool want_excl) ++{ ++ int err; ++ struct dentry *d; ++ ++ IMustLock(dir); ++ ++ d = path->dentry; ++ path->dentry = d->d_parent; ++ err = security_path_mknod(path, d, mode, 0); ++ path->dentry = d; ++ if (unlikely(err)) ++ goto out; ++ ++ lockdep_off(); ++ err = vfs_create(dir, path->dentry, mode, want_excl); ++ lockdep_on(); ++ if (!err) { ++ struct path tmp = *path; ++ int did; ++ ++ vfsub_update_h_iattr(&tmp, &did); ++ if (did) { ++ tmp.dentry = path->dentry->d_parent; ++ vfsub_update_h_iattr(&tmp, /*did*/NULL); ++ } ++ /*ignore*/ ++ } ++ ++out: ++ return err; ++} ++ ++int vfsub_symlink(struct inode *dir, struct path *path, const char *symname) ++{ ++ int err; ++ struct dentry *d; ++ ++ IMustLock(dir); ++ ++ d = path->dentry; ++ path->dentry = d->d_parent; ++ err = security_path_symlink(path, d, symname); ++ path->dentry = d; ++ if (unlikely(err)) ++ goto out; ++ ++ lockdep_off(); ++ err = vfs_symlink(dir, path->dentry, symname); ++ lockdep_on(); ++ if (!err) { ++ struct path tmp = *path; ++ int did; ++ ++ vfsub_update_h_iattr(&tmp, &did); ++ if (did) { ++ tmp.dentry = path->dentry->d_parent; ++ vfsub_update_h_iattr(&tmp, /*did*/NULL); ++ } ++ /*ignore*/ ++ } ++ ++out: ++ return err; ++} ++ ++int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev) ++{ ++ int err; ++ struct dentry *d; ++ ++ IMustLock(dir); ++ ++ d = path->dentry; ++ path->dentry = d->d_parent; ++ err = security_path_mknod(path, d, mode, new_encode_dev(dev)); ++ path->dentry = d; ++ if (unlikely(err)) ++ goto out; ++ ++ lockdep_off(); ++ err = vfs_mknod(dir, path->dentry, mode, dev); ++ lockdep_on(); ++ if (!err) { ++ struct path tmp = *path; ++ int did; ++ ++ vfsub_update_h_iattr(&tmp, &did); ++ if (did) { ++ tmp.dentry = path->dentry->d_parent; ++ vfsub_update_h_iattr(&tmp, /*did*/NULL); ++ } ++ /*ignore*/ ++ } ++ ++out: ++ return err; ++} ++ ++static int au_test_nlink(struct inode *inode) ++{ ++ const unsigned int link_max = UINT_MAX >> 1; /* rough margin */ ++ ++ if (!au_test_fs_no_limit_nlink(inode->i_sb) ++ || inode->i_nlink < link_max) ++ return 0; ++ return -EMLINK; ++} ++ ++int vfsub_link(struct dentry *src_dentry, struct inode *dir, struct path *path, ++ struct inode **delegated_inode) ++{ ++ int err; ++ struct dentry *d; ++ ++ IMustLock(dir); ++ ++ err = au_test_nlink(d_inode(src_dentry)); ++ if (unlikely(err)) ++ return err; ++ ++ /* we don't call may_linkat() */ ++ d = path->dentry; ++ path->dentry = d->d_parent; ++ err = security_path_link(src_dentry, path, d); ++ path->dentry = d; ++ if (unlikely(err)) ++ goto out; ++ ++ lockdep_off(); ++ err = vfs_link(src_dentry, dir, path->dentry, delegated_inode); ++ lockdep_on(); ++ if (!err) { ++ struct path tmp = *path; ++ int did; ++ ++ /* fuse has different memory inode for the same inumber */ ++ vfsub_update_h_iattr(&tmp, &did); ++ if (did) { ++ tmp.dentry = path->dentry->d_parent; ++ vfsub_update_h_iattr(&tmp, /*did*/NULL); ++ tmp.dentry = src_dentry; ++ vfsub_update_h_iattr(&tmp, /*did*/NULL); ++ } ++ /*ignore*/ ++ } ++ ++out: ++ return err; ++} ++ ++int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry, ++ struct inode *dir, struct path *path, ++ struct inode **delegated_inode, unsigned int flags) ++{ ++ int err; ++ struct path tmp = { ++ .mnt = path->mnt ++ }; ++ struct dentry *d; ++ ++ IMustLock(dir); ++ IMustLock(src_dir); ++ ++ d = path->dentry; ++ path->dentry = d->d_parent; ++ tmp.dentry = src_dentry->d_parent; ++ err = security_path_rename(&tmp, src_dentry, path, d, /*flags*/0); ++ path->dentry = d; ++ if (unlikely(err)) ++ goto out; ++ ++ lockdep_off(); ++ err = vfs_rename(src_dir, src_dentry, dir, path->dentry, ++ delegated_inode, flags); ++ lockdep_on(); ++ if (!err) { ++ int did; ++ ++ tmp.dentry = d->d_parent; ++ vfsub_update_h_iattr(&tmp, &did); ++ if (did) { ++ tmp.dentry = src_dentry; ++ vfsub_update_h_iattr(&tmp, /*did*/NULL); ++ tmp.dentry = src_dentry->d_parent; ++ vfsub_update_h_iattr(&tmp, /*did*/NULL); ++ } ++ /*ignore*/ ++ } ++ ++out: ++ return err; ++} ++ ++int vfsub_mkdir(struct inode *dir, struct path *path, int mode) ++{ ++ int err; ++ struct dentry *d; ++ ++ IMustLock(dir); ++ ++ d = path->dentry; ++ path->dentry = d->d_parent; ++ err = security_path_mkdir(path, d, mode); ++ path->dentry = d; ++ if (unlikely(err)) ++ goto out; ++ ++ lockdep_off(); ++ err = vfs_mkdir(dir, path->dentry, mode); ++ lockdep_on(); ++ if (!err) { ++ struct path tmp = *path; ++ int did; ++ ++ vfsub_update_h_iattr(&tmp, &did); ++ if (did) { ++ tmp.dentry = path->dentry->d_parent; ++ vfsub_update_h_iattr(&tmp, /*did*/NULL); ++ } ++ /*ignore*/ ++ } ++ ++out: ++ return err; ++} ++ ++int vfsub_rmdir(struct inode *dir, struct path *path) ++{ ++ int err; ++ struct dentry *d; ++ ++ IMustLock(dir); ++ ++ d = path->dentry; ++ path->dentry = d->d_parent; ++ err = security_path_rmdir(path, d); ++ path->dentry = d; ++ if (unlikely(err)) ++ goto out; ++ ++ lockdep_off(); ++ err = vfs_rmdir(dir, path->dentry); ++ lockdep_on(); ++ if (!err) { ++ struct path tmp = { ++ .dentry = path->dentry->d_parent, ++ .mnt = path->mnt ++ }; ++ ++ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/ ++ } ++ ++out: ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* todo: support mmap_sem? */ ++ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count, ++ loff_t *ppos) ++{ ++ ssize_t err; ++ ++ lockdep_off(); ++ err = vfs_read(file, ubuf, count, ppos); ++ lockdep_on(); ++ if (err >= 0) ++ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/ ++ return err; ++} ++ ++/* todo: kernel_read()? */ ++ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count, ++ loff_t *ppos) ++{ ++ ssize_t err; ++ mm_segment_t oldfs; ++ union { ++ void *k; ++ char __user *u; ++ } buf; ++ ++ buf.k = kbuf; ++ oldfs = get_fs(); ++ set_fs(KERNEL_DS); ++ err = vfsub_read_u(file, buf.u, count, ppos); ++ set_fs(oldfs); ++ return err; ++} ++ ++ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count, ++ loff_t *ppos) ++{ ++ ssize_t err; ++ ++ lockdep_off(); ++ err = vfs_write(file, ubuf, count, ppos); ++ lockdep_on(); ++ if (err >= 0) ++ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/ ++ return err; ++} ++ ++ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos) ++{ ++ ssize_t err; ++ mm_segment_t oldfs; ++ union { ++ void *k; ++ const char __user *u; ++ } buf; ++ ++ buf.k = kbuf; ++ oldfs = get_fs(); ++ set_fs(KERNEL_DS); ++ err = vfsub_write_u(file, buf.u, count, ppos); ++ set_fs(oldfs); ++ return err; ++} ++ ++int vfsub_flush(struct file *file, fl_owner_t id) ++{ ++ int err; ++ ++ err = 0; ++ if (file->f_op->flush) { ++ if (!au_test_nfs(file->f_path.dentry->d_sb)) ++ err = file->f_op->flush(file, id); ++ else { ++ lockdep_off(); ++ err = file->f_op->flush(file, id); ++ lockdep_on(); ++ } ++ if (!err) ++ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); ++ /*ignore*/ ++ } ++ return err; ++} ++ ++int vfsub_iterate_dir(struct file *file, struct dir_context *ctx) ++{ ++ int err; ++ ++ AuDbg("%pD, ctx{%ps, %llu}\n", file, ctx->actor, ctx->pos); ++ ++ lockdep_off(); ++ err = iterate_dir(file, ctx); ++ lockdep_on(); ++ if (err >= 0) ++ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/ ++ ++ return err; ++} ++ ++long vfsub_splice_to(struct file *in, loff_t *ppos, ++ struct pipe_inode_info *pipe, size_t len, ++ unsigned int flags) ++{ ++ long err; ++ ++ lockdep_off(); ++ err = do_splice_to(in, ppos, pipe, len, flags); ++ lockdep_on(); ++ file_accessed(in); ++ if (err >= 0) ++ vfsub_update_h_iattr(&in->f_path, /*did*/NULL); /*ignore*/ ++ return err; ++} ++ ++long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out, ++ loff_t *ppos, size_t len, unsigned int flags) ++{ ++ long err; ++ ++ lockdep_off(); ++ err = do_splice_from(pipe, out, ppos, len, flags); ++ lockdep_on(); ++ if (err >= 0) ++ vfsub_update_h_iattr(&out->f_path, /*did*/NULL); /*ignore*/ ++ return err; ++} ++ ++int vfsub_fsync(struct file *file, struct path *path, int datasync) ++{ ++ int err; ++ ++ /* file can be NULL */ ++ lockdep_off(); ++ err = vfs_fsync(file, datasync); ++ lockdep_on(); ++ if (!err) { ++ if (!path) { ++ AuDebugOn(!file); ++ path = &file->f_path; ++ } ++ vfsub_update_h_iattr(path, /*did*/NULL); /*ignore*/ ++ } ++ return err; ++} ++ ++/* cf. open.c:do_sys_truncate() and do_sys_ftruncate() */ ++int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr, ++ struct file *h_file) ++{ ++ int err; ++ struct inode *h_inode; ++ struct super_block *h_sb; ++ ++ if (!h_file) { ++ err = vfsub_truncate(h_path, length); ++ goto out; ++ } ++ ++ h_inode = d_inode(h_path->dentry); ++ h_sb = h_inode->i_sb; ++ lockdep_off(); ++ sb_start_write(h_sb); ++ lockdep_on(); ++ err = locks_verify_truncate(h_inode, h_file, length); ++ if (!err) ++ err = security_path_truncate(h_path); ++ if (!err) { ++ lockdep_off(); ++ err = do_truncate(h_path->dentry, length, attr, h_file); ++ lockdep_on(); ++ } ++ lockdep_off(); ++ sb_end_write(h_sb); ++ lockdep_on(); ++ ++out: ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++struct au_vfsub_mkdir_args { ++ int *errp; ++ struct inode *dir; ++ struct path *path; ++ int mode; ++}; ++ ++static void au_call_vfsub_mkdir(void *args) ++{ ++ struct au_vfsub_mkdir_args *a = args; ++ *a->errp = vfsub_mkdir(a->dir, a->path, a->mode); ++} ++ ++int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode) ++{ ++ int err, do_sio, wkq_err; ++ ++ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE); ++ if (!do_sio) { ++ lockdep_off(); ++ err = vfsub_mkdir(dir, path, mode); ++ lockdep_on(); ++ } else { ++ struct au_vfsub_mkdir_args args = { ++ .errp = &err, ++ .dir = dir, ++ .path = path, ++ .mode = mode ++ }; ++ wkq_err = au_wkq_wait(au_call_vfsub_mkdir, &args); ++ if (unlikely(wkq_err)) ++ err = wkq_err; ++ } ++ ++ return err; ++} ++ ++struct au_vfsub_rmdir_args { ++ int *errp; ++ struct inode *dir; ++ struct path *path; ++}; ++ ++static void au_call_vfsub_rmdir(void *args) ++{ ++ struct au_vfsub_rmdir_args *a = args; ++ *a->errp = vfsub_rmdir(a->dir, a->path); ++} ++ ++int vfsub_sio_rmdir(struct inode *dir, struct path *path) ++{ ++ int err, do_sio, wkq_err; ++ ++ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE); ++ if (!do_sio) { ++ lockdep_off(); ++ err = vfsub_rmdir(dir, path); ++ lockdep_on(); ++ } else { ++ struct au_vfsub_rmdir_args args = { ++ .errp = &err, ++ .dir = dir, ++ .path = path ++ }; ++ wkq_err = au_wkq_wait(au_call_vfsub_rmdir, &args); ++ if (unlikely(wkq_err)) ++ err = wkq_err; ++ } ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++struct notify_change_args { ++ int *errp; ++ struct path *path; ++ struct iattr *ia; ++ struct inode **delegated_inode; ++}; ++ ++static void call_notify_change(void *args) ++{ ++ struct notify_change_args *a = args; ++ struct inode *h_inode; ++ ++ h_inode = d_inode(a->path->dentry); ++ IMustLock(h_inode); ++ ++ *a->errp = -EPERM; ++ if (!IS_IMMUTABLE(h_inode) && !IS_APPEND(h_inode)) { ++ lockdep_off(); ++ *a->errp = notify_change(a->path->dentry, a->ia, ++ a->delegated_inode); ++ lockdep_on(); ++ if (!*a->errp) ++ vfsub_update_h_iattr(a->path, /*did*/NULL); /*ignore*/ ++ } ++ AuTraceErr(*a->errp); ++} ++ ++int vfsub_notify_change(struct path *path, struct iattr *ia, ++ struct inode **delegated_inode) ++{ ++ int err; ++ struct notify_change_args args = { ++ .errp = &err, ++ .path = path, ++ .ia = ia, ++ .delegated_inode = delegated_inode ++ }; ++ ++ call_notify_change(&args); ++ ++ return err; ++} ++ ++int vfsub_sio_notify_change(struct path *path, struct iattr *ia, ++ struct inode **delegated_inode) ++{ ++ int err, wkq_err; ++ struct notify_change_args args = { ++ .errp = &err, ++ .path = path, ++ .ia = ia, ++ .delegated_inode = delegated_inode ++ }; ++ ++ wkq_err = au_wkq_wait(call_notify_change, &args); ++ if (unlikely(wkq_err)) ++ err = wkq_err; ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++struct unlink_args { ++ int *errp; ++ struct inode *dir; ++ struct path *path; ++ struct inode **delegated_inode; ++}; ++ ++static void call_unlink(void *args) ++{ ++ struct unlink_args *a = args; ++ struct dentry *d = a->path->dentry; ++ struct inode *h_inode; ++ const int stop_sillyrename = (au_test_nfs(d->d_sb) ++ && au_dcount(d) == 1); ++ ++ IMustLock(a->dir); ++ ++ a->path->dentry = d->d_parent; ++ *a->errp = security_path_unlink(a->path, d); ++ a->path->dentry = d; ++ if (unlikely(*a->errp)) ++ return; ++ ++ if (!stop_sillyrename) ++ dget(d); ++ h_inode = NULL; ++ if (d_is_positive(d)) { ++ h_inode = d_inode(d); ++ ihold(h_inode); ++ } ++ ++ lockdep_off(); ++ *a->errp = vfs_unlink(a->dir, d, a->delegated_inode); ++ lockdep_on(); ++ if (!*a->errp) { ++ struct path tmp = { ++ .dentry = d->d_parent, ++ .mnt = a->path->mnt ++ }; ++ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/ ++ } ++ ++ if (!stop_sillyrename) ++ dput(d); ++ if (h_inode) ++ iput(h_inode); ++ ++ AuTraceErr(*a->errp); ++} ++ ++/* ++ * @dir: must be locked. ++ * @dentry: target dentry. ++ */ ++int vfsub_unlink(struct inode *dir, struct path *path, ++ struct inode **delegated_inode, int force) ++{ ++ int err; ++ struct unlink_args args = { ++ .errp = &err, ++ .dir = dir, ++ .path = path, ++ .delegated_inode = delegated_inode ++ }; ++ ++ if (!force) ++ call_unlink(&args); ++ else { ++ int wkq_err; ++ ++ wkq_err = au_wkq_wait(call_unlink, &args); ++ if (unlikely(wkq_err)) ++ err = wkq_err; ++ } ++ ++ return err; ++} +diff -Nurp linux-5.4/fs/aufs/vfsub.h linux-5.4-aufs/fs/aufs/vfsub.h +--- linux-5.4/fs/aufs/vfsub.h 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/vfsub.h 2019-11-28 01:25:59.068925618 +0200 +@@ -0,0 +1,341 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * sub-routines for VFS ++ */ ++ ++#ifndef __AUFS_VFSUB_H__ ++#define __AUFS_VFSUB_H__ ++ ++#ifdef __KERNEL__ ++ ++#include ++#include ++#include ++#include ++#include "debug.h" ++ ++/* copied from linux/fs/internal.h */ ++/* todo: BAD approach!! */ ++extern void __mnt_drop_write(struct vfsmount *); ++extern struct file *alloc_empty_file(int, const struct cred *); ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* lock subclass for lower inode */ ++/* default MAX_LOCKDEP_SUBCLASSES(8) is not enough */ ++/* reduce? gave up. */ ++enum { ++ AuLsc_I_Begin = I_MUTEX_PARENT2, /* 5 */ ++ AuLsc_I_PARENT, /* lower inode, parent first */ ++ AuLsc_I_PARENT2, /* copyup dirs */ ++ AuLsc_I_PARENT3, /* copyup wh */ ++ AuLsc_I_CHILD, ++ AuLsc_I_CHILD2, ++ AuLsc_I_End ++}; ++ ++/* to debug easier, do not make them inlined functions */ ++#define MtxMustLock(mtx) AuDebugOn(!mutex_is_locked(mtx)) ++#define IMustLock(i) AuDebugOn(!inode_is_locked(i)) ++ ++/* ---------------------------------------------------------------------- */ ++ ++static inline void vfsub_drop_nlink(struct inode *inode) ++{ ++ AuDebugOn(!inode->i_nlink); ++ drop_nlink(inode); ++} ++ ++static inline void vfsub_dead_dir(struct inode *inode) ++{ ++ AuDebugOn(!S_ISDIR(inode->i_mode)); ++ inode->i_flags |= S_DEAD; ++ clear_nlink(inode); ++} ++ ++static inline int vfsub_native_ro(struct inode *inode) ++{ ++ return sb_rdonly(inode->i_sb) ++ || IS_RDONLY(inode) ++ /* || IS_APPEND(inode) */ ++ || IS_IMMUTABLE(inode); ++} ++ ++#ifdef CONFIG_AUFS_BR_FUSE ++int vfsub_test_mntns(struct vfsmount *mnt, struct super_block *h_sb); ++#else ++AuStubInt0(vfsub_test_mntns, struct vfsmount *mnt, struct super_block *h_sb); ++#endif ++ ++int vfsub_sync_filesystem(struct super_block *h_sb, int wait); ++ ++/* ---------------------------------------------------------------------- */ ++ ++int vfsub_update_h_iattr(struct path *h_path, int *did); ++struct file *vfsub_dentry_open(struct path *path, int flags); ++struct file *vfsub_filp_open(const char *path, int oflags, int mode); ++struct au_branch; ++struct vfsub_aopen_args { ++ struct file *file; ++ unsigned int open_flag; ++ umode_t create_mode; ++ struct au_branch *br; ++}; ++int vfsub_atomic_open(struct inode *dir, struct dentry *dentry, ++ struct vfsub_aopen_args *args); ++int vfsub_kern_path(const char *name, unsigned int flags, struct path *path); ++ ++struct dentry *vfsub_lookup_one_len_unlocked(const char *name, ++ struct dentry *parent, int len); ++struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent, ++ int len); ++ ++struct vfsub_lkup_one_args { ++ struct dentry **errp; ++ struct qstr *name; ++ struct dentry *parent; ++}; ++ ++static inline struct dentry *vfsub_lkup_one(struct qstr *name, ++ struct dentry *parent) ++{ ++ return vfsub_lookup_one_len(name->name, parent, name->len); ++} ++ ++void vfsub_call_lkup_one(void *args); ++ ++/* ---------------------------------------------------------------------- */ ++ ++static inline int vfsub_mnt_want_write(struct vfsmount *mnt) ++{ ++ int err; ++ ++ lockdep_off(); ++ err = mnt_want_write(mnt); ++ lockdep_on(); ++ return err; ++} ++ ++static inline void vfsub_mnt_drop_write(struct vfsmount *mnt) ++{ ++ lockdep_off(); ++ mnt_drop_write(mnt); ++ lockdep_on(); ++} ++ ++#if 0 /* reserved */ ++static inline void vfsub_mnt_drop_write_file(struct file *file) ++{ ++ lockdep_off(); ++ mnt_drop_write_file(file); ++ lockdep_on(); ++} ++#endif ++ ++/* ---------------------------------------------------------------------- */ ++ ++struct au_hinode; ++struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1, ++ struct dentry *d2, struct au_hinode *hdir2); ++void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1, ++ struct dentry *d2, struct au_hinode *hdir2); ++ ++int vfsub_create(struct inode *dir, struct path *path, int mode, ++ bool want_excl); ++int vfsub_symlink(struct inode *dir, struct path *path, ++ const char *symname); ++int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev); ++int vfsub_link(struct dentry *src_dentry, struct inode *dir, ++ struct path *path, struct inode **delegated_inode); ++int vfsub_rename(struct inode *src_hdir, struct dentry *src_dentry, ++ struct inode *hdir, struct path *path, ++ struct inode **delegated_inode, unsigned int flags); ++int vfsub_mkdir(struct inode *dir, struct path *path, int mode); ++int vfsub_rmdir(struct inode *dir, struct path *path); ++ ++/* ---------------------------------------------------------------------- */ ++ ++ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count, ++ loff_t *ppos); ++ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count, ++ loff_t *ppos); ++ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count, ++ loff_t *ppos); ++ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, ++ loff_t *ppos); ++int vfsub_flush(struct file *file, fl_owner_t id); ++int vfsub_iterate_dir(struct file *file, struct dir_context *ctx); ++ ++static inline loff_t vfsub_f_size_read(struct file *file) ++{ ++ return i_size_read(file_inode(file)); ++} ++ ++static inline unsigned int vfsub_file_flags(struct file *file) ++{ ++ unsigned int flags; ++ ++ spin_lock(&file->f_lock); ++ flags = file->f_flags; ++ spin_unlock(&file->f_lock); ++ ++ return flags; ++} ++ ++static inline int vfsub_file_execed(struct file *file) ++{ ++ /* todo: direct access f_flags */ ++ return !!(vfsub_file_flags(file) & __FMODE_EXEC); ++} ++ ++#if 0 /* reserved */ ++static inline void vfsub_file_accessed(struct file *h_file) ++{ ++ file_accessed(h_file); ++ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL); /*ignore*/ ++} ++#endif ++ ++#if 0 /* reserved */ ++static inline void vfsub_touch_atime(struct vfsmount *h_mnt, ++ struct dentry *h_dentry) ++{ ++ struct path h_path = { ++ .dentry = h_dentry, ++ .mnt = h_mnt ++ }; ++ touch_atime(&h_path); ++ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/ ++} ++#endif ++ ++static inline int vfsub_update_time(struct inode *h_inode, ++ struct timespec64 *ts, int flags) ++{ ++ return update_time(h_inode, ts, flags); ++ /* no vfsub_update_h_iattr() since we don't have struct path */ ++} ++ ++#ifdef CONFIG_FS_POSIX_ACL ++static inline int vfsub_acl_chmod(struct inode *h_inode, umode_t h_mode) ++{ ++ int err; ++ ++ err = posix_acl_chmod(h_inode, h_mode); ++ if (err == -EOPNOTSUPP) ++ err = 0; ++ return err; ++} ++#else ++AuStubInt0(vfsub_acl_chmod, struct inode *h_inode, umode_t h_mode); ++#endif ++ ++long vfsub_splice_to(struct file *in, loff_t *ppos, ++ struct pipe_inode_info *pipe, size_t len, ++ unsigned int flags); ++long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out, ++ loff_t *ppos, size_t len, unsigned int flags); ++ ++static inline long vfsub_truncate(struct path *path, loff_t length) ++{ ++ long err; ++ ++ lockdep_off(); ++ err = vfs_truncate(path, length); ++ lockdep_on(); ++ return err; ++} ++ ++int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr, ++ struct file *h_file); ++int vfsub_fsync(struct file *file, struct path *path, int datasync); ++ ++/* ++ * re-use branch fs's ioctl(FICLONE) while aufs itself doesn't support such ++ * ioctl. ++ */ ++static inline loff_t vfsub_clone_file_range(struct file *src, struct file *dst, ++ loff_t len) ++{ ++ loff_t err; ++ ++ lockdep_off(); ++ err = vfs_clone_file_range(src, 0, dst, 0, len, /*remap_flags*/0); ++ lockdep_on(); ++ ++ return err; ++} ++ ++/* copy_file_range(2) is a systemcall */ ++static inline ssize_t vfsub_copy_file_range(struct file *src, loff_t src_pos, ++ struct file *dst, loff_t dst_pos, ++ size_t len, unsigned int flags) ++{ ++ ssize_t ssz; ++ ++ lockdep_off(); ++ ssz = vfs_copy_file_range(src, src_pos, dst, dst_pos, len, flags); ++ lockdep_on(); ++ ++ return ssz; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static inline loff_t vfsub_llseek(struct file *file, loff_t offset, int origin) ++{ ++ loff_t err; ++ ++ lockdep_off(); ++ err = vfs_llseek(file, offset, origin); ++ lockdep_on(); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode); ++int vfsub_sio_rmdir(struct inode *dir, struct path *path); ++int vfsub_sio_notify_change(struct path *path, struct iattr *ia, ++ struct inode **delegated_inode); ++int vfsub_notify_change(struct path *path, struct iattr *ia, ++ struct inode **delegated_inode); ++int vfsub_unlink(struct inode *dir, struct path *path, ++ struct inode **delegated_inode, int force); ++ ++static inline int vfsub_getattr(const struct path *path, struct kstat *st) ++{ ++ return vfs_getattr(path, st, STATX_BASIC_STATS, AT_STATX_SYNC_AS_STAT); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static inline int vfsub_setxattr(struct dentry *dentry, const char *name, ++ const void *value, size_t size, int flags) ++{ ++ int err; ++ ++ lockdep_off(); ++ err = vfs_setxattr(dentry, name, value, size, flags); ++ lockdep_on(); ++ ++ return err; ++} ++ ++static inline int vfsub_removexattr(struct dentry *dentry, const char *name) ++{ ++ int err; ++ ++ lockdep_off(); ++ err = vfs_removexattr(dentry, name); ++ lockdep_on(); ++ ++ return err; ++} ++ ++#endif /* __KERNEL__ */ ++#endif /* __AUFS_VFSUB_H__ */ +diff -Nurp linux-5.4/fs/aufs/whout.c linux-5.4-aufs/fs/aufs/whout.c +--- linux-5.4/fs/aufs/whout.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/whout.c 2019-11-28 01:25:59.069925618 +0200 +@@ -0,0 +1,1049 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * whiteout for logical deletion and opaque directory ++ */ ++ ++#include "aufs.h" ++ ++#define WH_MASK 0444 ++ ++/* ++ * If a directory contains this file, then it is opaque. We start with the ++ * .wh. flag so that it is blocked by lookup. ++ */ ++static struct qstr diropq_name = QSTR_INIT(AUFS_WH_DIROPQ, ++ sizeof(AUFS_WH_DIROPQ) - 1); ++ ++/* ++ * generate whiteout name, which is NOT terminated by NULL. ++ * @name: original d_name.name ++ * @len: original d_name.len ++ * @wh: whiteout qstr ++ * returns zero when succeeds, otherwise error. ++ * succeeded value as wh->name should be freed by kfree(). ++ */ ++int au_wh_name_alloc(struct qstr *wh, const struct qstr *name) ++{ ++ char *p; ++ ++ if (unlikely(name->len > PATH_MAX - AUFS_WH_PFX_LEN)) ++ return -ENAMETOOLONG; ++ ++ wh->len = name->len + AUFS_WH_PFX_LEN; ++ p = kmalloc(wh->len, GFP_NOFS); ++ wh->name = p; ++ if (p) { ++ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN); ++ memcpy(p + AUFS_WH_PFX_LEN, name->name, name->len); ++ /* smp_mb(); */ ++ return 0; ++ } ++ return -ENOMEM; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * test if the @wh_name exists under @h_parent. ++ * @try_sio specifies the necessary of super-io. ++ */ ++int au_wh_test(struct dentry *h_parent, struct qstr *wh_name, int try_sio) ++{ ++ int err; ++ struct dentry *wh_dentry; ++ ++ if (!try_sio) ++ wh_dentry = vfsub_lkup_one(wh_name, h_parent); ++ else ++ wh_dentry = au_sio_lkup_one(wh_name, h_parent); ++ err = PTR_ERR(wh_dentry); ++ if (IS_ERR(wh_dentry)) { ++ if (err == -ENAMETOOLONG) ++ err = 0; ++ goto out; ++ } ++ ++ err = 0; ++ if (d_is_negative(wh_dentry)) ++ goto out_wh; /* success */ ++ ++ err = 1; ++ if (d_is_reg(wh_dentry)) ++ goto out_wh; /* success */ ++ ++ err = -EIO; ++ AuIOErr("%pd Invalid whiteout entry type 0%o.\n", ++ wh_dentry, d_inode(wh_dentry)->i_mode); ++ ++out_wh: ++ dput(wh_dentry); ++out: ++ return err; ++} ++ ++/* ++ * test if the @h_dentry sets opaque or not. ++ */ ++int au_diropq_test(struct dentry *h_dentry) ++{ ++ int err; ++ struct inode *h_dir; ++ ++ h_dir = d_inode(h_dentry); ++ err = au_wh_test(h_dentry, &diropq_name, ++ au_test_h_perm_sio(h_dir, MAY_EXEC)); ++ return err; ++} ++ ++/* ++ * returns a negative dentry whose name is unique and temporary. ++ */ ++struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br, ++ struct qstr *prefix) ++{ ++ struct dentry *dentry; ++ int i; ++ char defname[NAME_MAX - AUFS_MAX_NAMELEN + DNAME_INLINE_LEN + 1], ++ *name, *p; ++ /* strict atomic_t is unnecessary here */ ++ static unsigned short cnt; ++ struct qstr qs; ++ ++ BUILD_BUG_ON(sizeof(cnt) * 2 > AUFS_WH_TMP_LEN); ++ ++ name = defname; ++ qs.len = sizeof(defname) - DNAME_INLINE_LEN + prefix->len - 1; ++ if (unlikely(prefix->len > DNAME_INLINE_LEN)) { ++ dentry = ERR_PTR(-ENAMETOOLONG); ++ if (unlikely(qs.len > NAME_MAX)) ++ goto out; ++ dentry = ERR_PTR(-ENOMEM); ++ name = kmalloc(qs.len + 1, GFP_NOFS); ++ if (unlikely(!name)) ++ goto out; ++ } ++ ++ /* doubly whiteout-ed */ ++ memcpy(name, AUFS_WH_PFX AUFS_WH_PFX, AUFS_WH_PFX_LEN * 2); ++ p = name + AUFS_WH_PFX_LEN * 2; ++ memcpy(p, prefix->name, prefix->len); ++ p += prefix->len; ++ *p++ = '.'; ++ AuDebugOn(name + qs.len + 1 - p <= AUFS_WH_TMP_LEN); ++ ++ qs.name = name; ++ for (i = 0; i < 3; i++) { ++ sprintf(p, "%.*x", AUFS_WH_TMP_LEN, cnt++); ++ dentry = au_sio_lkup_one(&qs, h_parent); ++ if (IS_ERR(dentry) || d_is_negative(dentry)) ++ goto out_name; ++ dput(dentry); ++ } ++ /* pr_warn("could not get random name\n"); */ ++ dentry = ERR_PTR(-EEXIST); ++ AuDbg("%.*s\n", AuLNPair(&qs)); ++ BUG(); ++ ++out_name: ++ if (name != defname) ++ au_kfree_try_rcu(name); ++out: ++ AuTraceErrPtr(dentry); ++ return dentry; ++} ++ ++/* ++ * rename the @h_dentry on @br to the whiteouted temporary name. ++ */ ++int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br) ++{ ++ int err; ++ struct path h_path = { ++ .mnt = au_br_mnt(br) ++ }; ++ struct inode *h_dir, *delegated; ++ struct dentry *h_parent; ++ ++ h_parent = h_dentry->d_parent; /* dir inode is locked */ ++ h_dir = d_inode(h_parent); ++ IMustLock(h_dir); ++ ++ h_path.dentry = au_whtmp_lkup(h_parent, br, &h_dentry->d_name); ++ err = PTR_ERR(h_path.dentry); ++ if (IS_ERR(h_path.dentry)) ++ goto out; ++ ++ /* under the same dir, no need to lock_rename() */ ++ delegated = NULL; ++ err = vfsub_rename(h_dir, h_dentry, h_dir, &h_path, &delegated, ++ /*flags*/0); ++ AuTraceErr(err); ++ if (unlikely(err == -EWOULDBLOCK)) { ++ pr_warn("cannot retry for NFSv4 delegation" ++ " for an internal rename\n"); ++ iput(delegated); ++ } ++ dput(h_path.dentry); ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++/* ++ * functions for removing a whiteout ++ */ ++ ++static int do_unlink_wh(struct inode *h_dir, struct path *h_path) ++{ ++ int err, force; ++ struct inode *delegated; ++ ++ /* ++ * forces superio when the dir has a sticky bit. ++ * this may be a violation of unix fs semantics. ++ */ ++ force = (h_dir->i_mode & S_ISVTX) ++ && !uid_eq(current_fsuid(), d_inode(h_path->dentry)->i_uid); ++ delegated = NULL; ++ err = vfsub_unlink(h_dir, h_path, &delegated, force); ++ if (unlikely(err == -EWOULDBLOCK)) { ++ pr_warn("cannot retry for NFSv4 delegation" ++ " for an internal unlink\n"); ++ iput(delegated); ++ } ++ return err; ++} ++ ++int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path, ++ struct dentry *dentry) ++{ ++ int err; ++ ++ err = do_unlink_wh(h_dir, h_path); ++ if (!err && dentry) ++ au_set_dbwh(dentry, -1); ++ ++ return err; ++} ++ ++static int unlink_wh_name(struct dentry *h_parent, struct qstr *wh, ++ struct au_branch *br) ++{ ++ int err; ++ struct path h_path = { ++ .mnt = au_br_mnt(br) ++ }; ++ ++ err = 0; ++ h_path.dentry = vfsub_lkup_one(wh, h_parent); ++ if (IS_ERR(h_path.dentry)) ++ err = PTR_ERR(h_path.dentry); ++ else { ++ if (d_is_reg(h_path.dentry)) ++ err = do_unlink_wh(d_inode(h_parent), &h_path); ++ dput(h_path.dentry); ++ } ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++/* ++ * initialize/clean whiteout for a branch ++ */ ++ ++static void au_wh_clean(struct inode *h_dir, struct path *whpath, ++ const int isdir) ++{ ++ int err; ++ struct inode *delegated; ++ ++ if (d_is_negative(whpath->dentry)) ++ return; ++ ++ if (isdir) ++ err = vfsub_rmdir(h_dir, whpath); ++ else { ++ delegated = NULL; ++ err = vfsub_unlink(h_dir, whpath, &delegated, /*force*/0); ++ if (unlikely(err == -EWOULDBLOCK)) { ++ pr_warn("cannot retry for NFSv4 delegation" ++ " for an internal unlink\n"); ++ iput(delegated); ++ } ++ } ++ if (unlikely(err)) ++ pr_warn("failed removing %pd (%d), ignored.\n", ++ whpath->dentry, err); ++} ++ ++static int test_linkable(struct dentry *h_root) ++{ ++ struct inode *h_dir = d_inode(h_root); ++ ++ if (h_dir->i_op->link) ++ return 0; ++ ++ pr_err("%pd (%s) doesn't support link(2), use noplink and rw+nolwh\n", ++ h_root, au_sbtype(h_root->d_sb)); ++ return -ENOSYS; ++} ++ ++/* todo: should this mkdir be done in /sbin/mount.aufs helper? */ ++static int au_whdir(struct inode *h_dir, struct path *path) ++{ ++ int err; ++ ++ err = -EEXIST; ++ if (d_is_negative(path->dentry)) { ++ int mode = 0700; ++ ++ if (au_test_nfs(path->dentry->d_sb)) ++ mode |= 0111; ++ err = vfsub_mkdir(h_dir, path, mode); ++ } else if (d_is_dir(path->dentry)) ++ err = 0; ++ else ++ pr_err("unknown %pd exists\n", path->dentry); ++ ++ return err; ++} ++ ++struct au_wh_base { ++ const struct qstr *name; ++ struct dentry *dentry; ++}; ++ ++static void au_wh_init_ro(struct inode *h_dir, struct au_wh_base base[], ++ struct path *h_path) ++{ ++ h_path->dentry = base[AuBrWh_BASE].dentry; ++ au_wh_clean(h_dir, h_path, /*isdir*/0); ++ h_path->dentry = base[AuBrWh_PLINK].dentry; ++ au_wh_clean(h_dir, h_path, /*isdir*/1); ++ h_path->dentry = base[AuBrWh_ORPH].dentry; ++ au_wh_clean(h_dir, h_path, /*isdir*/1); ++} ++ ++/* ++ * returns tri-state, ++ * minus: error, caller should print the message ++ * zero: success ++ * plus: error, caller should NOT print the message ++ */ ++static int au_wh_init_rw_nolink(struct dentry *h_root, struct au_wbr *wbr, ++ int do_plink, struct au_wh_base base[], ++ struct path *h_path) ++{ ++ int err; ++ struct inode *h_dir; ++ ++ h_dir = d_inode(h_root); ++ h_path->dentry = base[AuBrWh_BASE].dentry; ++ au_wh_clean(h_dir, h_path, /*isdir*/0); ++ h_path->dentry = base[AuBrWh_PLINK].dentry; ++ if (do_plink) { ++ err = test_linkable(h_root); ++ if (unlikely(err)) { ++ err = 1; ++ goto out; ++ } ++ ++ err = au_whdir(h_dir, h_path); ++ if (unlikely(err)) ++ goto out; ++ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry); ++ } else ++ au_wh_clean(h_dir, h_path, /*isdir*/1); ++ h_path->dentry = base[AuBrWh_ORPH].dentry; ++ err = au_whdir(h_dir, h_path); ++ if (unlikely(err)) ++ goto out; ++ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry); ++ ++out: ++ return err; ++} ++ ++/* ++ * for the moment, aufs supports the branch filesystem which does not support ++ * link(2). testing on FAT which does not support i_op->setattr() fully either, ++ * copyup failed. finally, such filesystem will not be used as the writable ++ * branch. ++ * ++ * returns tri-state, see above. ++ */ ++static int au_wh_init_rw(struct dentry *h_root, struct au_wbr *wbr, ++ int do_plink, struct au_wh_base base[], ++ struct path *h_path) ++{ ++ int err; ++ struct inode *h_dir; ++ ++ WbrWhMustWriteLock(wbr); ++ ++ err = test_linkable(h_root); ++ if (unlikely(err)) { ++ err = 1; ++ goto out; ++ } ++ ++ /* ++ * todo: should this create be done in /sbin/mount.aufs helper? ++ */ ++ err = -EEXIST; ++ h_dir = d_inode(h_root); ++ if (d_is_negative(base[AuBrWh_BASE].dentry)) { ++ h_path->dentry = base[AuBrWh_BASE].dentry; ++ err = vfsub_create(h_dir, h_path, WH_MASK, /*want_excl*/true); ++ } else if (d_is_reg(base[AuBrWh_BASE].dentry)) ++ err = 0; ++ else ++ pr_err("unknown %pd2 exists\n", base[AuBrWh_BASE].dentry); ++ if (unlikely(err)) ++ goto out; ++ ++ h_path->dentry = base[AuBrWh_PLINK].dentry; ++ if (do_plink) { ++ err = au_whdir(h_dir, h_path); ++ if (unlikely(err)) ++ goto out; ++ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry); ++ } else ++ au_wh_clean(h_dir, h_path, /*isdir*/1); ++ wbr->wbr_whbase = dget(base[AuBrWh_BASE].dentry); ++ ++ h_path->dentry = base[AuBrWh_ORPH].dentry; ++ err = au_whdir(h_dir, h_path); ++ if (unlikely(err)) ++ goto out; ++ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry); ++ ++out: ++ return err; ++} ++ ++/* ++ * initialize the whiteout base file/dir for @br. ++ */ ++int au_wh_init(struct au_branch *br, struct super_block *sb) ++{ ++ int err, i; ++ const unsigned char do_plink ++ = !!au_opt_test(au_mntflags(sb), PLINK); ++ struct inode *h_dir; ++ struct path path = br->br_path; ++ struct dentry *h_root = path.dentry; ++ struct au_wbr *wbr = br->br_wbr; ++ static const struct qstr base_name[] = { ++ [AuBrWh_BASE] = QSTR_INIT(AUFS_BASE_NAME, ++ sizeof(AUFS_BASE_NAME) - 1), ++ [AuBrWh_PLINK] = QSTR_INIT(AUFS_PLINKDIR_NAME, ++ sizeof(AUFS_PLINKDIR_NAME) - 1), ++ [AuBrWh_ORPH] = QSTR_INIT(AUFS_ORPHDIR_NAME, ++ sizeof(AUFS_ORPHDIR_NAME) - 1) ++ }; ++ struct au_wh_base base[] = { ++ [AuBrWh_BASE] = { ++ .name = base_name + AuBrWh_BASE, ++ .dentry = NULL ++ }, ++ [AuBrWh_PLINK] = { ++ .name = base_name + AuBrWh_PLINK, ++ .dentry = NULL ++ }, ++ [AuBrWh_ORPH] = { ++ .name = base_name + AuBrWh_ORPH, ++ .dentry = NULL ++ } ++ }; ++ ++ if (wbr) ++ WbrWhMustWriteLock(wbr); ++ ++ for (i = 0; i < AuBrWh_Last; i++) { ++ /* doubly whiteouted */ ++ struct dentry *d; ++ ++ d = au_wh_lkup(h_root, (void *)base[i].name, br); ++ err = PTR_ERR(d); ++ if (IS_ERR(d)) ++ goto out; ++ ++ base[i].dentry = d; ++ AuDebugOn(wbr ++ && wbr->wbr_wh[i] ++ && wbr->wbr_wh[i] != base[i].dentry); ++ } ++ ++ if (wbr) ++ for (i = 0; i < AuBrWh_Last; i++) { ++ dput(wbr->wbr_wh[i]); ++ wbr->wbr_wh[i] = NULL; ++ } ++ ++ err = 0; ++ if (!au_br_writable(br->br_perm)) { ++ h_dir = d_inode(h_root); ++ au_wh_init_ro(h_dir, base, &path); ++ } else if (!au_br_wh_linkable(br->br_perm)) { ++ err = au_wh_init_rw_nolink(h_root, wbr, do_plink, base, &path); ++ if (err > 0) ++ goto out; ++ else if (err) ++ goto out_err; ++ } else { ++ err = au_wh_init_rw(h_root, wbr, do_plink, base, &path); ++ if (err > 0) ++ goto out; ++ else if (err) ++ goto out_err; ++ } ++ goto out; /* success */ ++ ++out_err: ++ pr_err("an error(%d) on the writable branch %pd(%s)\n", ++ err, h_root, au_sbtype(h_root->d_sb)); ++out: ++ for (i = 0; i < AuBrWh_Last; i++) ++ dput(base[i].dentry); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++/* ++ * whiteouts are all hard-linked usually. ++ * when its link count reaches a ceiling, we create a new whiteout base ++ * asynchronously. ++ */ ++ ++struct reinit_br_wh { ++ struct super_block *sb; ++ struct au_branch *br; ++}; ++ ++static void reinit_br_wh(void *arg) ++{ ++ int err; ++ aufs_bindex_t bindex; ++ struct path h_path; ++ struct reinit_br_wh *a = arg; ++ struct au_wbr *wbr; ++ struct inode *dir, *delegated; ++ struct dentry *h_root; ++ struct au_hinode *hdir; ++ ++ err = 0; ++ wbr = a->br->br_wbr; ++ /* big aufs lock */ ++ si_noflush_write_lock(a->sb); ++ if (!au_br_writable(a->br->br_perm)) ++ goto out; ++ bindex = au_br_index(a->sb, a->br->br_id); ++ if (unlikely(bindex < 0)) ++ goto out; ++ ++ di_read_lock_parent(a->sb->s_root, AuLock_IR); ++ dir = d_inode(a->sb->s_root); ++ hdir = au_hi(dir, bindex); ++ h_root = au_h_dptr(a->sb->s_root, bindex); ++ AuDebugOn(h_root != au_br_dentry(a->br)); ++ ++ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT); ++ wbr_wh_write_lock(wbr); ++ err = au_h_verify(wbr->wbr_whbase, au_opt_udba(a->sb), hdir->hi_inode, ++ h_root, a->br); ++ if (!err) { ++ h_path.dentry = wbr->wbr_whbase; ++ h_path.mnt = au_br_mnt(a->br); ++ delegated = NULL; ++ err = vfsub_unlink(hdir->hi_inode, &h_path, &delegated, ++ /*force*/0); ++ if (unlikely(err == -EWOULDBLOCK)) { ++ pr_warn("cannot retry for NFSv4 delegation" ++ " for an internal unlink\n"); ++ iput(delegated); ++ } ++ } else { ++ pr_warn("%pd is moved, ignored\n", wbr->wbr_whbase); ++ err = 0; ++ } ++ dput(wbr->wbr_whbase); ++ wbr->wbr_whbase = NULL; ++ if (!err) ++ err = au_wh_init(a->br, a->sb); ++ wbr_wh_write_unlock(wbr); ++ au_hn_inode_unlock(hdir); ++ di_read_unlock(a->sb->s_root, AuLock_IR); ++ if (!err) ++ au_fhsm_wrote(a->sb, bindex, /*force*/0); ++ ++out: ++ if (wbr) ++ atomic_dec(&wbr->wbr_wh_running); ++ au_lcnt_dec(&a->br->br_count); ++ si_write_unlock(a->sb); ++ au_nwt_done(&au_sbi(a->sb)->si_nowait); ++ au_kfree_rcu(a); ++ if (unlikely(err)) ++ AuIOErr("err %d\n", err); ++} ++ ++static void kick_reinit_br_wh(struct super_block *sb, struct au_branch *br) ++{ ++ int do_dec, wkq_err; ++ struct reinit_br_wh *arg; ++ ++ do_dec = 1; ++ if (atomic_inc_return(&br->br_wbr->wbr_wh_running) != 1) ++ goto out; ++ ++ /* ignore ENOMEM */ ++ arg = kmalloc(sizeof(*arg), GFP_NOFS); ++ if (arg) { ++ /* ++ * dec(wh_running), kfree(arg) and dec(br_count) ++ * in reinit function ++ */ ++ arg->sb = sb; ++ arg->br = br; ++ au_lcnt_inc(&br->br_count); ++ wkq_err = au_wkq_nowait(reinit_br_wh, arg, sb, /*flags*/0); ++ if (unlikely(wkq_err)) { ++ atomic_dec(&br->br_wbr->wbr_wh_running); ++ au_lcnt_dec(&br->br_count); ++ au_kfree_rcu(arg); ++ } ++ do_dec = 0; ++ } ++ ++out: ++ if (do_dec) ++ atomic_dec(&br->br_wbr->wbr_wh_running); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * create the whiteout @wh. ++ */ ++static int link_or_create_wh(struct super_block *sb, aufs_bindex_t bindex, ++ struct dentry *wh) ++{ ++ int err; ++ struct path h_path = { ++ .dentry = wh ++ }; ++ struct au_branch *br; ++ struct au_wbr *wbr; ++ struct dentry *h_parent; ++ struct inode *h_dir, *delegated; ++ ++ h_parent = wh->d_parent; /* dir inode is locked */ ++ h_dir = d_inode(h_parent); ++ IMustLock(h_dir); ++ ++ br = au_sbr(sb, bindex); ++ h_path.mnt = au_br_mnt(br); ++ wbr = br->br_wbr; ++ wbr_wh_read_lock(wbr); ++ if (wbr->wbr_whbase) { ++ delegated = NULL; ++ err = vfsub_link(wbr->wbr_whbase, h_dir, &h_path, &delegated); ++ if (unlikely(err == -EWOULDBLOCK)) { ++ pr_warn("cannot retry for NFSv4 delegation" ++ " for an internal link\n"); ++ iput(delegated); ++ } ++ if (!err || err != -EMLINK) ++ goto out; ++ ++ /* link count full. re-initialize br_whbase. */ ++ kick_reinit_br_wh(sb, br); ++ } ++ ++ /* return this error in this context */ ++ err = vfsub_create(h_dir, &h_path, WH_MASK, /*want_excl*/true); ++ if (!err) ++ au_fhsm_wrote(sb, bindex, /*force*/0); ++ ++out: ++ wbr_wh_read_unlock(wbr); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * create or remove the diropq. ++ */ ++static struct dentry *do_diropq(struct dentry *dentry, aufs_bindex_t bindex, ++ unsigned int flags) ++{ ++ struct dentry *opq_dentry, *h_dentry; ++ struct super_block *sb; ++ struct au_branch *br; ++ int err; ++ ++ sb = dentry->d_sb; ++ br = au_sbr(sb, bindex); ++ h_dentry = au_h_dptr(dentry, bindex); ++ opq_dentry = vfsub_lkup_one(&diropq_name, h_dentry); ++ if (IS_ERR(opq_dentry)) ++ goto out; ++ ++ if (au_ftest_diropq(flags, CREATE)) { ++ err = link_or_create_wh(sb, bindex, opq_dentry); ++ if (!err) { ++ au_set_dbdiropq(dentry, bindex); ++ goto out; /* success */ ++ } ++ } else { ++ struct path tmp = { ++ .dentry = opq_dentry, ++ .mnt = au_br_mnt(br) ++ }; ++ err = do_unlink_wh(au_h_iptr(d_inode(dentry), bindex), &tmp); ++ if (!err) ++ au_set_dbdiropq(dentry, -1); ++ } ++ dput(opq_dentry); ++ opq_dentry = ERR_PTR(err); ++ ++out: ++ return opq_dentry; ++} ++ ++struct do_diropq_args { ++ struct dentry **errp; ++ struct dentry *dentry; ++ aufs_bindex_t bindex; ++ unsigned int flags; ++}; ++ ++static void call_do_diropq(void *args) ++{ ++ struct do_diropq_args *a = args; ++ *a->errp = do_diropq(a->dentry, a->bindex, a->flags); ++} ++ ++struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex, ++ unsigned int flags) ++{ ++ struct dentry *diropq, *h_dentry; ++ ++ h_dentry = au_h_dptr(dentry, bindex); ++ if (!au_test_h_perm_sio(d_inode(h_dentry), MAY_EXEC | MAY_WRITE)) ++ diropq = do_diropq(dentry, bindex, flags); ++ else { ++ int wkq_err; ++ struct do_diropq_args args = { ++ .errp = &diropq, ++ .dentry = dentry, ++ .bindex = bindex, ++ .flags = flags ++ }; ++ ++ wkq_err = au_wkq_wait(call_do_diropq, &args); ++ if (unlikely(wkq_err)) ++ diropq = ERR_PTR(wkq_err); ++ } ++ ++ return diropq; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * lookup whiteout dentry. ++ * @h_parent: lower parent dentry which must exist and be locked ++ * @base_name: name of dentry which will be whiteouted ++ * returns dentry for whiteout. ++ */ ++struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name, ++ struct au_branch *br) ++{ ++ int err; ++ struct qstr wh_name; ++ struct dentry *wh_dentry; ++ ++ err = au_wh_name_alloc(&wh_name, base_name); ++ wh_dentry = ERR_PTR(err); ++ if (!err) { ++ wh_dentry = vfsub_lkup_one(&wh_name, h_parent); ++ au_kfree_try_rcu(wh_name.name); ++ } ++ return wh_dentry; ++} ++ ++/* ++ * link/create a whiteout for @dentry on @bindex. ++ */ ++struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex, ++ struct dentry *h_parent) ++{ ++ struct dentry *wh_dentry; ++ struct super_block *sb; ++ int err; ++ ++ sb = dentry->d_sb; ++ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, au_sbr(sb, bindex)); ++ if (!IS_ERR(wh_dentry) && d_is_negative(wh_dentry)) { ++ err = link_or_create_wh(sb, bindex, wh_dentry); ++ if (!err) { ++ au_set_dbwh(dentry, bindex); ++ au_fhsm_wrote(sb, bindex, /*force*/0); ++ } else { ++ dput(wh_dentry); ++ wh_dentry = ERR_PTR(err); ++ } ++ } ++ ++ return wh_dentry; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* Delete all whiteouts in this directory on branch bindex. */ ++static int del_wh_children(struct dentry *h_dentry, struct au_nhash *whlist, ++ aufs_bindex_t bindex, struct au_branch *br) ++{ ++ int err; ++ unsigned long ul, n; ++ struct qstr wh_name; ++ char *p; ++ struct hlist_head *head; ++ struct au_vdir_wh *pos; ++ struct au_vdir_destr *str; ++ ++ err = -ENOMEM; ++ p = (void *)__get_free_page(GFP_NOFS); ++ wh_name.name = p; ++ if (unlikely(!wh_name.name)) ++ goto out; ++ ++ err = 0; ++ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN); ++ p += AUFS_WH_PFX_LEN; ++ n = whlist->nh_num; ++ head = whlist->nh_head; ++ for (ul = 0; !err && ul < n; ul++, head++) { ++ hlist_for_each_entry(pos, head, wh_hash) { ++ if (pos->wh_bindex != bindex) ++ continue; ++ ++ str = &pos->wh_str; ++ if (str->len + AUFS_WH_PFX_LEN <= PATH_MAX) { ++ memcpy(p, str->name, str->len); ++ wh_name.len = AUFS_WH_PFX_LEN + str->len; ++ err = unlink_wh_name(h_dentry, &wh_name, br); ++ if (!err) ++ continue; ++ break; ++ } ++ AuIOErr("whiteout name too long %.*s\n", ++ str->len, str->name); ++ err = -EIO; ++ break; ++ } ++ } ++ free_page((unsigned long)wh_name.name); ++ ++out: ++ return err; ++} ++ ++struct del_wh_children_args { ++ int *errp; ++ struct dentry *h_dentry; ++ struct au_nhash *whlist; ++ aufs_bindex_t bindex; ++ struct au_branch *br; ++}; ++ ++static void call_del_wh_children(void *args) ++{ ++ struct del_wh_children_args *a = args; ++ *a->errp = del_wh_children(a->h_dentry, a->whlist, a->bindex, a->br); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp) ++{ ++ struct au_whtmp_rmdir *whtmp; ++ int err; ++ unsigned int rdhash; ++ ++ SiMustAnyLock(sb); ++ ++ whtmp = kzalloc(sizeof(*whtmp), gfp); ++ if (unlikely(!whtmp)) { ++ whtmp = ERR_PTR(-ENOMEM); ++ goto out; ++ } ++ ++ /* no estimation for dir size */ ++ rdhash = au_sbi(sb)->si_rdhash; ++ if (!rdhash) ++ rdhash = AUFS_RDHASH_DEF; ++ err = au_nhash_alloc(&whtmp->whlist, rdhash, gfp); ++ if (unlikely(err)) { ++ au_kfree_rcu(whtmp); ++ whtmp = ERR_PTR(err); ++ } ++ ++out: ++ return whtmp; ++} ++ ++void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp) ++{ ++ if (whtmp->br) ++ au_lcnt_dec(&whtmp->br->br_count); ++ dput(whtmp->wh_dentry); ++ iput(whtmp->dir); ++ au_nhash_wh_free(&whtmp->whlist); ++ au_kfree_rcu(whtmp); ++} ++ ++/* ++ * rmdir the whiteouted temporary named dir @h_dentry. ++ * @whlist: whiteouted children. ++ */ ++int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex, ++ struct dentry *wh_dentry, struct au_nhash *whlist) ++{ ++ int err; ++ unsigned int h_nlink; ++ struct path h_tmp; ++ struct inode *wh_inode, *h_dir; ++ struct au_branch *br; ++ ++ h_dir = d_inode(wh_dentry->d_parent); /* dir inode is locked */ ++ IMustLock(h_dir); ++ ++ br = au_sbr(dir->i_sb, bindex); ++ wh_inode = d_inode(wh_dentry); ++ inode_lock_nested(wh_inode, AuLsc_I_CHILD); ++ ++ /* ++ * someone else might change some whiteouts while we were sleeping. ++ * it means this whlist may have an obsoleted entry. ++ */ ++ if (!au_test_h_perm_sio(wh_inode, MAY_EXEC | MAY_WRITE)) ++ err = del_wh_children(wh_dentry, whlist, bindex, br); ++ else { ++ int wkq_err; ++ struct del_wh_children_args args = { ++ .errp = &err, ++ .h_dentry = wh_dentry, ++ .whlist = whlist, ++ .bindex = bindex, ++ .br = br ++ }; ++ ++ wkq_err = au_wkq_wait(call_del_wh_children, &args); ++ if (unlikely(wkq_err)) ++ err = wkq_err; ++ } ++ inode_unlock(wh_inode); ++ ++ if (!err) { ++ h_tmp.dentry = wh_dentry; ++ h_tmp.mnt = au_br_mnt(br); ++ h_nlink = h_dir->i_nlink; ++ err = vfsub_rmdir(h_dir, &h_tmp); ++ /* some fs doesn't change the parent nlink in some cases */ ++ h_nlink -= h_dir->i_nlink; ++ } ++ ++ if (!err) { ++ if (au_ibtop(dir) == bindex) { ++ /* todo: dir->i_mutex is necessary */ ++ au_cpup_attr_timesizes(dir); ++ if (h_nlink) ++ vfsub_drop_nlink(dir); ++ } ++ return 0; /* success */ ++ } ++ ++ pr_warn("failed removing %pd(%d), ignored\n", wh_dentry, err); ++ return err; ++} ++ ++static void call_rmdir_whtmp(void *args) ++{ ++ int err; ++ aufs_bindex_t bindex; ++ struct au_whtmp_rmdir *a = args; ++ struct super_block *sb; ++ struct dentry *h_parent; ++ struct inode *h_dir; ++ struct au_hinode *hdir; ++ ++ /* rmdir by nfsd may cause deadlock with this i_mutex */ ++ /* inode_lock(a->dir); */ ++ err = -EROFS; ++ sb = a->dir->i_sb; ++ si_read_lock(sb, !AuLock_FLUSH); ++ if (!au_br_writable(a->br->br_perm)) ++ goto out; ++ bindex = au_br_index(sb, a->br->br_id); ++ if (unlikely(bindex < 0)) ++ goto out; ++ ++ err = -EIO; ++ ii_write_lock_parent(a->dir); ++ h_parent = dget_parent(a->wh_dentry); ++ h_dir = d_inode(h_parent); ++ hdir = au_hi(a->dir, bindex); ++ err = vfsub_mnt_want_write(au_br_mnt(a->br)); ++ if (unlikely(err)) ++ goto out_mnt; ++ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT); ++ err = au_h_verify(a->wh_dentry, au_opt_udba(sb), h_dir, h_parent, ++ a->br); ++ if (!err) ++ err = au_whtmp_rmdir(a->dir, bindex, a->wh_dentry, &a->whlist); ++ au_hn_inode_unlock(hdir); ++ vfsub_mnt_drop_write(au_br_mnt(a->br)); ++ ++out_mnt: ++ dput(h_parent); ++ ii_write_unlock(a->dir); ++out: ++ /* inode_unlock(a->dir); */ ++ au_whtmp_rmdir_free(a); ++ si_read_unlock(sb); ++ au_nwt_done(&au_sbi(sb)->si_nowait); ++ if (unlikely(err)) ++ AuIOErr("err %d\n", err); ++} ++ ++void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex, ++ struct dentry *wh_dentry, struct au_whtmp_rmdir *args) ++{ ++ int wkq_err; ++ struct super_block *sb; ++ ++ IMustLock(dir); ++ ++ /* all post-process will be done in do_rmdir_whtmp(). */ ++ sb = dir->i_sb; ++ args->dir = au_igrab(dir); ++ args->br = au_sbr(sb, bindex); ++ au_lcnt_inc(&args->br->br_count); ++ args->wh_dentry = dget(wh_dentry); ++ wkq_err = au_wkq_nowait(call_rmdir_whtmp, args, sb, /*flags*/0); ++ if (unlikely(wkq_err)) { ++ pr_warn("rmdir error %pd (%d), ignored\n", wh_dentry, wkq_err); ++ au_whtmp_rmdir_free(args); ++ } ++} +diff -Nurp linux-5.4/fs/aufs/whout.h linux-5.4-aufs/fs/aufs/whout.h +--- linux-5.4/fs/aufs/whout.h 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/whout.h 2019-11-28 01:25:59.069925618 +0200 +@@ -0,0 +1,73 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * whiteout for logical deletion and opaque directory ++ */ ++ ++#ifndef __AUFS_WHOUT_H__ ++#define __AUFS_WHOUT_H__ ++ ++#ifdef __KERNEL__ ++ ++#include "dir.h" ++ ++/* whout.c */ ++int au_wh_name_alloc(struct qstr *wh, const struct qstr *name); ++int au_wh_test(struct dentry *h_parent, struct qstr *wh_name, int try_sio); ++int au_diropq_test(struct dentry *h_dentry); ++struct au_branch; ++struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br, ++ struct qstr *prefix); ++int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br); ++int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path, ++ struct dentry *dentry); ++int au_wh_init(struct au_branch *br, struct super_block *sb); ++ ++/* diropq flags */ ++#define AuDiropq_CREATE 1 ++#define au_ftest_diropq(flags, name) ((flags) & AuDiropq_##name) ++#define au_fset_diropq(flags, name) \ ++ do { (flags) |= AuDiropq_##name; } while (0) ++#define au_fclr_diropq(flags, name) \ ++ do { (flags) &= ~AuDiropq_##name; } while (0) ++ ++struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex, ++ unsigned int flags); ++struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name, ++ struct au_branch *br); ++struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex, ++ struct dentry *h_parent); ++ ++/* real rmdir for the whiteout-ed dir */ ++struct au_whtmp_rmdir { ++ struct inode *dir; ++ struct au_branch *br; ++ struct dentry *wh_dentry; ++ struct au_nhash whlist; ++}; ++ ++struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp); ++void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp); ++int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex, ++ struct dentry *wh_dentry, struct au_nhash *whlist); ++void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex, ++ struct dentry *wh_dentry, struct au_whtmp_rmdir *args); ++ ++/* ---------------------------------------------------------------------- */ ++ ++static inline struct dentry *au_diropq_create(struct dentry *dentry, ++ aufs_bindex_t bindex) ++{ ++ return au_diropq_sio(dentry, bindex, AuDiropq_CREATE); ++} ++ ++static inline int au_diropq_remove(struct dentry *dentry, aufs_bindex_t bindex) ++{ ++ return PTR_ERR(au_diropq_sio(dentry, bindex, !AuDiropq_CREATE)); ++} ++ ++#endif /* __KERNEL__ */ ++#endif /* __AUFS_WHOUT_H__ */ +diff -Nurp linux-5.4/fs/aufs/wkq.c linux-5.4-aufs/fs/aufs/wkq.c +--- linux-5.4/fs/aufs/wkq.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/wkq.c 2019-11-28 01:25:59.069925618 +0200 +@@ -0,0 +1,379 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * workqueue for asynchronous/super-io operations ++ * todo: try new credential scheme ++ */ ++ ++#include ++#include "aufs.h" ++ ++/* internal workqueue named AUFS_WKQ_NAME */ ++ ++static struct workqueue_struct *au_wkq; ++ ++struct au_wkinfo { ++ struct work_struct wk; ++ struct kobject *kobj; ++ ++ unsigned int flags; /* see wkq.h */ ++ ++ au_wkq_func_t func; ++ void *args; ++ ++#ifdef CONFIG_LOCKDEP ++ int dont_check; ++ struct held_lock **hlock; ++#endif ++ ++ struct completion *comp; ++}; ++ ++/* ---------------------------------------------------------------------- */ ++/* ++ * Aufs passes some operations to the workqueue such as the internal copyup. ++ * This scheme looks rather unnatural for LOCKDEP debugging feature, since the ++ * job run by workqueue depends upon the locks acquired in the other task. ++ * Delegating a small operation to the workqueue, aufs passes its lockdep ++ * information too. And the job in the workqueue restores the info in order to ++ * pretend as if it acquired those locks. This is just to make LOCKDEP work ++ * correctly and expectedly. ++ */ ++ ++#ifndef CONFIG_LOCKDEP ++AuStubInt0(au_wkq_lockdep_alloc, struct au_wkinfo *wkinfo); ++AuStubVoid(au_wkq_lockdep_free, struct au_wkinfo *wkinfo); ++AuStubVoid(au_wkq_lockdep_pre, struct au_wkinfo *wkinfo); ++AuStubVoid(au_wkq_lockdep_post, struct au_wkinfo *wkinfo); ++AuStubVoid(au_wkq_lockdep_init, struct au_wkinfo *wkinfo); ++#else ++static void au_wkq_lockdep_init(struct au_wkinfo *wkinfo) ++{ ++ wkinfo->hlock = NULL; ++ wkinfo->dont_check = 0; ++} ++ ++/* ++ * 1: matched ++ * 0: unmatched ++ */ ++static int au_wkq_lockdep_test(struct lock_class_key *key, const char *name) ++{ ++ static DEFINE_SPINLOCK(spin); ++ static struct { ++ char *name; ++ struct lock_class_key *key; ++ } a[] = { ++ { .name = "&sbinfo->si_rwsem" }, ++ { .name = "&finfo->fi_rwsem" }, ++ { .name = "&dinfo->di_rwsem" }, ++ { .name = "&iinfo->ii_rwsem" } ++ }; ++ static int set; ++ int i; ++ ++ /* lockless read from 'set.' see below */ ++ if (set == ARRAY_SIZE(a)) { ++ for (i = 0; i < ARRAY_SIZE(a); i++) ++ if (a[i].key == key) ++ goto match; ++ goto unmatch; ++ } ++ ++ spin_lock(&spin); ++ if (set) ++ for (i = 0; i < ARRAY_SIZE(a); i++) ++ if (a[i].key == key) { ++ spin_unlock(&spin); ++ goto match; ++ } ++ for (i = 0; i < ARRAY_SIZE(a); i++) { ++ if (a[i].key) { ++ if (unlikely(a[i].key == key)) { /* rare but possible */ ++ spin_unlock(&spin); ++ goto match; ++ } else ++ continue; ++ } ++ if (strstr(a[i].name, name)) { ++ /* ++ * the order of these three lines is important for the ++ * lockless read above. ++ */ ++ a[i].key = key; ++ spin_unlock(&spin); ++ set++; ++ /* AuDbg("%d, %s\n", set, name); */ ++ goto match; ++ } ++ } ++ spin_unlock(&spin); ++ goto unmatch; ++ ++match: ++ return 1; ++unmatch: ++ return 0; ++} ++ ++static int au_wkq_lockdep_alloc(struct au_wkinfo *wkinfo) ++{ ++ int err, n; ++ struct task_struct *curr; ++ struct held_lock **hl, *held_locks, *p; ++ ++ err = 0; ++ curr = current; ++ wkinfo->dont_check = lockdep_recursing(curr); ++ if (wkinfo->dont_check) ++ goto out; ++ n = curr->lockdep_depth; ++ if (!n) ++ goto out; ++ ++ err = -ENOMEM; ++ wkinfo->hlock = kmalloc_array(n + 1, sizeof(*wkinfo->hlock), GFP_NOFS); ++ if (unlikely(!wkinfo->hlock)) ++ goto out; ++ ++ err = 0; ++#if 0 ++ if (0 && au_debug_test()) /* left for debugging */ ++ lockdep_print_held_locks(curr); ++#endif ++ held_locks = curr->held_locks; ++ hl = wkinfo->hlock; ++ while (n--) { ++ p = held_locks++; ++ if (au_wkq_lockdep_test(p->instance->key, p->instance->name)) ++ *hl++ = p; ++ } ++ *hl = NULL; ++ ++out: ++ return err; ++} ++ ++static void au_wkq_lockdep_free(struct au_wkinfo *wkinfo) ++{ ++ au_kfree_try_rcu(wkinfo->hlock); ++} ++ ++static void au_wkq_lockdep_pre(struct au_wkinfo *wkinfo) ++{ ++ struct held_lock *p, **hl = wkinfo->hlock; ++ int subclass; ++ ++ if (wkinfo->dont_check) ++ lockdep_off(); ++ if (!hl) ++ return; ++ while ((p = *hl++)) { /* assignment */ ++ subclass = lockdep_hlock_class(p)->subclass; ++ /* AuDbg("%s, %d\n", p->instance->name, subclass); */ ++ if (p->read) ++ rwsem_acquire_read(p->instance, subclass, 0, ++ /*p->acquire_ip*/_RET_IP_); ++ else ++ rwsem_acquire(p->instance, subclass, 0, ++ /*p->acquire_ip*/_RET_IP_); ++ } ++} ++ ++static void au_wkq_lockdep_post(struct au_wkinfo *wkinfo) ++{ ++ struct held_lock *p, **hl = wkinfo->hlock; ++ ++ if (wkinfo->dont_check) ++ lockdep_on(); ++ if (!hl) ++ return; ++ while ((p = *hl++)) /* assignment */ ++ rwsem_release(p->instance, 0, /*p->acquire_ip*/_RET_IP_); ++} ++#endif ++ ++static void wkq_func(struct work_struct *wk) ++{ ++ struct au_wkinfo *wkinfo = container_of(wk, struct au_wkinfo, wk); ++ ++ AuDebugOn(!uid_eq(current_fsuid(), GLOBAL_ROOT_UID)); ++ AuDebugOn(rlimit(RLIMIT_FSIZE) != RLIM_INFINITY); ++ ++ au_wkq_lockdep_pre(wkinfo); ++ wkinfo->func(wkinfo->args); ++ au_wkq_lockdep_post(wkinfo); ++ if (au_ftest_wkq(wkinfo->flags, WAIT)) ++ complete(wkinfo->comp); ++ else { ++ kobject_put(wkinfo->kobj); ++ module_put(THIS_MODULE); /* todo: ?? */ ++ au_kfree_rcu(wkinfo); ++ } ++} ++ ++/* ++ * Since struct completion is large, try allocating it dynamically. ++ */ ++#if 1 /* defined(CONFIG_4KSTACKS) || defined(AuTest4KSTACKS) */ ++#define AuWkqCompDeclare(name) struct completion *comp = NULL ++ ++static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp) ++{ ++ *comp = kmalloc(sizeof(**comp), GFP_NOFS); ++ if (*comp) { ++ init_completion(*comp); ++ wkinfo->comp = *comp; ++ return 0; ++ } ++ return -ENOMEM; ++} ++ ++static void au_wkq_comp_free(struct completion *comp) ++{ ++ au_kfree_rcu(comp); ++} ++ ++#else ++ ++/* no braces */ ++#define AuWkqCompDeclare(name) \ ++ DECLARE_COMPLETION_ONSTACK(_ ## name); \ ++ struct completion *comp = &_ ## name ++ ++static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp) ++{ ++ wkinfo->comp = *comp; ++ return 0; ++} ++ ++static void au_wkq_comp_free(struct completion *comp __maybe_unused) ++{ ++ /* empty */ ++} ++#endif /* 4KSTACKS */ ++ ++static void au_wkq_run(struct au_wkinfo *wkinfo) ++{ ++ if (au_ftest_wkq(wkinfo->flags, NEST)) { ++ if (au_wkq_test()) { ++ AuWarn1("wkq from wkq, unless silly-rename on NFS," ++ " due to a dead dir by UDBA," ++ " or async xino write?\n"); ++ AuDebugOn(au_ftest_wkq(wkinfo->flags, WAIT)); ++ } ++ } else ++ au_dbg_verify_kthread(); ++ ++ if (au_ftest_wkq(wkinfo->flags, WAIT)) { ++ INIT_WORK_ONSTACK(&wkinfo->wk, wkq_func); ++ queue_work(au_wkq, &wkinfo->wk); ++ } else { ++ INIT_WORK(&wkinfo->wk, wkq_func); ++ schedule_work(&wkinfo->wk); ++ } ++} ++ ++/* ++ * Be careful. It is easy to make deadlock happen. ++ * processA: lock, wkq and wait ++ * processB: wkq and wait, lock in wkq ++ * --> deadlock ++ */ ++int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args) ++{ ++ int err; ++ AuWkqCompDeclare(comp); ++ struct au_wkinfo wkinfo = { ++ .flags = flags, ++ .func = func, ++ .args = args ++ }; ++ ++ err = au_wkq_comp_alloc(&wkinfo, &comp); ++ if (unlikely(err)) ++ goto out; ++ err = au_wkq_lockdep_alloc(&wkinfo); ++ if (unlikely(err)) ++ goto out_comp; ++ if (!err) { ++ au_wkq_run(&wkinfo); ++ /* no timeout, no interrupt */ ++ wait_for_completion(wkinfo.comp); ++ } ++ au_wkq_lockdep_free(&wkinfo); ++ ++out_comp: ++ au_wkq_comp_free(comp); ++out: ++ destroy_work_on_stack(&wkinfo.wk); ++ return err; ++} ++ ++/* ++ * Note: dget/dput() in func for aufs dentries are not supported. It will be a ++ * problem in a concurrent umounting. ++ */ ++int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb, ++ unsigned int flags) ++{ ++ int err; ++ struct au_wkinfo *wkinfo; ++ ++ atomic_inc(&au_sbi(sb)->si_nowait.nw_len); ++ ++ /* ++ * wkq_func() must free this wkinfo. ++ * it highly depends upon the implementation of workqueue. ++ */ ++ err = 0; ++ wkinfo = kmalloc(sizeof(*wkinfo), GFP_NOFS); ++ if (wkinfo) { ++ wkinfo->kobj = &au_sbi(sb)->si_kobj; ++ wkinfo->flags = flags & ~AuWkq_WAIT; ++ wkinfo->func = func; ++ wkinfo->args = args; ++ wkinfo->comp = NULL; ++ au_wkq_lockdep_init(wkinfo); ++ kobject_get(wkinfo->kobj); ++ __module_get(THIS_MODULE); /* todo: ?? */ ++ ++ au_wkq_run(wkinfo); ++ } else { ++ err = -ENOMEM; ++ au_nwt_done(&au_sbi(sb)->si_nowait); ++ } ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++void au_nwt_init(struct au_nowait_tasks *nwt) ++{ ++ atomic_set(&nwt->nw_len, 0); ++ /* smp_mb(); */ /* atomic_set */ ++ init_waitqueue_head(&nwt->nw_wq); ++} ++ ++void au_wkq_fin(void) ++{ ++ destroy_workqueue(au_wkq); ++} ++ ++int __init au_wkq_init(void) ++{ ++ int err; ++ ++ err = 0; ++ au_wkq = alloc_workqueue(AUFS_WKQ_NAME, 0, WQ_DFL_ACTIVE); ++ if (IS_ERR(au_wkq)) ++ err = PTR_ERR(au_wkq); ++ else if (!au_wkq) ++ err = -ENOMEM; ++ ++ return err; ++} +diff -Nurp linux-5.4/fs/aufs/wkq.h linux-5.4-aufs/fs/aufs/wkq.h +--- linux-5.4/fs/aufs/wkq.h 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/wkq.h 2019-11-28 01:25:59.069925618 +0200 +@@ -0,0 +1,76 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * workqueue for asynchronous/super-io operations ++ * todo: try new credentials management scheme ++ */ ++ ++#ifndef __AUFS_WKQ_H__ ++#define __AUFS_WKQ_H__ ++ ++#ifdef __KERNEL__ ++ ++#include ++ ++struct super_block; ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * in the next operation, wait for the 'nowait' tasks in system-wide workqueue ++ */ ++struct au_nowait_tasks { ++ atomic_t nw_len; ++ wait_queue_head_t nw_wq; ++}; ++ ++/* ---------------------------------------------------------------------- */ ++ ++typedef void (*au_wkq_func_t)(void *args); ++ ++/* wkq flags */ ++#define AuWkq_WAIT 1 ++#define AuWkq_NEST (1 << 1) ++#define au_ftest_wkq(flags, name) ((flags) & AuWkq_##name) ++#define au_fset_wkq(flags, name) \ ++ do { (flags) |= AuWkq_##name; } while (0) ++#define au_fclr_wkq(flags, name) \ ++ do { (flags) &= ~AuWkq_##name; } while (0) ++ ++/* wkq.c */ ++int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args); ++int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb, ++ unsigned int flags); ++void au_nwt_init(struct au_nowait_tasks *nwt); ++int __init au_wkq_init(void); ++void au_wkq_fin(void); ++ ++/* ---------------------------------------------------------------------- */ ++ ++static inline int au_wkq_test(void) ++{ ++ return current->flags & PF_WQ_WORKER; ++} ++ ++static inline int au_wkq_wait(au_wkq_func_t func, void *args) ++{ ++ return au_wkq_do_wait(AuWkq_WAIT, func, args); ++} ++ ++static inline void au_nwt_done(struct au_nowait_tasks *nwt) ++{ ++ if (atomic_dec_and_test(&nwt->nw_len)) ++ wake_up_all(&nwt->nw_wq); ++} ++ ++static inline int au_nwt_flush(struct au_nowait_tasks *nwt) ++{ ++ wait_event(nwt->nw_wq, !atomic_read(&nwt->nw_len)); ++ return 0; ++} ++ ++#endif /* __KERNEL__ */ ++#endif /* __AUFS_WKQ_H__ */ +diff -Nurp linux-5.4/fs/aufs/xattr.c linux-5.4-aufs/fs/aufs/xattr.c +--- linux-5.4/fs/aufs/xattr.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/xattr.c 2019-11-28 01:25:59.069925618 +0200 +@@ -0,0 +1,343 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2014-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * handling xattr functions ++ */ ++ ++#include ++#include ++#include ++#include "aufs.h" ++ ++static int au_xattr_ignore(int err, char *name, unsigned int ignore_flags) ++{ ++ if (!ignore_flags) ++ goto out; ++ switch (err) { ++ case -ENOMEM: ++ case -EDQUOT: ++ goto out; ++ } ++ ++ if ((ignore_flags & AuBrAttr_ICEX) == AuBrAttr_ICEX) { ++ err = 0; ++ goto out; ++ } ++ ++#define cmp(brattr, prefix) do { \ ++ if (!strncmp(name, XATTR_##prefix##_PREFIX, \ ++ XATTR_##prefix##_PREFIX_LEN)) { \ ++ if (ignore_flags & AuBrAttr_ICEX_##brattr) \ ++ err = 0; \ ++ goto out; \ ++ } \ ++ } while (0) ++ ++ cmp(SEC, SECURITY); ++ cmp(SYS, SYSTEM); ++ cmp(TR, TRUSTED); ++ cmp(USR, USER); ++#undef cmp ++ ++ if (ignore_flags & AuBrAttr_ICEX_OTH) ++ err = 0; ++ ++out: ++ return err; ++} ++ ++static const int au_xattr_out_of_list = AuBrAttr_ICEX_OTH << 1; ++ ++static int au_do_cpup_xattr(struct dentry *h_dst, struct dentry *h_src, ++ char *name, char **buf, unsigned int ignore_flags, ++ unsigned int verbose) ++{ ++ int err; ++ ssize_t ssz; ++ struct inode *h_idst; ++ ++ ssz = vfs_getxattr_alloc(h_src, name, buf, 0, GFP_NOFS); ++ err = ssz; ++ if (unlikely(err <= 0)) { ++ if (err == -ENODATA ++ || (err == -EOPNOTSUPP ++ && ((ignore_flags & au_xattr_out_of_list) ++ || (au_test_nfs_noacl(d_inode(h_src)) ++ && (!strcmp(name, XATTR_NAME_POSIX_ACL_ACCESS) ++ || !strcmp(name, ++ XATTR_NAME_POSIX_ACL_DEFAULT)))) ++ )) ++ err = 0; ++ if (err && (verbose || au_debug_test())) ++ pr_err("%s, err %d\n", name, err); ++ goto out; ++ } ++ ++ /* unlock it temporary */ ++ h_idst = d_inode(h_dst); ++ inode_unlock(h_idst); ++ err = vfsub_setxattr(h_dst, name, *buf, ssz, /*flags*/0); ++ inode_lock_nested(h_idst, AuLsc_I_CHILD2); ++ if (unlikely(err)) { ++ if (verbose || au_debug_test()) ++ pr_err("%s, err %d\n", name, err); ++ err = au_xattr_ignore(err, name, ignore_flags); ++ } ++ ++out: ++ return err; ++} ++ ++int au_cpup_xattr(struct dentry *h_dst, struct dentry *h_src, int ignore_flags, ++ unsigned int verbose) ++{ ++ int err, unlocked, acl_access, acl_default; ++ ssize_t ssz; ++ struct inode *h_isrc, *h_idst; ++ char *value, *p, *o, *e; ++ ++ /* try stopping to update the source inode while we are referencing */ ++ /* there should not be the parent-child relationship between them */ ++ h_isrc = d_inode(h_src); ++ h_idst = d_inode(h_dst); ++ inode_unlock(h_idst); ++ inode_lock_shared_nested(h_isrc, AuLsc_I_CHILD); ++ inode_lock_nested(h_idst, AuLsc_I_CHILD2); ++ unlocked = 0; ++ ++ /* some filesystems don't list POSIX ACL, for example tmpfs */ ++ ssz = vfs_listxattr(h_src, NULL, 0); ++ err = ssz; ++ if (unlikely(err < 0)) { ++ AuTraceErr(err); ++ if (err == -ENODATA ++ || err == -EOPNOTSUPP) ++ err = 0; /* ignore */ ++ goto out; ++ } ++ ++ err = 0; ++ p = NULL; ++ o = NULL; ++ if (ssz) { ++ err = -ENOMEM; ++ p = kmalloc(ssz, GFP_NOFS); ++ o = p; ++ if (unlikely(!p)) ++ goto out; ++ err = vfs_listxattr(h_src, p, ssz); ++ } ++ inode_unlock_shared(h_isrc); ++ unlocked = 1; ++ AuDbg("err %d, ssz %zd\n", err, ssz); ++ if (unlikely(err < 0)) ++ goto out_free; ++ ++ err = 0; ++ e = p + ssz; ++ value = NULL; ++ acl_access = 0; ++ acl_default = 0; ++ while (!err && p < e) { ++ acl_access |= !strncmp(p, XATTR_NAME_POSIX_ACL_ACCESS, ++ sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1); ++ acl_default |= !strncmp(p, XATTR_NAME_POSIX_ACL_DEFAULT, ++ sizeof(XATTR_NAME_POSIX_ACL_DEFAULT) ++ - 1); ++ err = au_do_cpup_xattr(h_dst, h_src, p, &value, ignore_flags, ++ verbose); ++ p += strlen(p) + 1; ++ } ++ AuTraceErr(err); ++ ignore_flags |= au_xattr_out_of_list; ++ if (!err && !acl_access) { ++ err = au_do_cpup_xattr(h_dst, h_src, ++ XATTR_NAME_POSIX_ACL_ACCESS, &value, ++ ignore_flags, verbose); ++ AuTraceErr(err); ++ } ++ if (!err && !acl_default) { ++ err = au_do_cpup_xattr(h_dst, h_src, ++ XATTR_NAME_POSIX_ACL_DEFAULT, &value, ++ ignore_flags, verbose); ++ AuTraceErr(err); ++ } ++ ++ au_kfree_try_rcu(value); ++ ++out_free: ++ au_kfree_try_rcu(o); ++out: ++ if (!unlocked) ++ inode_unlock_shared(h_isrc); ++ AuTraceErr(err); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int au_smack_reentering(struct super_block *sb) ++{ ++#if IS_ENABLED(CONFIG_SECURITY_SMACK) ++ /* ++ * as a part of lookup, smack_d_instantiate() is called, and it calls ++ * i_op->getxattr(). ouch. ++ */ ++ return si_pid_test(sb); ++#else ++ return 0; ++#endif ++} ++ ++enum { ++ AU_XATTR_LIST, ++ AU_XATTR_GET ++}; ++ ++struct au_lgxattr { ++ int type; ++ union { ++ struct { ++ char *list; ++ size_t size; ++ } list; ++ struct { ++ const char *name; ++ void *value; ++ size_t size; ++ } get; ++ } u; ++}; ++ ++static ssize_t au_lgxattr(struct dentry *dentry, struct au_lgxattr *arg) ++{ ++ ssize_t err; ++ int reenter; ++ struct path h_path; ++ struct super_block *sb; ++ ++ sb = dentry->d_sb; ++ reenter = au_smack_reentering(sb); ++ if (!reenter) { ++ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM); ++ if (unlikely(err)) ++ goto out; ++ } ++ err = au_h_path_getattr(dentry, /*force*/1, &h_path, reenter); ++ if (unlikely(err)) ++ goto out_si; ++ if (unlikely(!h_path.dentry)) ++ /* illegally overlapped or something */ ++ goto out_di; /* pretending success */ ++ ++ /* always topmost entry only */ ++ switch (arg->type) { ++ case AU_XATTR_LIST: ++ err = vfs_listxattr(h_path.dentry, ++ arg->u.list.list, arg->u.list.size); ++ break; ++ case AU_XATTR_GET: ++ AuDebugOn(d_is_negative(h_path.dentry)); ++ err = vfs_getxattr(h_path.dentry, ++ arg->u.get.name, arg->u.get.value, ++ arg->u.get.size); ++ break; ++ } ++ ++out_di: ++ if (!reenter) ++ di_read_unlock(dentry, AuLock_IR); ++out_si: ++ if (!reenter) ++ si_read_unlock(sb); ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++ssize_t aufs_listxattr(struct dentry *dentry, char *list, size_t size) ++{ ++ struct au_lgxattr arg = { ++ .type = AU_XATTR_LIST, ++ .u.list = { ++ .list = list, ++ .size = size ++ }, ++ }; ++ ++ return au_lgxattr(dentry, &arg); ++} ++ ++static ssize_t au_getxattr(struct dentry *dentry, ++ struct inode *inode __maybe_unused, ++ const char *name, void *value, size_t size) ++{ ++ struct au_lgxattr arg = { ++ .type = AU_XATTR_GET, ++ .u.get = { ++ .name = name, ++ .value = value, ++ .size = size ++ }, ++ }; ++ ++ return au_lgxattr(dentry, &arg); ++} ++ ++static int au_setxattr(struct dentry *dentry, struct inode *inode, ++ const char *name, const void *value, size_t size, ++ int flags) ++{ ++ struct au_sxattr arg = { ++ .type = AU_XATTR_SET, ++ .u.set = { ++ .name = name, ++ .value = value, ++ .size = size, ++ .flags = flags ++ }, ++ }; ++ ++ return au_sxattr(dentry, inode, &arg); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int au_xattr_get(const struct xattr_handler *handler, ++ struct dentry *dentry, struct inode *inode, ++ const char *name, void *buffer, size_t size) ++{ ++ return au_getxattr(dentry, inode, name, buffer, size); ++} ++ ++static int au_xattr_set(const struct xattr_handler *handler, ++ struct dentry *dentry, struct inode *inode, ++ const char *name, const void *value, size_t size, ++ int flags) ++{ ++ return au_setxattr(dentry, inode, name, value, size, flags); ++} ++ ++static const struct xattr_handler au_xattr_handler = { ++ .name = "", ++ .prefix = "", ++ .get = au_xattr_get, ++ .set = au_xattr_set ++}; ++ ++static const struct xattr_handler *au_xattr_handlers[] = { ++#ifdef CONFIG_FS_POSIX_ACL ++ &posix_acl_access_xattr_handler, ++ &posix_acl_default_xattr_handler, ++#endif ++ &au_xattr_handler, /* must be last */ ++ NULL ++}; ++ ++void au_xattr_init(struct super_block *sb) ++{ ++ sb->s_xattr = au_xattr_handlers; ++} +diff -Nurp linux-5.4/fs/aufs/xino.c linux-5.4-aufs/fs/aufs/xino.c +--- linux-5.4/fs/aufs/xino.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/xino.c 2019-11-28 01:25:59.069925618 +0200 +@@ -0,0 +1,1952 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * external inode number translation table and bitmap ++ * ++ * things to consider ++ * - the lifetime ++ * + au_xino object ++ * + XINO files (xino, xib, xigen) ++ * + dynamic debugfs entries (xiN) ++ * + static debugfs entries (xib, xigen) ++ * + static sysfs entry (xi_path) ++ * - several entry points to handle them. ++ * + mount(2) without xino option (default) ++ * + mount(2) with xino option ++ * + mount(2) with noxino option ++ * + umount(2) ++ * + remount with add/del branches ++ * + remount with xino/noxino options ++ */ ++ ++#include ++#include ++#include "aufs.h" ++ ++static aufs_bindex_t sbr_find_shared(struct super_block *sb, aufs_bindex_t btop, ++ aufs_bindex_t bbot, ++ struct super_block *h_sb) ++{ ++ /* todo: try binary-search if the branches are many */ ++ for (; btop <= bbot; btop++) ++ if (h_sb == au_sbr_sb(sb, btop)) ++ return btop; ++ return -1; ++} ++ ++/* ++ * find another branch who is on the same filesystem of the specified ++ * branch{@btgt}. search until @bbot. ++ */ ++static aufs_bindex_t is_sb_shared(struct super_block *sb, aufs_bindex_t btgt, ++ aufs_bindex_t bbot) ++{ ++ aufs_bindex_t bindex; ++ struct super_block *tgt_sb; ++ ++ tgt_sb = au_sbr_sb(sb, btgt); ++ bindex = sbr_find_shared(sb, /*btop*/0, btgt - 1, tgt_sb); ++ if (bindex < 0) ++ bindex = sbr_find_shared(sb, btgt + 1, bbot, tgt_sb); ++ ++ return bindex; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * stop unnecessary notify events at creating xino files ++ */ ++ ++aufs_bindex_t au_xi_root(struct super_block *sb, struct dentry *dentry) ++{ ++ aufs_bindex_t bfound, bindex, bbot; ++ struct dentry *parent; ++ struct au_branch *br; ++ ++ bfound = -1; ++ parent = dentry->d_parent; /* safe d_parent access */ ++ bbot = au_sbbot(sb); ++ for (bindex = 0; bindex <= bbot; bindex++) { ++ br = au_sbr(sb, bindex); ++ if (au_br_dentry(br) == parent) { ++ bfound = bindex; ++ break; ++ } ++ } ++ ++ AuDbg("bfound b%d\n", bfound); ++ return bfound; ++} ++ ++struct au_xino_lock_dir { ++ struct au_hinode *hdir; ++ struct dentry *parent; ++ struct inode *dir; ++}; ++ ++static struct dentry *au_dget_parent_lock(struct dentry *dentry, ++ unsigned int lsc) ++{ ++ struct dentry *parent; ++ struct inode *dir; ++ ++ parent = dget_parent(dentry); ++ dir = d_inode(parent); ++ inode_lock_nested(dir, lsc); ++#if 0 /* it should not happen */ ++ spin_lock(&dentry->d_lock); ++ if (unlikely(dentry->d_parent != parent)) { ++ spin_unlock(&dentry->d_lock); ++ inode_unlock(dir); ++ dput(parent); ++ parent = NULL; ++ goto out; ++ } ++ spin_unlock(&dentry->d_lock); ++ ++out: ++#endif ++ return parent; ++} ++ ++static void au_xino_lock_dir(struct super_block *sb, struct path *xipath, ++ struct au_xino_lock_dir *ldir) ++{ ++ aufs_bindex_t bindex; ++ ++ ldir->hdir = NULL; ++ bindex = au_xi_root(sb, xipath->dentry); ++ if (bindex >= 0) { ++ /* rw branch root */ ++ ldir->hdir = au_hi(d_inode(sb->s_root), bindex); ++ au_hn_inode_lock_nested(ldir->hdir, AuLsc_I_PARENT); ++ } else { ++ /* other */ ++ ldir->parent = au_dget_parent_lock(xipath->dentry, ++ AuLsc_I_PARENT); ++ ldir->dir = d_inode(ldir->parent); ++ } ++} ++ ++static void au_xino_unlock_dir(struct au_xino_lock_dir *ldir) ++{ ++ if (ldir->hdir) ++ au_hn_inode_unlock(ldir->hdir); ++ else { ++ inode_unlock(ldir->dir); ++ dput(ldir->parent); ++ } ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * create and set a new xino file ++ */ ++struct file *au_xino_create(struct super_block *sb, char *fpath, int silent, ++ int wbrtop) ++{ ++ struct file *file; ++ struct dentry *h_parent, *d; ++ struct inode *h_dir, *inode; ++ int err; ++ static DEFINE_MUTEX(mtx); ++ ++ /* ++ * at mount-time, and the xino file is the default path, ++ * hnotify is disabled so we have no notify events to ignore. ++ * when a user specified the xino, we cannot get au_hdir to be ignored. ++ */ ++ if (!wbrtop) ++ mutex_lock(&mtx); ++ file = vfsub_filp_open(fpath, O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE ++ /* | __FMODE_NONOTIFY */, ++ 0666); ++ if (IS_ERR(file)) { ++ if (!wbrtop) ++ mutex_unlock(&mtx); ++ if (!silent) ++ pr_err("open %s(%ld)\n", fpath, PTR_ERR(file)); ++ return file; ++ } ++ ++ /* keep file count */ ++ err = 0; ++ d = file->f_path.dentry; ++ h_parent = au_dget_parent_lock(d, AuLsc_I_PARENT); ++ if (!wbrtop) ++ mutex_unlock(&mtx); ++ /* mnt_want_write() is unnecessary here */ ++ h_dir = d_inode(h_parent); ++ inode = file_inode(file); ++ /* no delegation since it is just created */ ++ if (inode->i_nlink) ++ err = vfsub_unlink(h_dir, &file->f_path, /*delegated*/NULL, ++ /*force*/0); ++ inode_unlock(h_dir); ++ dput(h_parent); ++ if (unlikely(err)) { ++ if (!silent) ++ pr_err("unlink %s(%d)\n", fpath, err); ++ goto out; ++ } ++ ++ err = -EINVAL; ++ if (unlikely(sb == d->d_sb)) { ++ if (!silent) ++ pr_err("%s must be outside\n", fpath); ++ goto out; ++ } ++ if (unlikely(au_test_fs_bad_xino(d->d_sb))) { ++ if (!silent) ++ pr_err("xino doesn't support %s(%s)\n", ++ fpath, au_sbtype(d->d_sb)); ++ goto out; ++ } ++ return file; /* success */ ++ ++out: ++ fput(file); ++ file = ERR_PTR(err); ++ return file; ++} ++ ++/* ++ * create a new xinofile at the same place/path as @base. ++ */ ++struct file *au_xino_create2(struct super_block *sb, struct path *base, ++ struct file *copy_src) ++{ ++ struct file *file; ++ struct dentry *dentry, *parent; ++ struct inode *dir, *delegated; ++ struct qstr *name; ++ struct path path; ++ int err, do_unlock; ++ struct au_xino_lock_dir ldir; ++ ++ do_unlock = 1; ++ au_xino_lock_dir(sb, base, &ldir); ++ dentry = base->dentry; ++ parent = dentry->d_parent; /* dir inode is locked */ ++ dir = d_inode(parent); ++ IMustLock(dir); ++ ++ name = &dentry->d_name; ++ path.dentry = vfsub_lookup_one_len(name->name, parent, name->len); ++ if (IS_ERR(path.dentry)) { ++ file = (void *)path.dentry; ++ pr_err("%pd lookup err %ld\n", dentry, PTR_ERR(path.dentry)); ++ goto out; ++ } ++ ++ /* no need to mnt_want_write() since we call dentry_open() later */ ++ err = vfs_create(dir, path.dentry, 0666, NULL); ++ if (unlikely(err)) { ++ file = ERR_PTR(err); ++ pr_err("%pd create err %d\n", dentry, err); ++ goto out_dput; ++ } ++ ++ path.mnt = base->mnt; ++ file = vfsub_dentry_open(&path, ++ O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE ++ /* | __FMODE_NONOTIFY */); ++ if (IS_ERR(file)) { ++ pr_err("%pd open err %ld\n", dentry, PTR_ERR(file)); ++ goto out_dput; ++ } ++ ++ delegated = NULL; ++ err = vfsub_unlink(dir, &file->f_path, &delegated, /*force*/0); ++ au_xino_unlock_dir(&ldir); ++ do_unlock = 0; ++ if (unlikely(err == -EWOULDBLOCK)) { ++ pr_warn("cannot retry for NFSv4 delegation" ++ " for an internal unlink\n"); ++ iput(delegated); ++ } ++ if (unlikely(err)) { ++ pr_err("%pd unlink err %d\n", dentry, err); ++ goto out_fput; ++ } ++ ++ if (copy_src) { ++ /* no one can touch copy_src xino */ ++ err = au_copy_file(file, copy_src, vfsub_f_size_read(copy_src)); ++ if (unlikely(err)) { ++ pr_err("%pd copy err %d\n", dentry, err); ++ goto out_fput; ++ } ++ } ++ goto out_dput; /* success */ ++ ++out_fput: ++ fput(file); ++ file = ERR_PTR(err); ++out_dput: ++ dput(path.dentry); ++out: ++ if (do_unlock) ++ au_xino_unlock_dir(&ldir); ++ return file; ++} ++ ++struct file *au_xino_file1(struct au_xino *xi) ++{ ++ struct file *file; ++ unsigned int u, nfile; ++ ++ file = NULL; ++ nfile = xi->xi_nfile; ++ for (u = 0; u < nfile; u++) { ++ file = xi->xi_file[u]; ++ if (file) ++ break; ++ } ++ ++ return file; ++} ++ ++static int au_xino_file_set(struct au_xino *xi, int idx, struct file *file) ++{ ++ int err; ++ struct file *f; ++ void *p; ++ ++ if (file) ++ get_file(file); ++ ++ err = 0; ++ f = NULL; ++ if (idx < xi->xi_nfile) { ++ f = xi->xi_file[idx]; ++ if (f) ++ fput(f); ++ } else { ++ p = au_kzrealloc(xi->xi_file, ++ sizeof(*xi->xi_file) * xi->xi_nfile, ++ sizeof(*xi->xi_file) * (idx + 1), ++ GFP_NOFS, /*may_shrink*/0); ++ if (p) { ++ MtxMustLock(&xi->xi_mtx); ++ xi->xi_file = p; ++ xi->xi_nfile = idx + 1; ++ } else { ++ err = -ENOMEM; ++ if (file) ++ fput(file); ++ goto out; ++ } ++ } ++ xi->xi_file[idx] = file; ++ ++out: ++ return err; ++} ++ ++/* ++ * if @xinew->xi is not set, then create new xigen file. ++ */ ++struct file *au_xi_new(struct super_block *sb, struct au_xi_new *xinew) ++{ ++ struct file *file; ++ int err; ++ ++ SiMustAnyLock(sb); ++ ++ file = au_xino_create2(sb, xinew->base, xinew->copy_src); ++ if (IS_ERR(file)) { ++ err = PTR_ERR(file); ++ pr_err("%s[%d], err %d\n", ++ xinew->xi ? "xino" : "xigen", ++ xinew->idx, err); ++ goto out; ++ } ++ ++ if (xinew->xi) ++ err = au_xino_file_set(xinew->xi, xinew->idx, file); ++ else { ++ BUG(); ++ /* todo: make xigen file an array */ ++ /* err = au_xigen_file_set(sb, xinew->idx, file); */ ++ } ++ fput(file); ++ if (unlikely(err)) ++ file = ERR_PTR(err); ++ ++out: ++ return file; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * truncate xino files ++ */ ++static int au_xino_do_trunc(struct super_block *sb, aufs_bindex_t bindex, ++ int idx, struct kstatfs *st) ++{ ++ int err; ++ blkcnt_t blocks; ++ struct file *file, *new_xino; ++ struct au_xi_new xinew = { ++ .idx = idx ++ }; ++ ++ err = 0; ++ xinew.xi = au_sbr(sb, bindex)->br_xino; ++ file = au_xino_file(xinew.xi, idx); ++ if (!file) ++ goto out; ++ ++ xinew.base = &file->f_path; ++ err = vfs_statfs(xinew.base, st); ++ if (unlikely(err)) { ++ AuErr1("statfs err %d, ignored\n", err); ++ err = 0; ++ goto out; ++ } ++ ++ blocks = file_inode(file)->i_blocks; ++ pr_info("begin truncating xino(b%d-%d), ib%llu, %llu/%llu free blks\n", ++ bindex, idx, (u64)blocks, st->f_bfree, st->f_blocks); ++ ++ xinew.copy_src = file; ++ new_xino = au_xi_new(sb, &xinew); ++ if (IS_ERR(new_xino)) { ++ err = PTR_ERR(new_xino); ++ pr_err("xino(b%d-%d), err %d, ignored\n", bindex, idx, err); ++ goto out; ++ } ++ ++ err = vfs_statfs(&new_xino->f_path, st); ++ if (!err) ++ pr_info("end truncating xino(b%d-%d), ib%llu, %llu/%llu free blks\n", ++ bindex, idx, (u64)file_inode(new_xino)->i_blocks, ++ st->f_bfree, st->f_blocks); ++ else { ++ AuErr1("statfs err %d, ignored\n", err); ++ err = 0; ++ } ++ ++out: ++ return err; ++} ++ ++int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex, int idx_begin) ++{ ++ int err, i; ++ unsigned long jiffy; ++ aufs_bindex_t bbot; ++ struct kstatfs *st; ++ struct au_branch *br; ++ struct au_xino *xi; ++ ++ err = -ENOMEM; ++ st = kmalloc(sizeof(*st), GFP_NOFS); ++ if (unlikely(!st)) ++ goto out; ++ ++ err = -EINVAL; ++ bbot = au_sbbot(sb); ++ if (unlikely(bindex < 0 || bbot < bindex)) ++ goto out_st; ++ ++ err = 0; ++ jiffy = jiffies; ++ br = au_sbr(sb, bindex); ++ xi = br->br_xino; ++ for (i = idx_begin; !err && i < xi->xi_nfile; i++) ++ err = au_xino_do_trunc(sb, bindex, i, st); ++ if (!err) ++ au_sbi(sb)->si_xino_jiffy = jiffy; ++ ++out_st: ++ au_kfree_rcu(st); ++out: ++ return err; ++} ++ ++struct xino_do_trunc_args { ++ struct super_block *sb; ++ struct au_branch *br; ++ int idx; ++}; ++ ++static void xino_do_trunc(void *_args) ++{ ++ struct xino_do_trunc_args *args = _args; ++ struct super_block *sb; ++ struct au_branch *br; ++ struct inode *dir; ++ int err, idx; ++ aufs_bindex_t bindex; ++ ++ err = 0; ++ sb = args->sb; ++ dir = d_inode(sb->s_root); ++ br = args->br; ++ idx = args->idx; ++ ++ si_noflush_write_lock(sb); ++ ii_read_lock_parent(dir); ++ bindex = au_br_index(sb, br->br_id); ++ err = au_xino_trunc(sb, bindex, idx); ++ ii_read_unlock(dir); ++ if (unlikely(err)) ++ pr_warn("err b%d, (%d)\n", bindex, err); ++ atomic_dec(&br->br_xino->xi_truncating); ++ au_lcnt_dec(&br->br_count); ++ si_write_unlock(sb); ++ au_nwt_done(&au_sbi(sb)->si_nowait); ++ au_kfree_rcu(args); ++} ++ ++/* ++ * returns the index in the xi_file array whose corresponding file is necessary ++ * to truncate, or -1 which means no need to truncate. ++ */ ++static int xino_trunc_test(struct super_block *sb, struct au_branch *br) ++{ ++ int err; ++ unsigned int u; ++ struct kstatfs st; ++ struct au_sbinfo *sbinfo; ++ struct au_xino *xi; ++ struct file *file; ++ ++ /* todo: si_xino_expire and the ratio should be customizable */ ++ sbinfo = au_sbi(sb); ++ if (time_before(jiffies, ++ sbinfo->si_xino_jiffy + sbinfo->si_xino_expire)) ++ return -1; ++ ++ /* truncation border */ ++ xi = br->br_xino; ++ for (u = 0; u < xi->xi_nfile; u++) { ++ file = au_xino_file(xi, u); ++ if (!file) ++ continue; ++ ++ err = vfs_statfs(&file->f_path, &st); ++ if (unlikely(err)) { ++ AuErr1("statfs err %d, ignored\n", err); ++ return -1; ++ } ++ if (div64_u64(st.f_bfree * 100, st.f_blocks) ++ >= AUFS_XINO_DEF_TRUNC) ++ return u; ++ } ++ ++ return -1; ++} ++ ++static void xino_try_trunc(struct super_block *sb, struct au_branch *br) ++{ ++ int idx; ++ struct xino_do_trunc_args *args; ++ int wkq_err; ++ ++ idx = xino_trunc_test(sb, br); ++ if (idx < 0) ++ return; ++ ++ if (atomic_inc_return(&br->br_xino->xi_truncating) > 1) ++ goto out; ++ ++ /* lock and kfree() will be called in trunc_xino() */ ++ args = kmalloc(sizeof(*args), GFP_NOFS); ++ if (unlikely(!args)) { ++ AuErr1("no memory\n"); ++ goto out; ++ } ++ ++ au_lcnt_inc(&br->br_count); ++ args->sb = sb; ++ args->br = br; ++ args->idx = idx; ++ wkq_err = au_wkq_nowait(xino_do_trunc, args, sb, /*flags*/0); ++ if (!wkq_err) ++ return; /* success */ ++ ++ pr_err("wkq %d\n", wkq_err); ++ au_lcnt_dec(&br->br_count); ++ au_kfree_rcu(args); ++ ++out: ++ atomic_dec(&br->br_xino->xi_truncating); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++struct au_xi_calc { ++ int idx; ++ loff_t pos; ++}; ++ ++static void au_xi_calc(struct super_block *sb, ino_t h_ino, ++ struct au_xi_calc *calc) ++{ ++ loff_t maxent; ++ ++ maxent = au_xi_maxent(sb); ++ calc->idx = div64_u64_rem(h_ino, maxent, &calc->pos); ++ calc->pos *= sizeof(ino_t); ++} ++ ++static int au_xino_do_new_async(struct super_block *sb, struct au_branch *br, ++ struct au_xi_calc *calc) ++{ ++ int err; ++ struct file *file; ++ struct au_xino *xi = br->br_xino; ++ struct au_xi_new xinew = { ++ .xi = xi ++ }; ++ ++ SiMustAnyLock(sb); ++ ++ err = 0; ++ if (!xi) ++ goto out; ++ ++ mutex_lock(&xi->xi_mtx); ++ file = au_xino_file(xi, calc->idx); ++ if (file) ++ goto out_mtx; ++ ++ file = au_xino_file(xi, /*idx*/-1); ++ AuDebugOn(!file); ++ xinew.idx = calc->idx; ++ xinew.base = &file->f_path; ++ /* xinew.copy_src = NULL; */ ++ file = au_xi_new(sb, &xinew); ++ if (IS_ERR(file)) ++ err = PTR_ERR(file); ++ ++out_mtx: ++ mutex_unlock(&xi->xi_mtx); ++out: ++ return err; ++} ++ ++struct au_xino_do_new_async_args { ++ struct super_block *sb; ++ struct au_branch *br; ++ struct au_xi_calc calc; ++ ino_t ino; ++}; ++ ++struct au_xi_writing { ++ struct hlist_bl_node node; ++ ino_t h_ino, ino; ++}; ++ ++static int au_xino_do_write(vfs_writef_t write, struct file *file, ++ struct au_xi_calc *calc, ino_t ino); ++ ++static void au_xino_call_do_new_async(void *args) ++{ ++ struct au_xino_do_new_async_args *a = args; ++ struct au_branch *br; ++ struct super_block *sb; ++ struct au_sbinfo *sbi; ++ struct inode *root; ++ struct file *file; ++ struct au_xi_writing *del, *p; ++ struct hlist_bl_head *hbl; ++ struct hlist_bl_node *pos; ++ int err; ++ ++ br = a->br; ++ sb = a->sb; ++ sbi = au_sbi(sb); ++ si_noflush_read_lock(sb); ++ root = d_inode(sb->s_root); ++ ii_read_lock_child(root); ++ err = au_xino_do_new_async(sb, br, &a->calc); ++ if (unlikely(err)) { ++ AuIOErr("err %d\n", err); ++ goto out; ++ } ++ ++ file = au_xino_file(br->br_xino, a->calc.idx); ++ AuDebugOn(!file); ++ err = au_xino_do_write(sbi->si_xwrite, file, &a->calc, a->ino); ++ if (unlikely(err)) { ++ AuIOErr("err %d\n", err); ++ goto out; ++ } ++ ++ del = NULL; ++ hbl = &br->br_xino->xi_writing; ++ hlist_bl_lock(hbl); ++ au_hbl_for_each(pos, hbl) { ++ p = container_of(pos, struct au_xi_writing, node); ++ if (p->ino == a->ino) { ++ del = p; ++ hlist_bl_del(&p->node); ++ break; ++ } ++ } ++ hlist_bl_unlock(hbl); ++ au_kfree_rcu(del); ++ ++out: ++ au_lcnt_dec(&br->br_count); ++ ii_read_unlock(root); ++ si_read_unlock(sb); ++ au_nwt_done(&sbi->si_nowait); ++ au_kfree_rcu(a); ++} ++ ++/* ++ * create a new xino file asynchronously ++ */ ++static int au_xino_new_async(struct super_block *sb, struct au_branch *br, ++ struct au_xi_calc *calc, ino_t ino) ++{ ++ int err; ++ struct au_xino_do_new_async_args *arg; ++ ++ err = -ENOMEM; ++ arg = kmalloc(sizeof(*arg), GFP_NOFS); ++ if (unlikely(!arg)) ++ goto out; ++ ++ arg->sb = sb; ++ arg->br = br; ++ arg->calc = *calc; ++ arg->ino = ino; ++ au_lcnt_inc(&br->br_count); ++ err = au_wkq_nowait(au_xino_call_do_new_async, arg, sb, AuWkq_NEST); ++ if (unlikely(err)) { ++ pr_err("wkq %d\n", err); ++ au_lcnt_dec(&br->br_count); ++ au_kfree_rcu(arg); ++ } ++ ++out: ++ return err; ++} ++ ++/* ++ * read @ino from xinofile for the specified branch{@sb, @bindex} ++ * at the position of @h_ino. ++ */ ++int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, ++ ino_t *ino) ++{ ++ int err; ++ ssize_t sz; ++ struct au_xi_calc calc; ++ struct au_sbinfo *sbinfo; ++ struct file *file; ++ struct au_xino *xi; ++ struct hlist_bl_head *hbl; ++ struct hlist_bl_node *pos; ++ struct au_xi_writing *p; ++ ++ *ino = 0; ++ if (!au_opt_test(au_mntflags(sb), XINO)) ++ return 0; /* no xino */ ++ ++ err = 0; ++ au_xi_calc(sb, h_ino, &calc); ++ xi = au_sbr(sb, bindex)->br_xino; ++ file = au_xino_file(xi, calc.idx); ++ if (!file) { ++ hbl = &xi->xi_writing; ++ hlist_bl_lock(hbl); ++ au_hbl_for_each(pos, hbl) { ++ p = container_of(pos, struct au_xi_writing, node); ++ if (p->h_ino == h_ino) { ++ AuDbg("hi%llu, i%llu, found\n", ++ (u64)p->h_ino, (u64)p->ino); ++ *ino = p->ino; ++ break; ++ } ++ } ++ hlist_bl_unlock(hbl); ++ return 0; ++ } else if (vfsub_f_size_read(file) < calc.pos + sizeof(*ino)) ++ return 0; /* no xino */ ++ ++ sbinfo = au_sbi(sb); ++ sz = xino_fread(sbinfo->si_xread, file, ino, sizeof(*ino), &calc.pos); ++ if (sz == sizeof(*ino)) ++ return 0; /* success */ ++ ++ err = sz; ++ if (unlikely(sz >= 0)) { ++ err = -EIO; ++ AuIOErr("xino read error (%zd)\n", sz); ++ } ++ return err; ++} ++ ++static int au_xino_do_write(vfs_writef_t write, struct file *file, ++ struct au_xi_calc *calc, ino_t ino) ++{ ++ ssize_t sz; ++ ++ sz = xino_fwrite(write, file, &ino, sizeof(ino), &calc->pos); ++ if (sz == sizeof(ino)) ++ return 0; /* success */ ++ ++ AuIOErr("write failed (%zd)\n", sz); ++ return -EIO; ++} ++ ++/* ++ * write @ino to the xinofile for the specified branch{@sb, @bindex} ++ * at the position of @h_ino. ++ * even if @ino is zero, it is written to the xinofile and means no entry. ++ * if the size of the xino file on a specific filesystem exceeds the watermark, ++ * try truncating it. ++ */ ++int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, ++ ino_t ino) ++{ ++ int err; ++ unsigned int mnt_flags; ++ struct au_xi_calc calc; ++ struct file *file; ++ struct au_branch *br; ++ struct au_xino *xi; ++ struct au_xi_writing *p; ++ ++ SiMustAnyLock(sb); ++ ++ mnt_flags = au_mntflags(sb); ++ if (!au_opt_test(mnt_flags, XINO)) ++ return 0; ++ ++ au_xi_calc(sb, h_ino, &calc); ++ br = au_sbr(sb, bindex); ++ xi = br->br_xino; ++ file = au_xino_file(xi, calc.idx); ++ if (!file) { ++ /* store the inum pair into the list */ ++ p = kmalloc(sizeof(*p), GFP_NOFS | __GFP_NOFAIL); ++ p->h_ino = h_ino; ++ p->ino = ino; ++ au_hbl_add(&p->node, &xi->xi_writing); ++ ++ /* create and write a new xino file asynchronously */ ++ err = au_xino_new_async(sb, br, &calc, ino); ++ if (!err) ++ return 0; /* success */ ++ goto out; ++ } ++ ++ err = au_xino_do_write(au_sbi(sb)->si_xwrite, file, &calc, ino); ++ if (!err) { ++ br = au_sbr(sb, bindex); ++ if (au_opt_test(mnt_flags, TRUNC_XINO) ++ && au_test_fs_trunc_xino(au_br_sb(br))) ++ xino_try_trunc(sb, br); ++ return 0; /* success */ ++ } ++ ++out: ++ AuIOErr("write failed (%d)\n", err); ++ return -EIO; ++} ++ ++static ssize_t xino_fread_wkq(vfs_readf_t func, struct file *file, void *buf, ++ size_t size, loff_t *pos); ++ ++/* todo: unnecessary to support mmap_sem since kernel-space? */ ++ssize_t xino_fread(vfs_readf_t func, struct file *file, void *kbuf, size_t size, ++ loff_t *pos) ++{ ++ ssize_t err; ++ mm_segment_t oldfs; ++ union { ++ void *k; ++ char __user *u; ++ } buf; ++ int i; ++ const int prevent_endless = 10; ++ ++ i = 0; ++ buf.k = kbuf; ++ oldfs = get_fs(); ++ set_fs(KERNEL_DS); ++ do { ++ err = func(file, buf.u, size, pos); ++ if (err == -EINTR ++ && !au_wkq_test() ++ && fatal_signal_pending(current)) { ++ set_fs(oldfs); ++ err = xino_fread_wkq(func, file, kbuf, size, pos); ++ BUG_ON(err == -EINTR); ++ oldfs = get_fs(); ++ set_fs(KERNEL_DS); ++ } ++ } while (i++ < prevent_endless ++ && (err == -EAGAIN || err == -EINTR)); ++ set_fs(oldfs); ++ ++#if 0 /* reserved for future use */ ++ if (err > 0) ++ fsnotify_access(file->f_path.dentry); ++#endif ++ ++ return err; ++} ++ ++struct xino_fread_args { ++ ssize_t *errp; ++ vfs_readf_t func; ++ struct file *file; ++ void *buf; ++ size_t size; ++ loff_t *pos; ++}; ++ ++static void call_xino_fread(void *args) ++{ ++ struct xino_fread_args *a = args; ++ *a->errp = xino_fread(a->func, a->file, a->buf, a->size, a->pos); ++} ++ ++static ssize_t xino_fread_wkq(vfs_readf_t func, struct file *file, void *buf, ++ size_t size, loff_t *pos) ++{ ++ ssize_t err; ++ int wkq_err; ++ struct xino_fread_args args = { ++ .errp = &err, ++ .func = func, ++ .file = file, ++ .buf = buf, ++ .size = size, ++ .pos = pos ++ }; ++ ++ wkq_err = au_wkq_wait(call_xino_fread, &args); ++ if (unlikely(wkq_err)) ++ err = wkq_err; ++ ++ return err; ++} ++ ++static ssize_t xino_fwrite_wkq(vfs_writef_t func, struct file *file, void *buf, ++ size_t size, loff_t *pos); ++ ++static ssize_t do_xino_fwrite(vfs_writef_t func, struct file *file, void *kbuf, ++ size_t size, loff_t *pos) ++{ ++ ssize_t err; ++ mm_segment_t oldfs; ++ union { ++ void *k; ++ const char __user *u; ++ } buf; ++ int i; ++ const int prevent_endless = 10; ++ ++ i = 0; ++ buf.k = kbuf; ++ oldfs = get_fs(); ++ set_fs(KERNEL_DS); ++ do { ++ err = func(file, buf.u, size, pos); ++ if (err == -EINTR ++ && !au_wkq_test() ++ && fatal_signal_pending(current)) { ++ set_fs(oldfs); ++ err = xino_fwrite_wkq(func, file, kbuf, size, pos); ++ BUG_ON(err == -EINTR); ++ oldfs = get_fs(); ++ set_fs(KERNEL_DS); ++ } ++ } while (i++ < prevent_endless ++ && (err == -EAGAIN || err == -EINTR)); ++ set_fs(oldfs); ++ ++#if 0 /* reserved for future use */ ++ if (err > 0) ++ fsnotify_modify(file->f_path.dentry); ++#endif ++ ++ return err; ++} ++ ++struct do_xino_fwrite_args { ++ ssize_t *errp; ++ vfs_writef_t func; ++ struct file *file; ++ void *buf; ++ size_t size; ++ loff_t *pos; ++}; ++ ++static void call_do_xino_fwrite(void *args) ++{ ++ struct do_xino_fwrite_args *a = args; ++ *a->errp = do_xino_fwrite(a->func, a->file, a->buf, a->size, a->pos); ++} ++ ++static ssize_t xino_fwrite_wkq(vfs_writef_t func, struct file *file, void *buf, ++ size_t size, loff_t *pos) ++{ ++ ssize_t err; ++ int wkq_err; ++ struct do_xino_fwrite_args args = { ++ .errp = &err, ++ .func = func, ++ .file = file, ++ .buf = buf, ++ .size = size, ++ .pos = pos ++ }; ++ ++ /* ++ * it breaks RLIMIT_FSIZE and normal user's limit, ++ * users should care about quota and real 'filesystem full.' ++ */ ++ wkq_err = au_wkq_wait(call_do_xino_fwrite, &args); ++ if (unlikely(wkq_err)) ++ err = wkq_err; ++ ++ return err; ++} ++ ++ssize_t xino_fwrite(vfs_writef_t func, struct file *file, void *buf, ++ size_t size, loff_t *pos) ++{ ++ ssize_t err; ++ ++ if (rlimit(RLIMIT_FSIZE) == RLIM_INFINITY) { ++ lockdep_off(); ++ err = do_xino_fwrite(func, file, buf, size, pos); ++ lockdep_on(); ++ } else { ++ lockdep_off(); ++ err = xino_fwrite_wkq(func, file, buf, size, pos); ++ lockdep_on(); ++ } ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * inode number bitmap ++ */ ++static const int page_bits = (int)PAGE_SIZE * BITS_PER_BYTE; ++static ino_t xib_calc_ino(unsigned long pindex, int bit) ++{ ++ ino_t ino; ++ ++ AuDebugOn(bit < 0 || page_bits <= bit); ++ ino = AUFS_FIRST_INO + pindex * page_bits + bit; ++ return ino; ++} ++ ++static void xib_calc_bit(ino_t ino, unsigned long *pindex, int *bit) ++{ ++ AuDebugOn(ino < AUFS_FIRST_INO); ++ ino -= AUFS_FIRST_INO; ++ *pindex = ino / page_bits; ++ *bit = ino % page_bits; ++} ++ ++static int xib_pindex(struct super_block *sb, unsigned long pindex) ++{ ++ int err; ++ loff_t pos; ++ ssize_t sz; ++ struct au_sbinfo *sbinfo; ++ struct file *xib; ++ unsigned long *p; ++ ++ sbinfo = au_sbi(sb); ++ MtxMustLock(&sbinfo->si_xib_mtx); ++ AuDebugOn(pindex > ULONG_MAX / PAGE_SIZE ++ || !au_opt_test(sbinfo->si_mntflags, XINO)); ++ ++ if (pindex == sbinfo->si_xib_last_pindex) ++ return 0; ++ ++ xib = sbinfo->si_xib; ++ p = sbinfo->si_xib_buf; ++ pos = sbinfo->si_xib_last_pindex; ++ pos *= PAGE_SIZE; ++ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos); ++ if (unlikely(sz != PAGE_SIZE)) ++ goto out; ++ ++ pos = pindex; ++ pos *= PAGE_SIZE; ++ if (vfsub_f_size_read(xib) >= pos + PAGE_SIZE) ++ sz = xino_fread(sbinfo->si_xread, xib, p, PAGE_SIZE, &pos); ++ else { ++ memset(p, 0, PAGE_SIZE); ++ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos); ++ } ++ if (sz == PAGE_SIZE) { ++ sbinfo->si_xib_last_pindex = pindex; ++ return 0; /* success */ ++ } ++ ++out: ++ AuIOErr1("write failed (%zd)\n", sz); ++ err = sz; ++ if (sz >= 0) ++ err = -EIO; ++ return err; ++} ++ ++static void au_xib_clear_bit(struct inode *inode) ++{ ++ int err, bit; ++ unsigned long pindex; ++ struct super_block *sb; ++ struct au_sbinfo *sbinfo; ++ ++ AuDebugOn(inode->i_nlink); ++ ++ sb = inode->i_sb; ++ xib_calc_bit(inode->i_ino, &pindex, &bit); ++ AuDebugOn(page_bits <= bit); ++ sbinfo = au_sbi(sb); ++ mutex_lock(&sbinfo->si_xib_mtx); ++ err = xib_pindex(sb, pindex); ++ if (!err) { ++ clear_bit(bit, sbinfo->si_xib_buf); ++ sbinfo->si_xib_next_bit = bit; ++ } ++ mutex_unlock(&sbinfo->si_xib_mtx); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * truncate a xino bitmap file ++ */ ++ ++/* todo: slow */ ++static int do_xib_restore(struct super_block *sb, struct file *file, void *page) ++{ ++ int err, bit; ++ ssize_t sz; ++ unsigned long pindex; ++ loff_t pos, pend; ++ struct au_sbinfo *sbinfo; ++ vfs_readf_t func; ++ ino_t *ino; ++ unsigned long *p; ++ ++ err = 0; ++ sbinfo = au_sbi(sb); ++ MtxMustLock(&sbinfo->si_xib_mtx); ++ p = sbinfo->si_xib_buf; ++ func = sbinfo->si_xread; ++ pend = vfsub_f_size_read(file); ++ pos = 0; ++ while (pos < pend) { ++ sz = xino_fread(func, file, page, PAGE_SIZE, &pos); ++ err = sz; ++ if (unlikely(sz <= 0)) ++ goto out; ++ ++ err = 0; ++ for (ino = page; sz > 0; ino++, sz -= sizeof(ino)) { ++ if (unlikely(*ino < AUFS_FIRST_INO)) ++ continue; ++ ++ xib_calc_bit(*ino, &pindex, &bit); ++ AuDebugOn(page_bits <= bit); ++ err = xib_pindex(sb, pindex); ++ if (!err) ++ set_bit(bit, p); ++ else ++ goto out; ++ } ++ } ++ ++out: ++ return err; ++} ++ ++static int xib_restore(struct super_block *sb) ++{ ++ int err, i; ++ unsigned int nfile; ++ aufs_bindex_t bindex, bbot; ++ void *page; ++ struct au_branch *br; ++ struct au_xino *xi; ++ struct file *file; ++ ++ err = -ENOMEM; ++ page = (void *)__get_free_page(GFP_NOFS); ++ if (unlikely(!page)) ++ goto out; ++ ++ err = 0; ++ bbot = au_sbbot(sb); ++ for (bindex = 0; !err && bindex <= bbot; bindex++) ++ if (!bindex || is_sb_shared(sb, bindex, bindex - 1) < 0) { ++ br = au_sbr(sb, bindex); ++ xi = br->br_xino; ++ nfile = xi->xi_nfile; ++ for (i = 0; i < nfile; i++) { ++ file = au_xino_file(xi, i); ++ if (file) ++ err = do_xib_restore(sb, file, page); ++ } ++ } else ++ AuDbg("skip shared b%d\n", bindex); ++ free_page((unsigned long)page); ++ ++out: ++ return err; ++} ++ ++int au_xib_trunc(struct super_block *sb) ++{ ++ int err; ++ ssize_t sz; ++ loff_t pos; ++ struct au_sbinfo *sbinfo; ++ unsigned long *p; ++ struct file *file; ++ ++ SiMustWriteLock(sb); ++ ++ err = 0; ++ sbinfo = au_sbi(sb); ++ if (!au_opt_test(sbinfo->si_mntflags, XINO)) ++ goto out; ++ ++ file = sbinfo->si_xib; ++ if (vfsub_f_size_read(file) <= PAGE_SIZE) ++ goto out; ++ ++ file = au_xino_create2(sb, &sbinfo->si_xib->f_path, NULL); ++ err = PTR_ERR(file); ++ if (IS_ERR(file)) ++ goto out; ++ fput(sbinfo->si_xib); ++ sbinfo->si_xib = file; ++ ++ p = sbinfo->si_xib_buf; ++ memset(p, 0, PAGE_SIZE); ++ pos = 0; ++ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xib, p, PAGE_SIZE, &pos); ++ if (unlikely(sz != PAGE_SIZE)) { ++ err = sz; ++ AuIOErr("err %d\n", err); ++ if (sz >= 0) ++ err = -EIO; ++ goto out; ++ } ++ ++ mutex_lock(&sbinfo->si_xib_mtx); ++ /* mnt_want_write() is unnecessary here */ ++ err = xib_restore(sb); ++ mutex_unlock(&sbinfo->si_xib_mtx); ++ ++out: ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++struct au_xino *au_xino_alloc(unsigned int nfile) ++{ ++ struct au_xino *xi; ++ ++ xi = kzalloc(sizeof(*xi), GFP_NOFS); ++ if (unlikely(!xi)) ++ goto out; ++ xi->xi_nfile = nfile; ++ xi->xi_file = kcalloc(nfile, sizeof(*xi->xi_file), GFP_NOFS); ++ if (unlikely(!xi->xi_file)) ++ goto out_free; ++ ++ xi->xi_nondir.total = 8; /* initial size */ ++ xi->xi_nondir.array = kcalloc(xi->xi_nondir.total, sizeof(ino_t), ++ GFP_NOFS); ++ if (unlikely(!xi->xi_nondir.array)) ++ goto out_file; ++ ++ spin_lock_init(&xi->xi_nondir.spin); ++ init_waitqueue_head(&xi->xi_nondir.wqh); ++ mutex_init(&xi->xi_mtx); ++ INIT_HLIST_BL_HEAD(&xi->xi_writing); ++ atomic_set(&xi->xi_truncating, 0); ++ kref_init(&xi->xi_kref); ++ goto out; /* success */ ++ ++out_file: ++ au_kfree_try_rcu(xi->xi_file); ++out_free: ++ au_kfree_rcu(xi); ++ xi = NULL; ++out: ++ return xi; ++} ++ ++static int au_xino_init(struct au_branch *br, int idx, struct file *file) ++{ ++ int err; ++ struct au_xino *xi; ++ ++ err = 0; ++ xi = au_xino_alloc(idx + 1); ++ if (unlikely(!xi)) { ++ err = -ENOMEM; ++ goto out; ++ } ++ ++ if (file) ++ get_file(file); ++ xi->xi_file[idx] = file; ++ AuDebugOn(br->br_xino); ++ br->br_xino = xi; ++ ++out: ++ return err; ++} ++ ++static void au_xino_release(struct kref *kref) ++{ ++ struct au_xino *xi; ++ int i; ++ unsigned long ul; ++ struct hlist_bl_head *hbl; ++ struct hlist_bl_node *pos, *n; ++ struct au_xi_writing *p; ++ ++ xi = container_of(kref, struct au_xino, xi_kref); ++ for (i = 0; i < xi->xi_nfile; i++) ++ if (xi->xi_file[i]) ++ fput(xi->xi_file[i]); ++ for (i = xi->xi_nondir.total - 1; i >= 0; i--) ++ AuDebugOn(xi->xi_nondir.array[i]); ++ mutex_destroy(&xi->xi_mtx); ++ hbl = &xi->xi_writing; ++ ul = au_hbl_count(hbl); ++ if (unlikely(ul)) { ++ pr_warn("xi_writing %lu\n", ul); ++ hlist_bl_lock(hbl); ++ hlist_bl_for_each_entry_safe (p, pos, n, hbl, node) { ++ hlist_bl_del(&p->node); ++ au_kfree_rcu(p); ++ } ++ hlist_bl_unlock(hbl); ++ } ++ au_kfree_try_rcu(xi->xi_file); ++ au_kfree_try_rcu(xi->xi_nondir.array); ++ au_kfree_rcu(xi); ++} ++ ++int au_xino_put(struct au_branch *br) ++{ ++ int ret; ++ struct au_xino *xi; ++ ++ ret = 0; ++ xi = br->br_xino; ++ if (xi) { ++ br->br_xino = NULL; ++ ret = kref_put(&xi->xi_kref, au_xino_release); ++ } ++ ++ return ret; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * xino mount option handlers ++ */ ++ ++/* xino bitmap */ ++static void xino_clear_xib(struct super_block *sb) ++{ ++ struct au_sbinfo *sbinfo; ++ ++ SiMustWriteLock(sb); ++ ++ sbinfo = au_sbi(sb); ++ /* unnecessary to clear sbinfo->si_xread and ->si_xwrite */ ++ if (sbinfo->si_xib) ++ fput(sbinfo->si_xib); ++ sbinfo->si_xib = NULL; ++ if (sbinfo->si_xib_buf) ++ free_page((unsigned long)sbinfo->si_xib_buf); ++ sbinfo->si_xib_buf = NULL; ++} ++ ++static int au_xino_set_xib(struct super_block *sb, struct path *path) ++{ ++ int err; ++ loff_t pos; ++ struct au_sbinfo *sbinfo; ++ struct file *file; ++ struct super_block *xi_sb; ++ ++ SiMustWriteLock(sb); ++ ++ sbinfo = au_sbi(sb); ++ file = au_xino_create2(sb, path, sbinfo->si_xib); ++ err = PTR_ERR(file); ++ if (IS_ERR(file)) ++ goto out; ++ if (sbinfo->si_xib) ++ fput(sbinfo->si_xib); ++ sbinfo->si_xib = file; ++ sbinfo->si_xread = vfs_readf(file); ++ sbinfo->si_xwrite = vfs_writef(file); ++ xi_sb = file_inode(file)->i_sb; ++ sbinfo->si_ximaxent = xi_sb->s_maxbytes; ++ if (unlikely(sbinfo->si_ximaxent < PAGE_SIZE)) { ++ err = -EIO; ++ pr_err("s_maxbytes(%llu) on %s is too small\n", ++ (u64)sbinfo->si_ximaxent, au_sbtype(xi_sb)); ++ goto out_unset; ++ } ++ sbinfo->si_ximaxent /= sizeof(ino_t); ++ ++ err = -ENOMEM; ++ if (!sbinfo->si_xib_buf) ++ sbinfo->si_xib_buf = (void *)get_zeroed_page(GFP_NOFS); ++ if (unlikely(!sbinfo->si_xib_buf)) ++ goto out_unset; ++ ++ sbinfo->si_xib_last_pindex = 0; ++ sbinfo->si_xib_next_bit = 0; ++ if (vfsub_f_size_read(file) < PAGE_SIZE) { ++ pos = 0; ++ err = xino_fwrite(sbinfo->si_xwrite, file, sbinfo->si_xib_buf, ++ PAGE_SIZE, &pos); ++ if (unlikely(err != PAGE_SIZE)) ++ goto out_free; ++ } ++ err = 0; ++ goto out; /* success */ ++ ++out_free: ++ if (sbinfo->si_xib_buf) ++ free_page((unsigned long)sbinfo->si_xib_buf); ++ sbinfo->si_xib_buf = NULL; ++ if (err >= 0) ++ err = -EIO; ++out_unset: ++ fput(sbinfo->si_xib); ++ sbinfo->si_xib = NULL; ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++/* xino for each branch */ ++static void xino_clear_br(struct super_block *sb) ++{ ++ aufs_bindex_t bindex, bbot; ++ struct au_branch *br; ++ ++ bbot = au_sbbot(sb); ++ for (bindex = 0; bindex <= bbot; bindex++) { ++ br = au_sbr(sb, bindex); ++ AuDebugOn(!br); ++ au_xino_put(br); ++ } ++} ++ ++static void au_xino_set_br_shared(struct super_block *sb, struct au_branch *br, ++ aufs_bindex_t bshared) ++{ ++ struct au_branch *brshared; ++ ++ brshared = au_sbr(sb, bshared); ++ AuDebugOn(!brshared->br_xino); ++ AuDebugOn(!brshared->br_xino->xi_file); ++ if (br->br_xino != brshared->br_xino) { ++ au_xino_get(brshared); ++ au_xino_put(br); ++ br->br_xino = brshared->br_xino; ++ } ++} ++ ++struct au_xino_do_set_br { ++ vfs_writef_t writef; ++ struct au_branch *br; ++ ino_t h_ino; ++ aufs_bindex_t bshared; ++}; ++ ++static int au_xino_do_set_br(struct super_block *sb, struct path *path, ++ struct au_xino_do_set_br *args) ++{ ++ int err; ++ struct au_xi_calc calc; ++ struct file *file; ++ struct au_branch *br; ++ struct au_xi_new xinew = { ++ .base = path ++ }; ++ ++ br = args->br; ++ xinew.xi = br->br_xino; ++ au_xi_calc(sb, args->h_ino, &calc); ++ xinew.copy_src = au_xino_file(xinew.xi, calc.idx); ++ if (args->bshared >= 0) ++ /* shared xino */ ++ au_xino_set_br_shared(sb, br, args->bshared); ++ else if (!xinew.xi) { ++ /* new xino */ ++ err = au_xino_init(br, calc.idx, xinew.copy_src); ++ if (unlikely(err)) ++ goto out; ++ } ++ ++ /* force re-creating */ ++ xinew.xi = br->br_xino; ++ xinew.idx = calc.idx; ++ mutex_lock(&xinew.xi->xi_mtx); ++ file = au_xi_new(sb, &xinew); ++ mutex_unlock(&xinew.xi->xi_mtx); ++ err = PTR_ERR(file); ++ if (IS_ERR(file)) ++ goto out; ++ AuDebugOn(!file); ++ ++ err = au_xino_do_write(args->writef, file, &calc, AUFS_ROOT_INO); ++ if (unlikely(err)) ++ au_xino_put(br); ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++static int au_xino_set_br(struct super_block *sb, struct path *path) ++{ ++ int err; ++ aufs_bindex_t bindex, bbot; ++ struct au_xino_do_set_br args; ++ struct inode *inode; ++ ++ SiMustWriteLock(sb); ++ ++ bbot = au_sbbot(sb); ++ inode = d_inode(sb->s_root); ++ args.writef = au_sbi(sb)->si_xwrite; ++ for (bindex = 0; bindex <= bbot; bindex++) { ++ args.h_ino = au_h_iptr(inode, bindex)->i_ino; ++ args.br = au_sbr(sb, bindex); ++ args.bshared = is_sb_shared(sb, bindex, bindex - 1); ++ err = au_xino_do_set_br(sb, path, &args); ++ if (unlikely(err)) ++ break; ++ } ++ ++ AuTraceErr(err); ++ return err; ++} ++ ++void au_xino_clr(struct super_block *sb) ++{ ++ struct au_sbinfo *sbinfo; ++ ++ au_xigen_clr(sb); ++ xino_clear_xib(sb); ++ xino_clear_br(sb); ++ dbgaufs_brs_del(sb, 0); ++ sbinfo = au_sbi(sb); ++ /* lvalue, do not call au_mntflags() */ ++ au_opt_clr(sbinfo->si_mntflags, XINO); ++} ++ ++int au_xino_set(struct super_block *sb, struct au_opt_xino *xiopt, int remount) ++{ ++ int err, skip; ++ struct dentry *dentry, *parent, *cur_dentry, *cur_parent; ++ struct qstr *dname, *cur_name; ++ struct file *cur_xino; ++ struct au_sbinfo *sbinfo; ++ struct path *path, *cur_path; ++ ++ SiMustWriteLock(sb); ++ ++ err = 0; ++ sbinfo = au_sbi(sb); ++ path = &xiopt->file->f_path; ++ dentry = path->dentry; ++ parent = dget_parent(dentry); ++ if (remount) { ++ skip = 0; ++ cur_xino = sbinfo->si_xib; ++ if (cur_xino) { ++ cur_path = &cur_xino->f_path; ++ cur_dentry = cur_path->dentry; ++ cur_parent = dget_parent(cur_dentry); ++ cur_name = &cur_dentry->d_name; ++ dname = &dentry->d_name; ++ skip = (cur_parent == parent ++ && au_qstreq(dname, cur_name)); ++ dput(cur_parent); ++ } ++ if (skip) ++ goto out; ++ } ++ ++ au_opt_set(sbinfo->si_mntflags, XINO); ++ err = au_xino_set_xib(sb, path); ++ /* si_x{read,write} are set */ ++ if (!err) ++ err = au_xigen_set(sb, path); ++ if (!err) ++ err = au_xino_set_br(sb, path); ++ if (!err) { ++ dbgaufs_brs_add(sb, 0, /*topdown*/1); ++ goto out; /* success */ ++ } ++ ++ /* reset all */ ++ AuIOErr("failed setting xino(%d).\n", err); ++ au_xino_clr(sb); ++ ++out: ++ dput(parent); ++ return err; ++} ++ ++/* ++ * create a xinofile at the default place/path. ++ */ ++struct file *au_xino_def(struct super_block *sb) ++{ ++ struct file *file; ++ char *page, *p; ++ struct au_branch *br; ++ struct super_block *h_sb; ++ struct path path; ++ aufs_bindex_t bbot, bindex, bwr; ++ ++ br = NULL; ++ bbot = au_sbbot(sb); ++ bwr = -1; ++ for (bindex = 0; bindex <= bbot; bindex++) { ++ br = au_sbr(sb, bindex); ++ if (au_br_writable(br->br_perm) ++ && !au_test_fs_bad_xino(au_br_sb(br))) { ++ bwr = bindex; ++ break; ++ } ++ } ++ ++ if (bwr >= 0) { ++ file = ERR_PTR(-ENOMEM); ++ page = (void *)__get_free_page(GFP_NOFS); ++ if (unlikely(!page)) ++ goto out; ++ path.mnt = au_br_mnt(br); ++ path.dentry = au_h_dptr(sb->s_root, bwr); ++ p = d_path(&path, page, PATH_MAX - sizeof(AUFS_XINO_FNAME)); ++ file = (void *)p; ++ if (!IS_ERR(p)) { ++ strcat(p, "/" AUFS_XINO_FNAME); ++ AuDbg("%s\n", p); ++ file = au_xino_create(sb, p, /*silent*/0, /*wbrtop*/1); ++ } ++ free_page((unsigned long)page); ++ } else { ++ file = au_xino_create(sb, AUFS_XINO_DEFPATH, /*silent*/0, ++ /*wbrtop*/0); ++ if (IS_ERR(file)) ++ goto out; ++ h_sb = file->f_path.dentry->d_sb; ++ if (unlikely(au_test_fs_bad_xino(h_sb))) { ++ pr_err("xino doesn't support %s(%s)\n", ++ AUFS_XINO_DEFPATH, au_sbtype(h_sb)); ++ fput(file); ++ file = ERR_PTR(-EINVAL); ++ } ++ } ++ ++out: ++ return file; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * initialize the xinofile for the specified branch @br ++ * at the place/path where @base_file indicates. ++ * test whether another branch is on the same filesystem or not, ++ * if found then share the xinofile with another branch. ++ */ ++int au_xino_init_br(struct super_block *sb, struct au_branch *br, ino_t h_ino, ++ struct path *base) ++{ ++ int err; ++ struct au_xino_do_set_br args = { ++ .h_ino = h_ino, ++ .br = br ++ }; ++ ++ args.writef = au_sbi(sb)->si_xwrite; ++ args.bshared = sbr_find_shared(sb, /*btop*/0, au_sbbot(sb), ++ au_br_sb(br)); ++ err = au_xino_do_set_br(sb, base, &args); ++ if (unlikely(err)) ++ au_xino_put(br); ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * get an unused inode number from bitmap ++ */ ++ino_t au_xino_new_ino(struct super_block *sb) ++{ ++ ino_t ino; ++ unsigned long *p, pindex, ul, pend; ++ struct au_sbinfo *sbinfo; ++ struct file *file; ++ int free_bit, err; ++ ++ if (!au_opt_test(au_mntflags(sb), XINO)) ++ return iunique(sb, AUFS_FIRST_INO); ++ ++ sbinfo = au_sbi(sb); ++ mutex_lock(&sbinfo->si_xib_mtx); ++ p = sbinfo->si_xib_buf; ++ free_bit = sbinfo->si_xib_next_bit; ++ if (free_bit < page_bits && !test_bit(free_bit, p)) ++ goto out; /* success */ ++ free_bit = find_first_zero_bit(p, page_bits); ++ if (free_bit < page_bits) ++ goto out; /* success */ ++ ++ pindex = sbinfo->si_xib_last_pindex; ++ for (ul = pindex - 1; ul < ULONG_MAX; ul--) { ++ err = xib_pindex(sb, ul); ++ if (unlikely(err)) ++ goto out_err; ++ free_bit = find_first_zero_bit(p, page_bits); ++ if (free_bit < page_bits) ++ goto out; /* success */ ++ } ++ ++ file = sbinfo->si_xib; ++ pend = vfsub_f_size_read(file) / PAGE_SIZE; ++ for (ul = pindex + 1; ul <= pend; ul++) { ++ err = xib_pindex(sb, ul); ++ if (unlikely(err)) ++ goto out_err; ++ free_bit = find_first_zero_bit(p, page_bits); ++ if (free_bit < page_bits) ++ goto out; /* success */ ++ } ++ BUG(); ++ ++out: ++ set_bit(free_bit, p); ++ sbinfo->si_xib_next_bit = free_bit + 1; ++ pindex = sbinfo->si_xib_last_pindex; ++ mutex_unlock(&sbinfo->si_xib_mtx); ++ ino = xib_calc_ino(pindex, free_bit); ++ AuDbg("i%lu\n", (unsigned long)ino); ++ return ino; ++out_err: ++ mutex_unlock(&sbinfo->si_xib_mtx); ++ AuDbg("i0\n"); ++ return 0; ++} ++ ++/* for s_op->delete_inode() */ ++void au_xino_delete_inode(struct inode *inode, const int unlinked) ++{ ++ int err; ++ unsigned int mnt_flags; ++ aufs_bindex_t bindex, bbot, bi; ++ unsigned char try_trunc; ++ struct au_iinfo *iinfo; ++ struct super_block *sb; ++ struct au_hinode *hi; ++ struct inode *h_inode; ++ struct au_branch *br; ++ vfs_writef_t xwrite; ++ struct au_xi_calc calc; ++ struct file *file; ++ ++ AuDebugOn(au_is_bad_inode(inode)); ++ ++ sb = inode->i_sb; ++ mnt_flags = au_mntflags(sb); ++ if (!au_opt_test(mnt_flags, XINO) ++ || inode->i_ino == AUFS_ROOT_INO) ++ return; ++ ++ if (unlinked) { ++ au_xigen_inc(inode); ++ au_xib_clear_bit(inode); ++ } ++ ++ iinfo = au_ii(inode); ++ bindex = iinfo->ii_btop; ++ if (bindex < 0) ++ return; ++ ++ xwrite = au_sbi(sb)->si_xwrite; ++ try_trunc = !!au_opt_test(mnt_flags, TRUNC_XINO); ++ hi = au_hinode(iinfo, bindex); ++ bbot = iinfo->ii_bbot; ++ for (; bindex <= bbot; bindex++, hi++) { ++ h_inode = hi->hi_inode; ++ if (!h_inode ++ || (!unlinked && h_inode->i_nlink)) ++ continue; ++ ++ /* inode may not be revalidated */ ++ bi = au_br_index(sb, hi->hi_id); ++ if (bi < 0) ++ continue; ++ ++ br = au_sbr(sb, bi); ++ au_xi_calc(sb, h_inode->i_ino, &calc); ++ file = au_xino_file(br->br_xino, calc.idx); ++ if (IS_ERR_OR_NULL(file)) ++ continue; ++ ++ err = au_xino_do_write(xwrite, file, &calc, /*ino*/0); ++ if (!err && try_trunc ++ && au_test_fs_trunc_xino(au_br_sb(br))) ++ xino_try_trunc(sb, br); ++ } ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int au_xinondir_find(struct au_xino *xi, ino_t h_ino) ++{ ++ int found, total, i; ++ ++ found = -1; ++ total = xi->xi_nondir.total; ++ for (i = 0; i < total; i++) { ++ if (xi->xi_nondir.array[i] != h_ino) ++ continue; ++ found = i; ++ break; ++ } ++ ++ return found; ++} ++ ++static int au_xinondir_expand(struct au_xino *xi) ++{ ++ int err, sz; ++ ino_t *p; ++ ++ BUILD_BUG_ON(KMALLOC_MAX_SIZE > INT_MAX); ++ ++ err = -ENOMEM; ++ sz = xi->xi_nondir.total * sizeof(ino_t); ++ if (unlikely(sz > KMALLOC_MAX_SIZE / 2)) ++ goto out; ++ p = au_kzrealloc(xi->xi_nondir.array, sz, sz << 1, GFP_ATOMIC, ++ /*may_shrink*/0); ++ if (p) { ++ xi->xi_nondir.array = p; ++ xi->xi_nondir.total <<= 1; ++ AuDbg("xi_nondir.total %d\n", xi->xi_nondir.total); ++ err = 0; ++ } ++ ++out: ++ return err; ++} ++ ++void au_xinondir_leave(struct super_block *sb, aufs_bindex_t bindex, ++ ino_t h_ino, int idx) ++{ ++ struct au_xino *xi; ++ ++ AuDebugOn(!au_opt_test(au_mntflags(sb), XINO)); ++ xi = au_sbr(sb, bindex)->br_xino; ++ AuDebugOn(idx < 0 || xi->xi_nondir.total <= idx); ++ ++ spin_lock(&xi->xi_nondir.spin); ++ AuDebugOn(xi->xi_nondir.array[idx] != h_ino); ++ xi->xi_nondir.array[idx] = 0; ++ spin_unlock(&xi->xi_nondir.spin); ++ wake_up_all(&xi->xi_nondir.wqh); ++} ++ ++int au_xinondir_enter(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, ++ int *idx) ++{ ++ int err, found, empty; ++ struct au_xino *xi; ++ ++ err = 0; ++ *idx = -1; ++ if (!au_opt_test(au_mntflags(sb), XINO)) ++ goto out; /* no xino */ ++ ++ xi = au_sbr(sb, bindex)->br_xino; ++ ++again: ++ spin_lock(&xi->xi_nondir.spin); ++ found = au_xinondir_find(xi, h_ino); ++ if (found == -1) { ++ empty = au_xinondir_find(xi, /*h_ino*/0); ++ if (empty == -1) { ++ empty = xi->xi_nondir.total; ++ err = au_xinondir_expand(xi); ++ if (unlikely(err)) ++ goto out_unlock; ++ } ++ xi->xi_nondir.array[empty] = h_ino; ++ *idx = empty; ++ } else { ++ spin_unlock(&xi->xi_nondir.spin); ++ wait_event(xi->xi_nondir.wqh, ++ xi->xi_nondir.array[found] != h_ino); ++ goto again; ++ } ++ ++out_unlock: ++ spin_unlock(&xi->xi_nondir.spin); ++out: ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++int au_xino_path(struct seq_file *seq, struct file *file) ++{ ++ int err; ++ ++ err = au_seq_path(seq, &file->f_path); ++ if (unlikely(err)) ++ goto out; ++ ++#define Deleted "\\040(deleted)" ++ seq->count -= sizeof(Deleted) - 1; ++ AuDebugOn(memcmp(seq->buf + seq->count, Deleted, ++ sizeof(Deleted) - 1)); ++#undef Deleted ++ ++out: ++ return err; ++} +diff -Nurp linux-5.4/fs/dcache.c linux-5.4-aufs/fs/dcache.c +--- linux-5.4/fs/dcache.c 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/fs/dcache.c 2019-11-28 01:25:59.069925618 +0200 +@@ -1264,7 +1264,7 @@ enum d_walk_ret { + * + * The @enter() callbacks are called with d_lock held. + */ +-static void d_walk(struct dentry *parent, void *data, ++void d_walk(struct dentry *parent, void *data, + enum d_walk_ret (*enter)(void *, struct dentry *)) + { + struct dentry *this_parent; +diff -Nurp linux-5.4/fs/fcntl.c linux-5.4-aufs/fs/fcntl.c +--- linux-5.4/fs/fcntl.c 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/fs/fcntl.c 2019-11-28 01:25:59.069925618 +0200 +@@ -32,7 +32,7 @@ + + #define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | O_DIRECT | O_NOATIME) + +-static int setfl(int fd, struct file * filp, unsigned long arg) ++int setfl(int fd, struct file * filp, unsigned long arg) + { + struct inode * inode = file_inode(filp); + int error = 0; +@@ -63,6 +63,8 @@ static int setfl(int fd, struct file * f + + if (filp->f_op->check_flags) + error = filp->f_op->check_flags(arg); ++ if (!error && filp->f_op->setfl) ++ error = filp->f_op->setfl(filp, arg); + if (error) + return error; + +diff -Nurp linux-5.4/fs/inode.c linux-5.4-aufs/fs/inode.c +--- linux-5.4/fs/inode.c 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/fs/inode.c 2019-11-28 01:25:59.070925617 +0200 +@@ -1673,7 +1673,7 @@ EXPORT_SYMBOL(generic_update_time); + * This does the actual work of updating an inodes time or version. Must have + * had called mnt_want_write() before calling this. + */ +-static int update_time(struct inode *inode, struct timespec64 *time, int flags) ++int update_time(struct inode *inode, struct timespec64 *time, int flags) + { + int (*update_time)(struct inode *, struct timespec64 *, int); + +diff -Nurp linux-5.4/fs/Kconfig linux-5.4-aufs/fs/Kconfig +--- linux-5.4/fs/Kconfig 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/fs/Kconfig 2019-11-28 01:33:04.893908639 +0200 +@@ -121,6 +121,7 @@ source "fs/quota/Kconfig" + source "fs/autofs/Kconfig" + source "fs/fuse/Kconfig" + source "fs/overlayfs/Kconfig" ++source "fs/aufs/Kconfig" + + menu "Caches" + +diff -Nurp linux-5.4/fs/Makefile linux-5.4-aufs/fs/Makefile +--- linux-5.4/fs/Makefile 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/fs/Makefile 2019-11-28 01:34:16.881905768 +0200 +@@ -110,6 +110,7 @@ obj-$(CONFIG_AUTOFS_FS) += autofs/ + obj-$(CONFIG_ADFS_FS) += adfs/ + obj-$(CONFIG_FUSE_FS) += fuse/ + obj-$(CONFIG_OVERLAY_FS) += overlayfs/ ++obj-$(CONFIG_AUFS_FS) += aufs/ + obj-$(CONFIG_ORANGEFS_FS) += orangefs/ + obj-$(CONFIG_UDF_FS) += udf/ + obj-$(CONFIG_SUN_OPENPROMFS) += openpromfs/ +diff -Nurp linux-5.4/fs/namespace.c linux-5.4-aufs/fs/namespace.c +--- linux-5.4/fs/namespace.c 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/fs/namespace.c 2019-11-28 01:25:59.070925617 +0200 +@@ -776,6 +776,12 @@ static inline int check_mnt(struct mount + return mnt->mnt_ns == current->nsproxy->mnt_ns; + } + ++/* for aufs, CONFIG_AUFS_BR_FUSE */ ++int is_current_mnt_ns(struct vfsmount *mnt) ++{ ++ return check_mnt(real_mount(mnt)); ++} ++ + /* + * vfsmount lock must be held for write + */ +diff -Nurp linux-5.4/fs/proc/base.c linux-5.4-aufs/fs/proc/base.c +--- linux-5.4/fs/proc/base.c 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/fs/proc/base.c 2019-11-28 01:25:59.070925617 +0200 +@@ -2037,7 +2037,7 @@ static int map_files_get_link(struct den + rc = -ENOENT; + vma = find_exact_vma(mm, vm_start, vm_end); + if (vma && vma->vm_file) { +- *path = vma->vm_file->f_path; ++ *path = vma_pr_or_file(vma)->f_path; + path_get(path); + rc = 0; + } +diff -Nurp linux-5.4/fs/proc/nommu.c linux-5.4-aufs/fs/proc/nommu.c +--- linux-5.4/fs/proc/nommu.c 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/fs/proc/nommu.c 2019-11-28 01:25:59.070925617 +0200 +@@ -41,7 +41,10 @@ static int nommu_region_show(struct seq_ + file = region->vm_file; + + if (file) { +- struct inode *inode = file_inode(region->vm_file); ++ struct inode *inode; ++ ++ file = vmr_pr_or_file(region); ++ inode = file_inode(file); + dev = inode->i_sb->s_dev; + ino = inode->i_ino; + } +diff -Nurp linux-5.4/fs/proc/task_mmu.c linux-5.4-aufs/fs/proc/task_mmu.c +--- linux-5.4/fs/proc/task_mmu.c 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/fs/proc/task_mmu.c 2019-11-28 01:25:59.070925617 +0200 +@@ -309,7 +309,10 @@ show_map_vma(struct seq_file *m, struct + const char *name = NULL; + + if (file) { +- struct inode *inode = file_inode(vma->vm_file); ++ struct inode *inode; ++ ++ file = vma_pr_or_file(vma); ++ inode = file_inode(file); + dev = inode->i_sb->s_dev; + ino = inode->i_ino; + pgoff = ((loff_t)vma->vm_pgoff) << PAGE_SHIFT; +@@ -1819,7 +1822,7 @@ static int show_numa_map(struct seq_file + struct proc_maps_private *proc_priv = &numa_priv->proc_maps; + struct vm_area_struct *vma = v; + struct numa_maps *md = &numa_priv->md; +- struct file *file = vma->vm_file; ++ struct file *file = vma_pr_or_file(vma); + struct mm_struct *mm = vma->vm_mm; + struct mempolicy *pol; + char buffer[64]; +diff -Nurp linux-5.4/fs/proc/task_nommu.c linux-5.4-aufs/fs/proc/task_nommu.c +--- linux-5.4/fs/proc/task_nommu.c 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/fs/proc/task_nommu.c 2019-11-28 01:25:59.070925617 +0200 +@@ -155,7 +155,10 @@ static int nommu_vma_show(struct seq_fil + file = vma->vm_file; + + if (file) { +- struct inode *inode = file_inode(vma->vm_file); ++ struct inode *inode; ++ ++ file = vma_pr_or_file(vma); ++ inode = file_inode(file); + dev = inode->i_sb->s_dev; + ino = inode->i_ino; + pgoff = (loff_t)vma->vm_pgoff << PAGE_SHIFT; +diff -Nurp linux-5.4/fs/read_write.c linux-5.4-aufs/fs/read_write.c +--- linux-5.4/fs/read_write.c 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/fs/read_write.c 2019-11-28 01:25:59.070925617 +0200 +@@ -498,6 +498,28 @@ static ssize_t __vfs_write(struct file * + return -EINVAL; + } + ++vfs_readf_t vfs_readf(struct file *file) ++{ ++ const struct file_operations *fop = file->f_op; ++ ++ if (fop->read) ++ return fop->read; ++ if (fop->read_iter) ++ return new_sync_read; ++ return ERR_PTR(-ENOSYS); ++} ++ ++vfs_writef_t vfs_writef(struct file *file) ++{ ++ const struct file_operations *fop = file->f_op; ++ ++ if (fop->write) ++ return fop->write; ++ if (fop->write_iter) ++ return new_sync_write; ++ return ERR_PTR(-ENOSYS); ++} ++ + ssize_t __kernel_write(struct file *file, const void *buf, size_t count, loff_t *pos) + { + mm_segment_t old_fs; +diff -Nurp linux-5.4/fs/splice.c linux-5.4-aufs/fs/splice.c +--- linux-5.4/fs/splice.c 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/fs/splice.c 2019-11-28 01:25:59.071925617 +0200 +@@ -834,8 +834,8 @@ EXPORT_SYMBOL(generic_splice_sendpage); + /* + * Attempt to initiate a splice from pipe to file. + */ +-static long do_splice_from(struct pipe_inode_info *pipe, struct file *out, +- loff_t *ppos, size_t len, unsigned int flags) ++long do_splice_from(struct pipe_inode_info *pipe, struct file *out, ++ loff_t *ppos, size_t len, unsigned int flags) + { + ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, + loff_t *, size_t, unsigned int); +@@ -851,9 +851,9 @@ static long do_splice_from(struct pipe_i + /* + * Attempt to initiate a splice from a file to a pipe. + */ +-static long do_splice_to(struct file *in, loff_t *ppos, +- struct pipe_inode_info *pipe, size_t len, +- unsigned int flags) ++long do_splice_to(struct file *in, loff_t *ppos, ++ struct pipe_inode_info *pipe, size_t len, ++ unsigned int flags) + { + ssize_t (*splice_read)(struct file *, loff_t *, + struct pipe_inode_info *, size_t, unsigned int); +diff -Nurp linux-5.4/fs/sync.c linux-5.4-aufs/fs/sync.c +--- linux-5.4/fs/sync.c 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/fs/sync.c 2019-11-28 01:25:59.071925617 +0200 +@@ -28,7 +28,7 @@ + * wait == 1 case since in that case write_inode() functions do + * sync_dirty_buffer() and thus effectively write one block at a time. + */ +-static int __sync_filesystem(struct super_block *sb, int wait) ++int __sync_filesystem(struct super_block *sb, int wait) + { + if (wait) + sync_inodes_sb(sb); +diff -Nurp linux-5.4/include/linux/fs.h linux-5.4-aufs/include/linux/fs.h +--- linux-5.4/include/linux/fs.h 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/include/linux/fs.h 2019-11-28 01:25:59.071925617 +0200 +@@ -1349,6 +1349,7 @@ extern void fasync_free(struct fasync_st + /* can be called from interrupts */ + extern void kill_fasync(struct fasync_struct **, int, int); + ++extern int setfl(int fd, struct file * filp, unsigned long arg); + extern void __f_setown(struct file *filp, struct pid *, enum pid_type, int force); + extern int f_setown(struct file *filp, unsigned long arg, int force); + extern void f_delown(struct file *filp); +@@ -1835,6 +1836,7 @@ struct file_operations { + ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int); + unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); + int (*check_flags)(int); ++ int (*setfl)(struct file *, unsigned long); + int (*flock) (struct file *, int, struct file_lock *); + ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int); + ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int); +@@ -1905,6 +1907,12 @@ ssize_t rw_copy_check_uvector(int type, + struct iovec *fast_pointer, + struct iovec **ret_pointer); + ++typedef ssize_t (*vfs_readf_t)(struct file *, char __user *, size_t, loff_t *); ++typedef ssize_t (*vfs_writef_t)(struct file *, const char __user *, size_t, ++ loff_t *); ++vfs_readf_t vfs_readf(struct file *file); ++vfs_writef_t vfs_writef(struct file *file); ++ + extern ssize_t __vfs_read(struct file *, char __user *, size_t, loff_t *); + extern ssize_t vfs_read(struct file *, char __user *, size_t, loff_t *); + extern ssize_t vfs_write(struct file *, const char __user *, size_t, loff_t *); +@@ -2325,6 +2333,7 @@ extern int current_umask(void); + extern void ihold(struct inode * inode); + extern void iput(struct inode *); + extern int generic_update_time(struct inode *, struct timespec64 *, int); ++extern int update_time(struct inode *, struct timespec64 *, int); + + /* /sys/fs */ + extern struct kobject *fs_kobj; +@@ -2613,6 +2622,7 @@ static inline bool sb_is_blkdev_sb(struc + return false; + } + #endif ++extern int __sync_filesystem(struct super_block *, int); + extern int sync_filesystem(struct super_block *); + extern const struct file_operations def_blk_fops; + extern const struct file_operations def_chr_fops; +diff -Nurp linux-5.4/include/linux/lockdep.h linux-5.4-aufs/include/linux/lockdep.h +--- linux-5.4/include/linux/lockdep.h 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/include/linux/lockdep.h 2019-11-28 01:25:59.071925617 +0200 +@@ -331,6 +331,8 @@ static inline int lockdep_match_key(stru + return lock->key == key; + } + ++struct lock_class *lockdep_hlock_class(struct held_lock *hlock); ++ + /* + * Acquire a lock. + * +@@ -473,6 +475,7 @@ struct lockdep_map { }; + + #define lockdep_depth(tsk) (0) + ++#define lockdep_is_held(lock) (1) + #define lockdep_is_held_type(l, r) (1) + + #define lockdep_assert_held(l) do { (void)(l); } while (0) +diff -Nurp linux-5.4/include/linux/mm.h linux-5.4-aufs/include/linux/mm.h +--- linux-5.4/include/linux/mm.h 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/include/linux/mm.h 2019-11-28 01:25:59.071925617 +0200 +@@ -1510,6 +1510,28 @@ static inline void unmap_shared_mapping_ + unmap_mapping_range(mapping, holebegin, holelen, 0); + } + ++extern void vma_do_file_update_time(struct vm_area_struct *, const char[], int); ++extern struct file *vma_do_pr_or_file(struct vm_area_struct *, const char[], ++ int); ++extern void vma_do_get_file(struct vm_area_struct *, const char[], int); ++extern void vma_do_fput(struct vm_area_struct *, const char[], int); ++ ++#define vma_file_update_time(vma) vma_do_file_update_time(vma, __func__, \ ++ __LINE__) ++#define vma_pr_or_file(vma) vma_do_pr_or_file(vma, __func__, \ ++ __LINE__) ++#define vma_get_file(vma) vma_do_get_file(vma, __func__, __LINE__) ++#define vma_fput(vma) vma_do_fput(vma, __func__, __LINE__) ++ ++#ifndef CONFIG_MMU ++extern struct file *vmr_do_pr_or_file(struct vm_region *, const char[], int); ++extern void vmr_do_fput(struct vm_region *, const char[], int); ++ ++#define vmr_pr_or_file(region) vmr_do_pr_or_file(region, __func__, \ ++ __LINE__) ++#define vmr_fput(region) vmr_do_fput(region, __func__, __LINE__) ++#endif /* !CONFIG_MMU */ ++ + extern int access_process_vm(struct task_struct *tsk, unsigned long addr, + void *buf, int len, unsigned int gup_flags); + extern int access_remote_vm(struct mm_struct *mm, unsigned long addr, +diff -Nurp linux-5.4/include/linux/mm_types.h linux-5.4-aufs/include/linux/mm_types.h +--- linux-5.4/include/linux/mm_types.h 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/include/linux/mm_types.h 2019-11-28 01:25:59.071925617 +0200 +@@ -267,6 +267,7 @@ struct vm_region { + unsigned long vm_top; /* region allocated to here */ + unsigned long vm_pgoff; /* the offset in vm_file corresponding to vm_start */ + struct file *vm_file; /* the backing file or NULL */ ++ struct file *vm_prfile; /* the virtual backing file or NULL */ + + int vm_usage; /* region usage count (access under nommu_region_sem) */ + bool vm_icache_flushed : 1; /* true if the icache has been flushed for +@@ -341,6 +342,7 @@ struct vm_area_struct { + unsigned long vm_pgoff; /* Offset (within vm_file) in PAGE_SIZE + units */ + struct file * vm_file; /* File we map to (can be NULL). */ ++ struct file *vm_prfile; /* shadow of vm_file */ + void * vm_private_data; /* was vm_pte (shared mem) */ + + #ifdef CONFIG_SWAP +diff -Nurp linux-5.4/include/linux/mnt_namespace.h linux-5.4-aufs/include/linux/mnt_namespace.h +--- linux-5.4/include/linux/mnt_namespace.h 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/include/linux/mnt_namespace.h 2019-11-28 01:25:59.071925617 +0200 +@@ -6,11 +6,14 @@ + struct mnt_namespace; + struct fs_struct; + struct user_namespace; ++struct vfsmount; + + extern struct mnt_namespace *copy_mnt_ns(unsigned long, struct mnt_namespace *, + struct user_namespace *, struct fs_struct *); + extern void put_mnt_ns(struct mnt_namespace *ns); + ++extern int is_current_mnt_ns(struct vfsmount *mnt); ++ + extern const struct file_operations proc_mounts_operations; + extern const struct file_operations proc_mountinfo_operations; + extern const struct file_operations proc_mountstats_operations; +diff -Nurp linux-5.4/include/linux/splice.h linux-5.4-aufs/include/linux/splice.h +--- linux-5.4/include/linux/splice.h 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/include/linux/splice.h 2019-11-28 01:25:59.071925617 +0200 +@@ -87,4 +87,10 @@ extern void splice_shrink_spd(struct spl + + extern const struct pipe_buf_operations page_cache_pipe_buf_ops; + extern const struct pipe_buf_operations default_pipe_buf_ops; ++ ++extern long do_splice_from(struct pipe_inode_info *pipe, struct file *out, ++ loff_t *ppos, size_t len, unsigned int flags); ++extern long do_splice_to(struct file *in, loff_t *ppos, ++ struct pipe_inode_info *pipe, size_t len, ++ unsigned int flags); + #endif +diff -Nurp linux-5.4/include/uapi/linux/aufs_type.h linux-5.4-aufs/include/uapi/linux/aufs_type.h +--- linux-5.4/include/uapi/linux/aufs_type.h 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/include/uapi/linux/aufs_type.h 2019-11-28 01:25:59.071925617 +0200 +@@ -0,0 +1,439 @@ ++/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++#ifndef __AUFS_TYPE_H__ ++#define __AUFS_TYPE_H__ ++ ++#define AUFS_NAME "aufs" ++ ++#ifdef __KERNEL__ ++/* ++ * define it before including all other headers. ++ * sched.h may use pr_* macros before defining "current", so define the ++ * no-current version first, and re-define later. ++ */ ++#define pr_fmt(fmt) AUFS_NAME " %s:%d: " fmt, __func__, __LINE__ ++#include ++#undef pr_fmt ++#define pr_fmt(fmt) \ ++ AUFS_NAME " %s:%d:%.*s[%d]: " fmt, __func__, __LINE__, \ ++ (int)sizeof(current->comm), current->comm, current->pid ++#else ++#include ++#include ++#endif /* __KERNEL__ */ ++ ++#include ++ ++#define AUFS_VERSION "5.4" ++ ++/* todo? move this to linux-2.6.19/include/magic.h */ ++#define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's') ++ ++/* ---------------------------------------------------------------------- */ ++ ++#ifdef CONFIG_AUFS_BRANCH_MAX_127 ++typedef int8_t aufs_bindex_t; ++#define AUFS_BRANCH_MAX 127 ++#else ++typedef int16_t aufs_bindex_t; ++#ifdef CONFIG_AUFS_BRANCH_MAX_511 ++#define AUFS_BRANCH_MAX 511 ++#elif defined(CONFIG_AUFS_BRANCH_MAX_1023) ++#define AUFS_BRANCH_MAX 1023 ++#elif defined(CONFIG_AUFS_BRANCH_MAX_32767) ++#define AUFS_BRANCH_MAX 32767 ++#endif ++#endif ++ ++#ifdef __KERNEL__ ++#ifndef AUFS_BRANCH_MAX ++#error unknown CONFIG_AUFS_BRANCH_MAX value ++#endif ++#endif /* __KERNEL__ */ ++ ++/* ---------------------------------------------------------------------- */ ++ ++#define AUFS_FSTYPE AUFS_NAME ++ ++#define AUFS_ROOT_INO 2 ++#define AUFS_FIRST_INO 11 ++ ++#define AUFS_WH_PFX ".wh." ++#define AUFS_WH_PFX_LEN ((int)sizeof(AUFS_WH_PFX) - 1) ++#define AUFS_WH_TMP_LEN 4 ++/* a limit for rmdir/rename a dir and copyup */ ++#define AUFS_MAX_NAMELEN (NAME_MAX \ ++ - AUFS_WH_PFX_LEN * 2 /* doubly whiteouted */\ ++ - 1 /* dot */\ ++ - AUFS_WH_TMP_LEN) /* hex */ ++#define AUFS_XINO_FNAME "." AUFS_NAME ".xino" ++#define AUFS_XINO_DEFPATH "/tmp/" AUFS_XINO_FNAME ++#define AUFS_XINO_DEF_SEC 30 /* seconds */ ++#define AUFS_XINO_DEF_TRUNC 45 /* percentage */ ++#define AUFS_DIRWH_DEF 3 ++#define AUFS_RDCACHE_DEF 10 /* seconds */ ++#define AUFS_RDCACHE_MAX 3600 /* seconds */ ++#define AUFS_RDBLK_DEF 512 /* bytes */ ++#define AUFS_RDHASH_DEF 32 ++#define AUFS_WKQ_NAME AUFS_NAME "d" ++#define AUFS_MFS_DEF_SEC 30 /* seconds */ ++#define AUFS_MFS_MAX_SEC 3600 /* seconds */ ++#define AUFS_FHSM_CACHE_DEF_SEC 30 /* seconds */ ++#define AUFS_PLINK_WARN 50 /* number of plinks in a single bucket */ ++ ++/* pseudo-link maintenace under /proc */ ++#define AUFS_PLINK_MAINT_NAME "plink_maint" ++#define AUFS_PLINK_MAINT_DIR "fs/" AUFS_NAME ++#define AUFS_PLINK_MAINT_PATH AUFS_PLINK_MAINT_DIR "/" AUFS_PLINK_MAINT_NAME ++ ++/* dirren, renamed dir */ ++#define AUFS_DR_INFO_PFX AUFS_WH_PFX ".dr." ++#define AUFS_DR_BRHINO_NAME AUFS_WH_PFX "hino" ++/* whiteouted doubly */ ++#define AUFS_WH_DR_INFO_PFX AUFS_WH_PFX AUFS_DR_INFO_PFX ++#define AUFS_WH_DR_BRHINO AUFS_WH_PFX AUFS_DR_BRHINO_NAME ++ ++#define AUFS_DIROPQ_NAME AUFS_WH_PFX ".opq" /* whiteouted doubly */ ++#define AUFS_WH_DIROPQ AUFS_WH_PFX AUFS_DIROPQ_NAME ++ ++#define AUFS_BASE_NAME AUFS_WH_PFX AUFS_NAME ++#define AUFS_PLINKDIR_NAME AUFS_WH_PFX "plnk" ++#define AUFS_ORPHDIR_NAME AUFS_WH_PFX "orph" ++ ++/* doubly whiteouted */ ++#define AUFS_WH_BASE AUFS_WH_PFX AUFS_BASE_NAME ++#define AUFS_WH_PLINKDIR AUFS_WH_PFX AUFS_PLINKDIR_NAME ++#define AUFS_WH_ORPHDIR AUFS_WH_PFX AUFS_ORPHDIR_NAME ++ ++/* branch permissions and attributes */ ++#define AUFS_BRPERM_RW "rw" ++#define AUFS_BRPERM_RO "ro" ++#define AUFS_BRPERM_RR "rr" ++#define AUFS_BRATTR_COO_REG "coo_reg" ++#define AUFS_BRATTR_COO_ALL "coo_all" ++#define AUFS_BRATTR_FHSM "fhsm" ++#define AUFS_BRATTR_UNPIN "unpin" ++#define AUFS_BRATTR_ICEX "icex" ++#define AUFS_BRATTR_ICEX_SEC "icexsec" ++#define AUFS_BRATTR_ICEX_SYS "icexsys" ++#define AUFS_BRATTR_ICEX_TR "icextr" ++#define AUFS_BRATTR_ICEX_USR "icexusr" ++#define AUFS_BRATTR_ICEX_OTH "icexoth" ++#define AUFS_BRRATTR_WH "wh" ++#define AUFS_BRWATTR_NLWH "nolwh" ++#define AUFS_BRWATTR_MOO "moo" ++ ++#define AuBrPerm_RW 1 /* writable, hardlinkable wh */ ++#define AuBrPerm_RO (1 << 1) /* readonly */ ++#define AuBrPerm_RR (1 << 2) /* natively readonly */ ++#define AuBrPerm_Mask (AuBrPerm_RW | AuBrPerm_RO | AuBrPerm_RR) ++ ++#define AuBrAttr_COO_REG (1 << 3) /* copy-up on open */ ++#define AuBrAttr_COO_ALL (1 << 4) ++#define AuBrAttr_COO_Mask (AuBrAttr_COO_REG | AuBrAttr_COO_ALL) ++ ++#define AuBrAttr_FHSM (1 << 5) /* file-based hsm */ ++#define AuBrAttr_UNPIN (1 << 6) /* rename-able top dir of ++ branch. meaningless since ++ linux-3.18-rc1 */ ++ ++/* ignore error in copying XATTR */ ++#define AuBrAttr_ICEX_SEC (1 << 7) ++#define AuBrAttr_ICEX_SYS (1 << 8) ++#define AuBrAttr_ICEX_TR (1 << 9) ++#define AuBrAttr_ICEX_USR (1 << 10) ++#define AuBrAttr_ICEX_OTH (1 << 11) ++#define AuBrAttr_ICEX (AuBrAttr_ICEX_SEC \ ++ | AuBrAttr_ICEX_SYS \ ++ | AuBrAttr_ICEX_TR \ ++ | AuBrAttr_ICEX_USR \ ++ | AuBrAttr_ICEX_OTH) ++ ++#define AuBrRAttr_WH (1 << 12) /* whiteout-able */ ++#define AuBrRAttr_Mask AuBrRAttr_WH ++ ++#define AuBrWAttr_NoLinkWH (1 << 13) /* un-hardlinkable whiteouts */ ++#define AuBrWAttr_MOO (1 << 14) /* move-up on open */ ++#define AuBrWAttr_Mask (AuBrWAttr_NoLinkWH | AuBrWAttr_MOO) ++ ++#define AuBrAttr_CMOO_Mask (AuBrAttr_COO_Mask | AuBrWAttr_MOO) ++ ++/* #warning test userspace */ ++#ifdef __KERNEL__ ++#ifndef CONFIG_AUFS_FHSM ++#undef AuBrAttr_FHSM ++#define AuBrAttr_FHSM 0 ++#endif ++#ifndef CONFIG_AUFS_XATTR ++#undef AuBrAttr_ICEX ++#define AuBrAttr_ICEX 0 ++#undef AuBrAttr_ICEX_SEC ++#define AuBrAttr_ICEX_SEC 0 ++#undef AuBrAttr_ICEX_SYS ++#define AuBrAttr_ICEX_SYS 0 ++#undef AuBrAttr_ICEX_TR ++#define AuBrAttr_ICEX_TR 0 ++#undef AuBrAttr_ICEX_USR ++#define AuBrAttr_ICEX_USR 0 ++#undef AuBrAttr_ICEX_OTH ++#define AuBrAttr_ICEX_OTH 0 ++#endif ++#endif ++ ++/* the longest combination */ ++/* AUFS_BRATTR_ICEX and AUFS_BRATTR_ICEX_TR don't affect here */ ++#define AuBrPermStrSz sizeof(AUFS_BRPERM_RW \ ++ "+" AUFS_BRATTR_COO_REG \ ++ "+" AUFS_BRATTR_FHSM \ ++ "+" AUFS_BRATTR_UNPIN \ ++ "+" AUFS_BRATTR_ICEX_SEC \ ++ "+" AUFS_BRATTR_ICEX_SYS \ ++ "+" AUFS_BRATTR_ICEX_USR \ ++ "+" AUFS_BRATTR_ICEX_OTH \ ++ "+" AUFS_BRWATTR_NLWH) ++ ++typedef struct { ++ char a[AuBrPermStrSz]; ++} au_br_perm_str_t; ++ ++static inline int au_br_writable(int brperm) ++{ ++ return brperm & AuBrPerm_RW; ++} ++ ++static inline int au_br_whable(int brperm) ++{ ++ return brperm & (AuBrPerm_RW | AuBrRAttr_WH); ++} ++ ++static inline int au_br_wh_linkable(int brperm) ++{ ++ return !(brperm & AuBrWAttr_NoLinkWH); ++} ++ ++static inline int au_br_cmoo(int brperm) ++{ ++ return brperm & AuBrAttr_CMOO_Mask; ++} ++ ++static inline int au_br_fhsm(int brperm) ++{ ++ return brperm & AuBrAttr_FHSM; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ioctl */ ++enum { ++ /* readdir in userspace */ ++ AuCtl_RDU, ++ AuCtl_RDU_INO, ++ ++ AuCtl_WBR_FD, /* pathconf wrapper */ ++ AuCtl_IBUSY, /* busy inode */ ++ AuCtl_MVDOWN, /* move-down */ ++ AuCtl_BR, /* info about branches */ ++ AuCtl_FHSM_FD /* connection for fhsm */ ++}; ++ ++/* borrowed from linux/include/linux/kernel.h */ ++#ifndef ALIGN ++#ifdef _GNU_SOURCE ++#define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a)-1) ++#else ++#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) ++#endif ++#define __ALIGN_MASK(x, mask) (((x)+(mask))&~(mask)) ++#endif ++ ++/* borrowed from linux/include/linux/compiler-gcc3.h */ ++#ifndef __aligned ++#define __aligned(x) __attribute__((aligned(x))) ++#endif ++ ++#ifdef __KERNEL__ ++#ifndef __packed ++#define __packed __attribute__((packed)) ++#endif ++#endif ++ ++struct au_rdu_cookie { ++ uint64_t h_pos; ++ int16_t bindex; ++ uint8_t flags; ++ uint8_t pad; ++ uint32_t generation; ++} __aligned(8); ++ ++struct au_rdu_ent { ++ uint64_t ino; ++ int16_t bindex; ++ uint8_t type; ++ uint8_t nlen; ++ uint8_t wh; ++ char name[0]; ++} __aligned(8); ++ ++static inline int au_rdu_len(int nlen) ++{ ++ /* include the terminating NULL */ ++ return ALIGN(sizeof(struct au_rdu_ent) + nlen + 1, ++ sizeof(uint64_t)); ++} ++ ++union au_rdu_ent_ul { ++ struct au_rdu_ent __user *e; ++ uint64_t ul; ++}; ++ ++enum { ++ AufsCtlRduV_SZ, ++ AufsCtlRduV_End ++}; ++ ++struct aufs_rdu { ++ /* input */ ++ union { ++ uint64_t sz; /* AuCtl_RDU */ ++ uint64_t nent; /* AuCtl_RDU_INO */ ++ }; ++ union au_rdu_ent_ul ent; ++ uint16_t verify[AufsCtlRduV_End]; ++ ++ /* input/output */ ++ uint32_t blk; ++ ++ /* output */ ++ union au_rdu_ent_ul tail; ++ /* number of entries which were added in a single call */ ++ uint64_t rent; ++ uint8_t full; ++ uint8_t shwh; ++ ++ struct au_rdu_cookie cookie; ++} __aligned(8); ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* dirren. the branch is identified by the filename who contains this */ ++struct au_drinfo { ++ uint64_t ino; ++ union { ++ uint8_t oldnamelen; ++ uint64_t _padding; ++ }; ++ uint8_t oldname[0]; ++} __aligned(8); ++ ++struct au_drinfo_fdata { ++ uint32_t magic; ++ struct au_drinfo drinfo; ++} __aligned(8); ++ ++#define AUFS_DRINFO_MAGIC_V1 ('a' << 24 | 'd' << 16 | 'r' << 8 | 0x01) ++/* future */ ++#define AUFS_DRINFO_MAGIC_V2 ('a' << 24 | 'd' << 16 | 'r' << 8 | 0x02) ++ ++/* ---------------------------------------------------------------------- */ ++ ++struct aufs_wbr_fd { ++ uint32_t oflags; ++ int16_t brid; ++} __aligned(8); ++ ++/* ---------------------------------------------------------------------- */ ++ ++struct aufs_ibusy { ++ uint64_t ino, h_ino; ++ int16_t bindex; ++} __aligned(8); ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* error code for move-down */ ++/* the actual message strings are implemented in aufs-util.git */ ++enum { ++ EAU_MVDOWN_OPAQUE = 1, ++ EAU_MVDOWN_WHITEOUT, ++ EAU_MVDOWN_UPPER, ++ EAU_MVDOWN_BOTTOM, ++ EAU_MVDOWN_NOUPPER, ++ EAU_MVDOWN_NOLOWERBR, ++ EAU_Last ++}; ++ ++/* flags for move-down */ ++#define AUFS_MVDOWN_DMSG 1 ++#define AUFS_MVDOWN_OWLOWER (1 << 1) /* overwrite lower */ ++#define AUFS_MVDOWN_KUPPER (1 << 2) /* keep upper */ ++#define AUFS_MVDOWN_ROLOWER (1 << 3) /* do even if lower is RO */ ++#define AUFS_MVDOWN_ROLOWER_R (1 << 4) /* did on lower RO */ ++#define AUFS_MVDOWN_ROUPPER (1 << 5) /* do even if upper is RO */ ++#define AUFS_MVDOWN_ROUPPER_R (1 << 6) /* did on upper RO */ ++#define AUFS_MVDOWN_BRID_UPPER (1 << 7) /* upper brid */ ++#define AUFS_MVDOWN_BRID_LOWER (1 << 8) /* lower brid */ ++#define AUFS_MVDOWN_FHSM_LOWER (1 << 9) /* find fhsm attr for lower */ ++#define AUFS_MVDOWN_STFS (1 << 10) /* req. stfs */ ++#define AUFS_MVDOWN_STFS_FAILED (1 << 11) /* output: stfs is unusable */ ++#define AUFS_MVDOWN_BOTTOM (1 << 12) /* output: no more lowers */ ++ ++/* index for move-down */ ++enum { ++ AUFS_MVDOWN_UPPER, ++ AUFS_MVDOWN_LOWER, ++ AUFS_MVDOWN_NARRAY ++}; ++ ++/* ++ * additional info of move-down ++ * number of free blocks and inodes. ++ * subset of struct kstatfs, but smaller and always 64bit. ++ */ ++struct aufs_stfs { ++ uint64_t f_blocks; ++ uint64_t f_bavail; ++ uint64_t f_files; ++ uint64_t f_ffree; ++}; ++ ++struct aufs_stbr { ++ int16_t brid; /* optional input */ ++ int16_t bindex; /* output */ ++ struct aufs_stfs stfs; /* output when AUFS_MVDOWN_STFS set */ ++} __aligned(8); ++ ++struct aufs_mvdown { ++ uint32_t flags; /* input/output */ ++ struct aufs_stbr stbr[AUFS_MVDOWN_NARRAY]; /* input/output */ ++ int8_t au_errno; /* output */ ++} __aligned(8); ++ ++/* ---------------------------------------------------------------------- */ ++ ++union aufs_brinfo { ++ /* PATH_MAX may differ between kernel-space and user-space */ ++ char _spacer[4096]; ++ struct { ++ int16_t id; ++ int perm; ++ char path[0]; ++ }; ++} __aligned(8); ++ ++/* ---------------------------------------------------------------------- */ ++ ++#define AuCtlType 'A' ++#define AUFS_CTL_RDU _IOWR(AuCtlType, AuCtl_RDU, struct aufs_rdu) ++#define AUFS_CTL_RDU_INO _IOWR(AuCtlType, AuCtl_RDU_INO, struct aufs_rdu) ++#define AUFS_CTL_WBR_FD _IOW(AuCtlType, AuCtl_WBR_FD, \ ++ struct aufs_wbr_fd) ++#define AUFS_CTL_IBUSY _IOWR(AuCtlType, AuCtl_IBUSY, struct aufs_ibusy) ++#define AUFS_CTL_MVDOWN _IOWR(AuCtlType, AuCtl_MVDOWN, \ ++ struct aufs_mvdown) ++#define AUFS_CTL_BRINFO _IOW(AuCtlType, AuCtl_BR, union aufs_brinfo) ++#define AUFS_CTL_FHSM_FD _IOW(AuCtlType, AuCtl_FHSM_FD, int) ++ ++#endif /* __AUFS_TYPE_H__ */ +diff -Nurp linux-5.4/kernel/fork.c linux-5.4-aufs/kernel/fork.c +--- linux-5.4/kernel/fork.c 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/kernel/fork.c 2019-11-28 01:25:59.072925617 +0200 +@@ -562,7 +562,7 @@ static __latent_entropy int dup_mmap(str + struct inode *inode = file_inode(file); + struct address_space *mapping = file->f_mapping; + +- get_file(file); ++ vma_get_file(tmp); + if (tmp->vm_flags & VM_DENYWRITE) + atomic_dec(&inode->i_writecount); + i_mmap_lock_write(mapping); +diff -Nurp linux-5.4/kernel/locking/lockdep.c linux-5.4-aufs/kernel/locking/lockdep.c +--- linux-5.4/kernel/locking/lockdep.c 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/kernel/locking/lockdep.c 2019-11-28 01:25:59.072925617 +0200 +@@ -153,7 +153,7 @@ static + struct lock_class lock_classes[MAX_LOCKDEP_KEYS]; + static DECLARE_BITMAP(lock_classes_in_use, MAX_LOCKDEP_KEYS); + +-static inline struct lock_class *hlock_class(struct held_lock *hlock) ++inline struct lock_class *lockdep_hlock_class(struct held_lock *hlock) + { + unsigned int class_idx = hlock->class_idx; + +@@ -174,6 +174,7 @@ static inline struct lock_class *hlock_c + */ + return lock_classes + class_idx; + } ++#define hlock_class(hlock) lockdep_hlock_class(hlock) + + #ifdef CONFIG_LOCK_STAT + static DEFINE_PER_CPU(struct lock_class_stats[MAX_LOCKDEP_KEYS], cpu_lock_stats); +diff -Nurp linux-5.4/MAINTAINERS linux-5.4-aufs/MAINTAINERS +--- linux-5.4/MAINTAINERS 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/MAINTAINERS 2019-11-28 01:25:59.062925618 +0200 +@@ -2832,6 +2832,19 @@ F: include/linux/audit.h + F: include/uapi/linux/audit.h + F: kernel/audit* + ++AUFS (advanced multi layered unification filesystem) FILESYSTEM ++M: "J. R. Okajima" ++L: aufs-users@lists.sourceforge.net (members only) ++L: linux-unionfs@vger.kernel.org ++W: http://aufs.sourceforge.net ++T: git://github.com/sfjro/aufs4-linux.git ++S: Supported ++F: Documentation/filesystems/aufs/ ++F: Documentation/ABI/testing/debugfs-aufs ++F: Documentation/ABI/testing/sysfs-aufs ++F: fs/aufs/ ++F: include/uapi/linux/aufs_type.h ++ + AUXILIARY DISPLAY DRIVERS + M: Miguel Ojeda Sandonis + S: Maintained +diff -Nurp linux-5.4/mm/filemap.c linux-5.4-aufs/mm/filemap.c +--- linux-5.4/mm/filemap.c 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/mm/filemap.c 2019-11-28 01:25:59.072925617 +0200 +@@ -2696,7 +2696,7 @@ vm_fault_t filemap_page_mkwrite(struct v + vm_fault_t ret = VM_FAULT_LOCKED; + + sb_start_pagefault(inode->i_sb); +- file_update_time(vmf->vma->vm_file); ++ vma_file_update_time(vmf->vma); + lock_page(page); + if (page->mapping != inode->i_mapping) { + unlock_page(page); +diff -Nurp linux-5.4/mm/Makefile linux-5.4-aufs/mm/Makefile +--- linux-5.4/mm/Makefile 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/mm/Makefile 2019-11-28 01:25:59.072925617 +0200 +@@ -42,7 +42,7 @@ obj-y := filemap.o mempool.o oom_kill. + mm_init.o mmu_context.o percpu.o slab_common.o \ + compaction.o vmacache.o \ + interval_tree.o list_lru.o workingset.o \ +- debug.o gup.o $(mmu-y) ++ prfile.o debug.o gup.o $(mmu-y) + + # Give 'page_alloc' its own module-parameter namespace + page-alloc-y := page_alloc.o +diff -Nurp linux-5.4/mm/mmap.c linux-5.4-aufs/mm/mmap.c +--- linux-5.4/mm/mmap.c 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/mm/mmap.c 2019-11-28 01:25:59.073925617 +0200 +@@ -182,7 +182,7 @@ static struct vm_area_struct *remove_vma + if (vma->vm_ops && vma->vm_ops->close) + vma->vm_ops->close(vma); + if (vma->vm_file) +- fput(vma->vm_file); ++ vma_fput(vma); + mpol_put(vma_policy(vma)); + vm_area_free(vma); + return next; +@@ -940,7 +940,7 @@ again: + if (remove_next) { + if (file) { + uprobe_munmap(next, next->vm_start, next->vm_end); +- fput(file); ++ vma_fput(vma); + } + if (next->anon_vma) + anon_vma_merge(vma, next); +@@ -1865,8 +1865,8 @@ out: + return addr; + + unmap_and_free_vma: ++ vma_fput(vma); + vma->vm_file = NULL; +- fput(file); + + /* Undo any partial mapping done by a device driver. */ + unmap_region(mm, vma, prev, vma->vm_start, vma->vm_end); +@@ -2695,7 +2695,7 @@ int __split_vma(struct mm_struct *mm, st + goto out_free_mpol; + + if (new->vm_file) +- get_file(new->vm_file); ++ vma_get_file(new); + + if (new->vm_ops && new->vm_ops->open) + new->vm_ops->open(new); +@@ -2714,7 +2714,7 @@ int __split_vma(struct mm_struct *mm, st + if (new->vm_ops && new->vm_ops->close) + new->vm_ops->close(new); + if (new->vm_file) +- fput(new->vm_file); ++ vma_fput(new); + unlink_anon_vmas(new); + out_free_mpol: + mpol_put(vma_policy(new)); +@@ -2906,7 +2906,7 @@ SYSCALL_DEFINE5(remap_file_pages, unsign + struct vm_area_struct *vma; + unsigned long populate = 0; + unsigned long ret = -EINVAL; +- struct file *file; ++ struct file *file, *prfile; + + pr_warn_once("%s (%d) uses deprecated remap_file_pages() syscall. See Documentation/vm/remap_file_pages.rst.\n", + current->comm, current->pid); +@@ -2981,10 +2981,27 @@ SYSCALL_DEFINE5(remap_file_pages, unsign + } + } + +- file = get_file(vma->vm_file); ++ vma_get_file(vma); ++ file = vma->vm_file; ++ prfile = vma->vm_prfile; + ret = do_mmap_pgoff(vma->vm_file, start, size, + prot, flags, pgoff, &populate, NULL); ++ if (!IS_ERR_VALUE(ret) && file && prfile) { ++ struct vm_area_struct *new_vma; ++ ++ new_vma = find_vma(mm, ret); ++ if (!new_vma->vm_prfile) ++ new_vma->vm_prfile = prfile; ++ if (new_vma != vma) ++ get_file(prfile); ++ } ++ /* ++ * two fput()s instead of vma_fput(vma), ++ * coz vma may not be available anymore. ++ */ + fput(file); ++ if (prfile) ++ fput(prfile); + out: + up_write(&mm->mmap_sem); + if (populate) +@@ -3274,7 +3291,7 @@ struct vm_area_struct *copy_vma(struct v + if (anon_vma_clone(new_vma, vma)) + goto out_free_mempol; + if (new_vma->vm_file) +- get_file(new_vma->vm_file); ++ vma_get_file(new_vma); + if (new_vma->vm_ops && new_vma->vm_ops->open) + new_vma->vm_ops->open(new_vma); + vma_link(mm, new_vma, prev, rb_link, rb_parent); +diff -Nurp linux-5.4/mm/nommu.c linux-5.4-aufs/mm/nommu.c +--- linux-5.4/mm/nommu.c 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/mm/nommu.c 2019-11-28 01:25:59.073925617 +0200 +@@ -552,7 +552,7 @@ static void __put_nommu_region(struct vm + up_write(&nommu_region_sem); + + if (region->vm_file) +- fput(region->vm_file); ++ vmr_fput(region); + + /* IO memory and memory shared directly out of the pagecache + * from ramfs/tmpfs mustn't be released here */ +@@ -690,7 +690,7 @@ static void delete_vma(struct mm_struct + if (vma->vm_ops && vma->vm_ops->close) + vma->vm_ops->close(vma); + if (vma->vm_file) +- fput(vma->vm_file); ++ vma_fput(vma); + put_nommu_region(vma->vm_region); + vm_area_free(vma); + } +@@ -1213,7 +1213,7 @@ unsigned long do_mmap(struct file *file, + goto error_just_free; + } + } +- fput(region->vm_file); ++ vmr_fput(region); + kmem_cache_free(vm_region_jar, region); + region = pregion; + result = start; +@@ -1290,10 +1290,10 @@ error_just_free: + up_write(&nommu_region_sem); + error: + if (region->vm_file) +- fput(region->vm_file); ++ vmr_fput(region); + kmem_cache_free(vm_region_jar, region); + if (vma->vm_file) +- fput(vma->vm_file); ++ vma_fput(vma); + vm_area_free(vma); + return ret; + +diff -Nurp linux-5.4/mm/prfile.c linux-5.4-aufs/mm/prfile.c +--- linux-5.4/mm/prfile.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/mm/prfile.c 2019-11-28 01:25:59.073925617 +0200 +@@ -0,0 +1,86 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Mainly for aufs which mmap(2) different file and wants to print different ++ * path in /proc/PID/maps. ++ * Call these functions via macros defined in linux/mm.h. ++ * ++ * See Documentation/filesystems/aufs/design/06mmap.txt ++ * ++ * Copyright (c) 2014-2019 Junjro R. Okajima ++ * Copyright (c) 2014 Ian Campbell ++ */ ++ ++#include ++#include ++#include ++ ++/* #define PRFILE_TRACE */ ++static inline void prfile_trace(struct file *f, struct file *pr, ++ const char func[], int line, const char func2[]) ++{ ++#ifdef PRFILE_TRACE ++ if (pr) ++ pr_info("%s:%d: %s, %pD2\n", func, line, func2, f); ++#endif ++} ++ ++void vma_do_file_update_time(struct vm_area_struct *vma, const char func[], ++ int line) ++{ ++ struct file *f = vma->vm_file, *pr = vma->vm_prfile; ++ ++ prfile_trace(f, pr, func, line, __func__); ++ file_update_time(f); ++ if (f && pr) ++ file_update_time(pr); ++} ++ ++struct file *vma_do_pr_or_file(struct vm_area_struct *vma, const char func[], ++ int line) ++{ ++ struct file *f = vma->vm_file, *pr = vma->vm_prfile; ++ ++ prfile_trace(f, pr, func, line, __func__); ++ return (f && pr) ? pr : f; ++} ++ ++void vma_do_get_file(struct vm_area_struct *vma, const char func[], int line) ++{ ++ struct file *f = vma->vm_file, *pr = vma->vm_prfile; ++ ++ prfile_trace(f, pr, func, line, __func__); ++ get_file(f); ++ if (f && pr) ++ get_file(pr); ++} ++ ++void vma_do_fput(struct vm_area_struct *vma, const char func[], int line) ++{ ++ struct file *f = vma->vm_file, *pr = vma->vm_prfile; ++ ++ prfile_trace(f, pr, func, line, __func__); ++ fput(f); ++ if (f && pr) ++ fput(pr); ++} ++ ++#ifndef CONFIG_MMU ++struct file *vmr_do_pr_or_file(struct vm_region *region, const char func[], ++ int line) ++{ ++ struct file *f = region->vm_file, *pr = region->vm_prfile; ++ ++ prfile_trace(f, pr, func, line, __func__); ++ return (f && pr) ? pr : f; ++} ++ ++void vmr_do_fput(struct vm_region *region, const char func[], int line) ++{ ++ struct file *f = region->vm_file, *pr = region->vm_prfile; ++ ++ prfile_trace(f, pr, func, line, __func__); ++ fput(f); ++ if (f && pr) ++ fput(pr); ++} ++#endif /* !CONFIG_MMU */ diff --git a/kernel/kernel/files/patches/mageia/fs-vboxsf.patch b/kernel/kernel/files/patches/mageia/fs-vboxsf.patch new file mode 100644 index 00000000..434fdee6 --- /dev/null +++ b/kernel/kernel/files/patches/mageia/fs-vboxsf.patch @@ -0,0 +1,3410 @@ +From df4028658f9dd7f82fd190e9db5bd82c05f94625 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Mon, 28 Oct 2019 12:17:44 +0100 +Subject: staging: Add VirtualBox guest shared folder (vboxsf) support + +VirtualBox hosts can share folders with guests, this commit adds a +VFS driver implementing the Linux-guest side of this, allowing folders +exported by the host to be mounted under Linux. + +This driver depends on the guest <-> host IPC functions exported by +the vboxguest driver. + +Signed-off-by: Hans de Goede +Link: https://lore.kernel.org/r/20191028111744.143863-2-hdegoede@redhat.com +Signed-off-by: Greg Kroah-Hartman +--- + MAINTAINERS | 6 + + drivers/staging/Kconfig | 2 + + drivers/staging/Makefile | 1 + + drivers/staging/vboxsf/Kconfig | 10 + + drivers/staging/vboxsf/Makefile | 5 + + drivers/staging/vboxsf/TODO | 7 + + drivers/staging/vboxsf/dir.c | 418 ++++++++++++++ + drivers/staging/vboxsf/file.c | 370 +++++++++++++ + drivers/staging/vboxsf/shfl_hostintf.h | 901 +++++++++++++++++++++++++++++++ + drivers/staging/vboxsf/super.c | 499 +++++++++++++++++ + drivers/staging/vboxsf/utils.c | 550 +++++++++++++++++++ + drivers/staging/vboxsf/vboxsf_wrappers.c | 371 +++++++++++++ + drivers/staging/vboxsf/vfsmod.h | 138 +++++ + 13 files changed, 3278 insertions(+) + create mode 100644 drivers/staging/vboxsf/Kconfig + create mode 100644 drivers/staging/vboxsf/Makefile + create mode 100644 drivers/staging/vboxsf/TODO + create mode 100644 drivers/staging/vboxsf/dir.c + create mode 100644 drivers/staging/vboxsf/file.c + create mode 100644 drivers/staging/vboxsf/shfl_hostintf.h + create mode 100644 drivers/staging/vboxsf/super.c + create mode 100644 drivers/staging/vboxsf/utils.c + create mode 100644 drivers/staging/vboxsf/vboxsf_wrappers.c + create mode 100644 drivers/staging/vboxsf/vfsmod.h + +diff --git a/MAINTAINERS b/MAINTAINERS +index c6c34d04ce95..71789e42ed17 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -17335,6 +17335,12 @@ F: include/linux/vbox_utils.h + F: include/uapi/linux/vbox*.h + F: drivers/virt/vboxguest/ + ++VIRTUAL BOX SHARED FOLDER VFS DRIVER: ++M: Hans de Goede ++L: linux-fsdevel@vger.kernel.org ++S: Maintained ++F: drivers/staging/vboxsf/* ++ + VIRTUAL SERIO DEVICE DRIVER + M: Stephen Chandler Paul + S: Maintained +diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig +index 6f1fa4c849a1..927d29eb92c6 100644 +--- a/drivers/staging/Kconfig ++++ b/drivers/staging/Kconfig +@@ -125,4 +125,6 @@ source "drivers/staging/exfat/Kconfig" + + source "drivers/staging/qlge/Kconfig" + ++source "drivers/staging/vboxsf/Kconfig" ++ + endif # STAGING +diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile +index a90f9b308c8d..f01f04199073 100644 +--- a/drivers/staging/Makefile ++++ b/drivers/staging/Makefile +@@ -53,3 +53,4 @@ obj-$(CONFIG_UWB) += uwb/ + obj-$(CONFIG_USB_WUSB) += wusbcore/ + obj-$(CONFIG_EXFAT_FS) += exfat/ + obj-$(CONFIG_QLGE) += qlge/ ++obj-$(CONFIG_VBOXSF_FS) += vboxsf/ +diff --git a/drivers/staging/vboxsf/Kconfig b/drivers/staging/vboxsf/Kconfig +new file mode 100644 +index 000000000000..b84586ae08b3 +--- /dev/null ++++ b/drivers/staging/vboxsf/Kconfig +@@ -0,0 +1,10 @@ ++config VBOXSF_FS ++ tristate "VirtualBox guest shared folder (vboxsf) support" ++ depends on X86 && VBOXGUEST ++ select NLS ++ help ++ VirtualBox hosts can share folders with guests, this driver ++ implements the Linux-guest side of this allowing folders exported ++ by the host to be mounted under Linux. ++ ++ If you want to use shared folders in VirtualBox guests, answer Y or M. +diff --git a/drivers/staging/vboxsf/Makefile b/drivers/staging/vboxsf/Makefile +new file mode 100644 +index 000000000000..9e4328e79623 +--- /dev/null ++++ b/drivers/staging/vboxsf/Makefile +@@ -0,0 +1,5 @@ ++# SPDX-License-Identifier: MIT ++ ++obj-$(CONFIG_VBOXSF_FS) += vboxsf.o ++ ++vboxsf-y := dir.o file.o utils.o vboxsf_wrappers.o super.o +diff --git a/drivers/staging/vboxsf/TODO b/drivers/staging/vboxsf/TODO +new file mode 100644 +index 000000000000..8b9193d0d4f0 +--- /dev/null ++++ b/drivers/staging/vboxsf/TODO +@@ -0,0 +1,7 @@ ++TODO: ++- Find a file-system developer to review this and give their Reviewed-By ++- Address any items coming up during review ++- Move to fs/vboxfs ++ ++Please send any patches to Greg Kroah-Hartman ++and Hans de Goede +diff --git a/drivers/staging/vboxsf/dir.c b/drivers/staging/vboxsf/dir.c +new file mode 100644 +index 000000000000..f260b5cc1646 +--- /dev/null ++++ b/drivers/staging/vboxsf/dir.c +@@ -0,0 +1,418 @@ ++// SPDX-License-Identifier: MIT ++/* ++ * VirtualBox Guest Shared Folders support: Directory inode and file operations ++ * ++ * Copyright (C) 2006-2018 Oracle Corporation ++ */ ++ ++#include ++#include ++#include "vfsmod.h" ++ ++static int vboxsf_dir_open(struct inode *inode, struct file *file) ++{ ++ struct vboxsf_sbi *sbi = VBOXSF_SBI(inode->i_sb); ++ struct shfl_createparms params = {}; ++ struct vboxsf_dir_info *sf_d; ++ int err; ++ ++ sf_d = vboxsf_dir_info_alloc(); ++ if (!sf_d) ++ return -ENOMEM; ++ ++ params.handle = SHFL_HANDLE_NIL; ++ params.create_flags = SHFL_CF_DIRECTORY | SHFL_CF_ACT_OPEN_IF_EXISTS | ++ SHFL_CF_ACT_FAIL_IF_NEW | SHFL_CF_ACCESS_READ; ++ ++ err = vboxsf_create_at_dentry(file_dentry(file), ¶ms); ++ if (err) ++ goto err_free_dir_info; ++ ++ if (params.result != SHFL_FILE_EXISTS) { ++ err = -ENOENT; ++ goto err_close; ++ } ++ ++ err = vboxsf_dir_read_all(sbi, sf_d, params.handle); ++ if (err) ++ goto err_close; ++ ++ vboxsf_close(sbi->root, params.handle); ++ file->private_data = sf_d; ++ return 0; ++ ++err_close: ++ vboxsf_close(sbi->root, params.handle); ++err_free_dir_info: ++ vboxsf_dir_info_free(sf_d); ++ return err; ++} ++ ++static int vboxsf_dir_release(struct inode *inode, struct file *file) ++{ ++ if (file->private_data) ++ vboxsf_dir_info_free(file->private_data); ++ ++ return 0; ++} ++ ++static unsigned int vboxsf_get_d_type(u32 mode) ++{ ++ unsigned int d_type; ++ ++ switch (mode & SHFL_TYPE_MASK) { ++ case SHFL_TYPE_FIFO: ++ d_type = DT_FIFO; ++ break; ++ case SHFL_TYPE_DEV_CHAR: ++ d_type = DT_CHR; ++ break; ++ case SHFL_TYPE_DIRECTORY: ++ d_type = DT_DIR; ++ break; ++ case SHFL_TYPE_DEV_BLOCK: ++ d_type = DT_BLK; ++ break; ++ case SHFL_TYPE_FILE: ++ d_type = DT_REG; ++ break; ++ case SHFL_TYPE_SYMLINK: ++ d_type = DT_LNK; ++ break; ++ case SHFL_TYPE_SOCKET: ++ d_type = DT_SOCK; ++ break; ++ case SHFL_TYPE_WHITEOUT: ++ d_type = DT_WHT; ++ break; ++ default: ++ d_type = DT_UNKNOWN; ++ break; ++ } ++ return d_type; ++} ++ ++static bool vboxsf_dir_emit(struct file *dir, struct dir_context *ctx) ++{ ++ struct vboxsf_sbi *sbi = VBOXSF_SBI(file_inode(dir)->i_sb); ++ struct vboxsf_dir_info *sf_d = dir->private_data; ++ struct shfl_dirinfo *info; ++ struct vboxsf_dir_buf *b; ++ unsigned int d_type; ++ loff_t i, cur = 0; ++ ino_t fake_ino; ++ size_t size; ++ int err; ++ ++ list_for_each_entry(b, &sf_d->info_list, head) { ++try_next_entry: ++ if (ctx->pos >= cur + b->entries) { ++ cur += b->entries; ++ continue; ++ } ++ ++ /* ++ * Note the vboxsf_dir_info objects we are iterating over here ++ * are variable sized, so the info pointer may end up being ++ * unaligned. This is how we get the data from the host. ++ * Since vboxsf is only supported on x86 machines this is not ++ * a problem. ++ */ ++ for (i = 0, info = b->buf; i < ctx->pos - cur; i++) { ++ size = offsetof(struct shfl_dirinfo, name.string) + ++ info->name.size; ++ info = (struct shfl_dirinfo *)((uintptr_t)info + size); ++ } ++ ++ /* Info now points to the right entry, emit it. */ ++ d_type = vboxsf_get_d_type(info->info.attr.mode); ++ ++ /* ++ * On 32 bit systems pos is 64 signed, while ino is 32 bit ++ * unsigned so fake_ino may overflow, check for this. ++ */ ++ if ((ino_t)(ctx->pos + 1) != (u64)(ctx->pos + 1)) { ++ vbg_err("vboxsf: fake ino overflow, truncating dir\n"); ++ return false; ++ } ++ fake_ino = ctx->pos + 1; ++ ++ if (sbi->nls) { ++ char d_name[NAME_MAX]; ++ ++ err = vboxsf_nlscpy(sbi, d_name, NAME_MAX, ++ info->name.string.utf8, ++ info->name.length); ++ if (err) { ++ /* skip erroneous entry and proceed */ ++ ctx->pos += 1; ++ goto try_next_entry; ++ } ++ ++ return dir_emit(ctx, d_name, strlen(d_name), ++ fake_ino, d_type); ++ } ++ ++ return dir_emit(ctx, info->name.string.utf8, info->name.length, ++ fake_ino, d_type); ++ } ++ ++ return false; ++} ++ ++static int vboxsf_dir_iterate(struct file *dir, struct dir_context *ctx) ++{ ++ bool keep_iterating; ++ ++ for (keep_iterating = true; keep_iterating; ctx->pos += 1) ++ keep_iterating = vboxsf_dir_emit(dir, ctx); ++ ++ return 0; ++} ++ ++const struct file_operations vboxsf_dir_fops = { ++ .open = vboxsf_dir_open, ++ .iterate = vboxsf_dir_iterate, ++ .release = vboxsf_dir_release, ++ .read = generic_read_dir, ++ .llseek = generic_file_llseek, ++}; ++ ++/* ++ * This is called during name resolution/lookup to check if the @dentry in ++ * the cache is still valid. the job is handled by vboxsf_inode_revalidate. ++ */ ++static int vboxsf_dentry_revalidate(struct dentry *dentry, unsigned int flags) ++{ ++ if (flags & LOOKUP_RCU) ++ return -ECHILD; ++ ++ if (d_really_is_positive(dentry)) ++ return vboxsf_inode_revalidate(dentry) == 0; ++ else ++ return vboxsf_stat_dentry(dentry, NULL) == -ENOENT; ++} ++ ++const struct dentry_operations vboxsf_dentry_ops = { ++ .d_revalidate = vboxsf_dentry_revalidate ++}; ++ ++/* iops */ ++ ++static struct dentry *vboxsf_dir_lookup(struct inode *parent, ++ struct dentry *dentry, ++ unsigned int flags) ++{ ++ struct vboxsf_sbi *sbi = VBOXSF_SBI(parent->i_sb); ++ struct shfl_fsobjinfo fsinfo; ++ struct inode *inode; ++ int err; ++ ++ dentry->d_time = jiffies; ++ ++ err = vboxsf_stat_dentry(dentry, &fsinfo); ++ if (err) { ++ inode = (err == -ENOENT) ? NULL : ERR_PTR(err); ++ } else { ++ inode = vboxsf_new_inode(parent->i_sb); ++ if (!IS_ERR(inode)) ++ vboxsf_init_inode(sbi, inode, &fsinfo); ++ } ++ ++ return d_splice_alias(inode, dentry); ++} ++ ++static int vboxsf_dir_instantiate(struct inode *parent, struct dentry *dentry, ++ struct shfl_fsobjinfo *info) ++{ ++ struct vboxsf_sbi *sbi = VBOXSF_SBI(parent->i_sb); ++ struct vboxsf_inode *sf_i; ++ struct inode *inode; ++ ++ inode = vboxsf_new_inode(parent->i_sb); ++ if (IS_ERR(inode)) ++ return PTR_ERR(inode); ++ ++ sf_i = VBOXSF_I(inode); ++ /* The host may have given us different attr then requested */ ++ sf_i->force_restat = 1; ++ vboxsf_init_inode(sbi, inode, info); ++ ++ d_instantiate(dentry, inode); ++ ++ return 0; ++} ++ ++static int vboxsf_dir_create(struct inode *parent, struct dentry *dentry, ++ umode_t mode, int is_dir) ++{ ++ struct vboxsf_inode *sf_parent_i = VBOXSF_I(parent); ++ struct vboxsf_sbi *sbi = VBOXSF_SBI(parent->i_sb); ++ struct shfl_createparms params = {}; ++ int err; ++ ++ params.handle = SHFL_HANDLE_NIL; ++ params.create_flags = SHFL_CF_ACT_CREATE_IF_NEW | ++ SHFL_CF_ACT_FAIL_IF_EXISTS | ++ SHFL_CF_ACCESS_READWRITE | ++ (is_dir ? SHFL_CF_DIRECTORY : 0); ++ params.info.attr.mode = (mode & 0777) | ++ (is_dir ? SHFL_TYPE_DIRECTORY : SHFL_TYPE_FILE); ++ params.info.attr.additional = SHFLFSOBJATTRADD_NOTHING; ++ ++ err = vboxsf_create_at_dentry(dentry, ¶ms); ++ if (err) ++ return err; ++ ++ if (params.result != SHFL_FILE_CREATED) ++ return -EPERM; ++ ++ vboxsf_close(sbi->root, params.handle); ++ ++ err = vboxsf_dir_instantiate(parent, dentry, ¶ms.info); ++ if (err) ++ return err; ++ ++ /* parent directory access/change time changed */ ++ sf_parent_i->force_restat = 1; ++ ++ return 0; ++} ++ ++static int vboxsf_dir_mkfile(struct inode *parent, struct dentry *dentry, ++ umode_t mode, bool excl) ++{ ++ return vboxsf_dir_create(parent, dentry, mode, 0); ++} ++ ++static int vboxsf_dir_mkdir(struct inode *parent, struct dentry *dentry, ++ umode_t mode) ++{ ++ return vboxsf_dir_create(parent, dentry, mode, 1); ++} ++ ++static int vboxsf_dir_unlink(struct inode *parent, struct dentry *dentry) ++{ ++ struct vboxsf_sbi *sbi = VBOXSF_SBI(parent->i_sb); ++ struct vboxsf_inode *sf_parent_i = VBOXSF_I(parent); ++ struct inode *inode = d_inode(dentry); ++ struct shfl_string *path; ++ u32 flags; ++ int err; ++ ++ if (S_ISDIR(inode->i_mode)) ++ flags = SHFL_REMOVE_DIR; ++ else ++ flags = SHFL_REMOVE_FILE; ++ ++ if (S_ISLNK(inode->i_mode)) ++ flags |= SHFL_REMOVE_SYMLINK; ++ ++ path = vboxsf_path_from_dentry(sbi, dentry); ++ if (IS_ERR(path)) ++ return PTR_ERR(path); ++ ++ err = vboxsf_remove(sbi->root, path, flags); ++ __putname(path); ++ if (err) ++ return err; ++ ++ /* parent directory access/change time changed */ ++ sf_parent_i->force_restat = 1; ++ ++ return 0; ++} ++ ++static int vboxsf_dir_rename(struct inode *old_parent, ++ struct dentry *old_dentry, ++ struct inode *new_parent, ++ struct dentry *new_dentry, ++ unsigned int flags) ++{ ++ struct vboxsf_sbi *sbi = VBOXSF_SBI(old_parent->i_sb); ++ struct vboxsf_inode *sf_old_parent_i = VBOXSF_I(old_parent); ++ struct vboxsf_inode *sf_new_parent_i = VBOXSF_I(new_parent); ++ u32 shfl_flags = SHFL_RENAME_FILE | SHFL_RENAME_REPLACE_IF_EXISTS; ++ struct shfl_string *old_path, *new_path; ++ int err; ++ ++ if (flags) ++ return -EINVAL; ++ ++ old_path = vboxsf_path_from_dentry(sbi, old_dentry); ++ if (IS_ERR(old_path)) ++ return PTR_ERR(old_path); ++ ++ new_path = vboxsf_path_from_dentry(sbi, new_dentry); ++ if (IS_ERR(new_path)) { ++ err = PTR_ERR(new_path); ++ goto err_put_old_path; ++ } ++ ++ if (d_inode(old_dentry)->i_mode & S_IFDIR) ++ shfl_flags = 0; ++ ++ err = vboxsf_rename(sbi->root, old_path, new_path, shfl_flags); ++ if (err == 0) { ++ /* parent directories access/change time changed */ ++ sf_new_parent_i->force_restat = 1; ++ sf_old_parent_i->force_restat = 1; ++ } ++ ++ __putname(new_path); ++err_put_old_path: ++ __putname(old_path); ++ return err; ++} ++ ++static int vboxsf_dir_symlink(struct inode *parent, struct dentry *dentry, ++ const char *symname) ++{ ++ struct vboxsf_inode *sf_parent_i = VBOXSF_I(parent); ++ struct vboxsf_sbi *sbi = VBOXSF_SBI(parent->i_sb); ++ int symname_size = strlen(symname) + 1; ++ struct shfl_string *path, *ssymname; ++ struct shfl_fsobjinfo info; ++ int err; ++ ++ path = vboxsf_path_from_dentry(sbi, dentry); ++ if (IS_ERR(path)) ++ return PTR_ERR(path); ++ ++ ssymname = kmalloc(SHFLSTRING_HEADER_SIZE + symname_size, GFP_KERNEL); ++ if (!ssymname) { ++ __putname(path); ++ return -ENOMEM; ++ } ++ ssymname->length = symname_size - 1; ++ ssymname->size = symname_size; ++ memcpy(ssymname->string.utf8, symname, symname_size); ++ ++ err = vboxsf_symlink(sbi->root, path, ssymname, &info); ++ kfree(ssymname); ++ __putname(path); ++ if (err) { ++ /* -EROFS means symlinks are note support -> -EPERM */ ++ return (err == -EROFS) ? -EPERM : err; ++ } ++ ++ err = vboxsf_dir_instantiate(parent, dentry, &info); ++ if (err) ++ return err; ++ ++ /* parent directory access/change time changed */ ++ sf_parent_i->force_restat = 1; ++ return 0; ++} ++ ++const struct inode_operations vboxsf_dir_iops = { ++ .lookup = vboxsf_dir_lookup, ++ .create = vboxsf_dir_mkfile, ++ .mkdir = vboxsf_dir_mkdir, ++ .rmdir = vboxsf_dir_unlink, ++ .unlink = vboxsf_dir_unlink, ++ .rename = vboxsf_dir_rename, ++ .symlink = vboxsf_dir_symlink, ++ .getattr = vboxsf_getattr, ++ .setattr = vboxsf_setattr, ++}; +diff --git a/drivers/staging/vboxsf/file.c b/drivers/staging/vboxsf/file.c +new file mode 100644 +index 000000000000..4b61ccf83fca +--- /dev/null ++++ b/drivers/staging/vboxsf/file.c +@@ -0,0 +1,370 @@ ++// SPDX-License-Identifier: MIT ++/* ++ * VirtualBox Guest Shared Folders support: Regular file inode and file ops. ++ * ++ * Copyright (C) 2006-2018 Oracle Corporation ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include "vfsmod.h" ++ ++struct vboxsf_handle { ++ u64 handle; ++ u32 root; ++ u32 access_flags; ++ struct kref refcount; ++ struct list_head head; ++}; ++ ++static int vboxsf_file_open(struct inode *inode, struct file *file) ++{ ++ struct vboxsf_inode *sf_i = VBOXSF_I(inode); ++ struct shfl_createparms params = {}; ++ struct vboxsf_handle *sf_handle; ++ u32 access_flags = 0; ++ int err; ++ ++ sf_handle = kmalloc(sizeof(*sf_handle), GFP_KERNEL); ++ if (!sf_handle) ++ return -ENOMEM; ++ ++ /* ++ * We check the value of params.handle afterwards to find out if ++ * the call succeeded or failed, as the API does not seem to cleanly ++ * distinguish error and informational messages. ++ * ++ * Furthermore, we must set params.handle to SHFL_HANDLE_NIL to ++ * make the shared folders host service use our mode parameter. ++ */ ++ params.handle = SHFL_HANDLE_NIL; ++ if (file->f_flags & O_CREAT) { ++ params.create_flags |= SHFL_CF_ACT_CREATE_IF_NEW; ++ /* ++ * We ignore O_EXCL, as the Linux kernel seems to call create ++ * beforehand itself, so O_EXCL should always fail. ++ */ ++ if (file->f_flags & O_TRUNC) ++ params.create_flags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS; ++ else ++ params.create_flags |= SHFL_CF_ACT_OPEN_IF_EXISTS; ++ } else { ++ params.create_flags |= SHFL_CF_ACT_FAIL_IF_NEW; ++ if (file->f_flags & O_TRUNC) ++ params.create_flags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS; ++ } ++ ++ switch (file->f_flags & O_ACCMODE) { ++ case O_RDONLY: ++ access_flags |= SHFL_CF_ACCESS_READ; ++ break; ++ ++ case O_WRONLY: ++ access_flags |= SHFL_CF_ACCESS_WRITE; ++ break; ++ ++ case O_RDWR: ++ access_flags |= SHFL_CF_ACCESS_READWRITE; ++ break; ++ ++ default: ++ WARN_ON(1); ++ } ++ ++ if (file->f_flags & O_APPEND) ++ access_flags |= SHFL_CF_ACCESS_APPEND; ++ ++ params.create_flags |= access_flags; ++ params.info.attr.mode = inode->i_mode; ++ ++ err = vboxsf_create_at_dentry(file_dentry(file), ¶ms); ++ if (err == 0 && params.handle == SHFL_HANDLE_NIL) ++ err = (params.result == SHFL_FILE_EXISTS) ? -EEXIST : -ENOENT; ++ if (err) { ++ kfree(sf_handle); ++ return err; ++ } ++ ++ /* the host may have given us different attr then requested */ ++ sf_i->force_restat = 1; ++ ++ /* init our handle struct and add it to the inode's handles list */ ++ sf_handle->handle = params.handle; ++ sf_handle->root = VBOXSF_SBI(inode->i_sb)->root; ++ sf_handle->access_flags = access_flags; ++ kref_init(&sf_handle->refcount); ++ ++ mutex_lock(&sf_i->handle_list_mutex); ++ list_add(&sf_handle->head, &sf_i->handle_list); ++ mutex_unlock(&sf_i->handle_list_mutex); ++ ++ file->private_data = sf_handle; ++ return 0; ++} ++ ++static void vboxsf_handle_release(struct kref *refcount) ++{ ++ struct vboxsf_handle *sf_handle = ++ container_of(refcount, struct vboxsf_handle, refcount); ++ ++ vboxsf_close(sf_handle->root, sf_handle->handle); ++ kfree(sf_handle); ++} ++ ++static int vboxsf_file_release(struct inode *inode, struct file *file) ++{ ++ struct vboxsf_inode *sf_i = VBOXSF_I(inode); ++ struct vboxsf_handle *sf_handle = file->private_data; ++ ++ /* ++ * When a file is closed on our (the guest) side, we want any subsequent ++ * accesses done on the host side to see all changes done from our side. ++ */ ++ filemap_write_and_wait(inode->i_mapping); ++ ++ mutex_lock(&sf_i->handle_list_mutex); ++ list_del(&sf_handle->head); ++ mutex_unlock(&sf_i->handle_list_mutex); ++ ++ kref_put(&sf_handle->refcount, vboxsf_handle_release); ++ return 0; ++} ++ ++/* ++ * Write back dirty pages now, because there may not be any suitable ++ * open files later ++ */ ++static void vboxsf_vma_close(struct vm_area_struct *vma) ++{ ++ filemap_write_and_wait(vma->vm_file->f_mapping); ++} ++ ++static const struct vm_operations_struct vboxsf_file_vm_ops = { ++ .close = vboxsf_vma_close, ++ .fault = filemap_fault, ++ .map_pages = filemap_map_pages, ++}; ++ ++static int vboxsf_file_mmap(struct file *file, struct vm_area_struct *vma) ++{ ++ int err; ++ ++ err = generic_file_mmap(file, vma); ++ if (!err) ++ vma->vm_ops = &vboxsf_file_vm_ops; ++ ++ return err; ++} ++ ++/* ++ * Note that since we are accessing files on the host's filesystem, files ++ * may always be changed underneath us by the host! ++ * ++ * The vboxsf API between the guest and the host does not offer any functions ++ * to deal with this. There is no inode-generation to check for changes, no ++ * events / callback on changes and no way to lock files. ++ * ++ * To avoid returning stale data when a file gets *opened* on our (the guest) ++ * side, we do a "stat" on the host side, then compare the mtime with the ++ * last known mtime and invalidate the page-cache if they differ. ++ * This is done from vboxsf_inode_revalidate(). ++ * ++ * When reads are done through the read_iter fop, it is possible to do ++ * further cache revalidation then, there are 3 options to deal with this: ++ * ++ * 1) Rely solely on the revalidation done at open time ++ * 2) Do another "stat" and compare mtime again. Unfortunately the vboxsf ++ * host API does not allow stat on handles, so we would need to use ++ * file->f_path.dentry and the stat will then fail if the file was unlinked ++ * or renamed (and there is no thing like NFS' silly-rename). So we get: ++ * 2a) "stat" and compare mtime, on stat failure invalidate the cache ++ * 2b) "stat" and compare mtime, on stat failure do nothing ++ * 3) Simply always call invalidate_inode_pages2_range on the range of the read ++ * ++ * Currently we are keeping things KISS and using option 1. this allows ++ * directly using generic_file_read_iter without wrapping it. ++ * ++ * This means that only data written on the host side before open() on ++ * the guest side is guaranteed to be seen by the guest. If necessary ++ * we may provide other read-cache strategies in the future and make this ++ * configurable through a mount option. ++ */ ++const struct file_operations vboxsf_reg_fops = { ++ .llseek = generic_file_llseek, ++ .read_iter = generic_file_read_iter, ++ .write_iter = generic_file_write_iter, ++ .mmap = vboxsf_file_mmap, ++ .open = vboxsf_file_open, ++ .release = vboxsf_file_release, ++ .fsync = noop_fsync, ++ .splice_read = generic_file_splice_read, ++}; ++ ++const struct inode_operations vboxsf_reg_iops = { ++ .getattr = vboxsf_getattr, ++ .setattr = vboxsf_setattr ++}; ++ ++static int vboxsf_readpage(struct file *file, struct page *page) ++{ ++ struct vboxsf_handle *sf_handle = file->private_data; ++ loff_t off = page_offset(page); ++ u32 nread = PAGE_SIZE; ++ u8 *buf; ++ int err; ++ ++ buf = kmap(page); ++ ++ err = vboxsf_read(sf_handle->root, sf_handle->handle, off, &nread, buf); ++ if (err == 0) { ++ memset(&buf[nread], 0, PAGE_SIZE - nread); ++ flush_dcache_page(page); ++ SetPageUptodate(page); ++ } else { ++ SetPageError(page); ++ } ++ ++ kunmap(page); ++ unlock_page(page); ++ return err; ++} ++ ++static struct vboxsf_handle *vboxsf_get_write_handle(struct vboxsf_inode *sf_i) ++{ ++ struct vboxsf_handle *h, *sf_handle = NULL; ++ ++ mutex_lock(&sf_i->handle_list_mutex); ++ list_for_each_entry(h, &sf_i->handle_list, head) { ++ if (h->access_flags == SHFL_CF_ACCESS_WRITE || ++ h->access_flags == SHFL_CF_ACCESS_READWRITE) { ++ kref_get(&h->refcount); ++ sf_handle = h; ++ break; ++ } ++ } ++ mutex_unlock(&sf_i->handle_list_mutex); ++ ++ return sf_handle; ++} ++ ++static int vboxsf_writepage(struct page *page, struct writeback_control *wbc) ++{ ++ struct inode *inode = page->mapping->host; ++ struct vboxsf_inode *sf_i = VBOXSF_I(inode); ++ struct vboxsf_handle *sf_handle; ++ loff_t off = page_offset(page); ++ loff_t size = i_size_read(inode); ++ u32 nwrite = PAGE_SIZE; ++ u8 *buf; ++ int err; ++ ++ if (off + PAGE_SIZE > size) ++ nwrite = size & ~PAGE_MASK; ++ ++ sf_handle = vboxsf_get_write_handle(sf_i); ++ if (!sf_handle) ++ return -EBADF; ++ ++ buf = kmap(page); ++ err = vboxsf_write(sf_handle->root, sf_handle->handle, ++ off, &nwrite, buf); ++ kunmap(page); ++ ++ kref_put(&sf_handle->refcount, vboxsf_handle_release); ++ ++ if (err == 0) { ++ ClearPageError(page); ++ /* mtime changed */ ++ sf_i->force_restat = 1; ++ } else { ++ ClearPageUptodate(page); ++ } ++ ++ unlock_page(page); ++ return err; ++} ++ ++static int vboxsf_write_end(struct file *file, struct address_space *mapping, ++ loff_t pos, unsigned int len, unsigned int copied, ++ struct page *page, void *fsdata) ++{ ++ struct inode *inode = mapping->host; ++ struct vboxsf_handle *sf_handle = file->private_data; ++ unsigned int from = pos & ~PAGE_MASK; ++ u32 nwritten = len; ++ u8 *buf; ++ int err; ++ ++ buf = kmap(page); ++ err = vboxsf_write(sf_handle->root, sf_handle->handle, ++ pos, &nwritten, buf + from); ++ kunmap(page); ++ ++ if (err) { ++ nwritten = 0; ++ goto out; ++ } ++ ++ /* mtime changed */ ++ VBOXSF_I(inode)->force_restat = 1; ++ ++ if (!PageUptodate(page) && nwritten == PAGE_SIZE) ++ SetPageUptodate(page); ++ ++ pos += nwritten; ++ if (pos > inode->i_size) ++ i_size_write(inode, pos); ++ ++out: ++ unlock_page(page); ++ put_page(page); ++ ++ return nwritten; ++} ++ ++const struct address_space_operations vboxsf_reg_aops = { ++ .readpage = vboxsf_readpage, ++ .writepage = vboxsf_writepage, ++ .set_page_dirty = __set_page_dirty_nobuffers, ++ .write_begin = simple_write_begin, ++ .write_end = vboxsf_write_end, ++}; ++ ++static const char *vboxsf_get_link(struct dentry *dentry, struct inode *inode, ++ struct delayed_call *done) ++{ ++ struct vboxsf_sbi *sbi = VBOXSF_SBI(inode->i_sb); ++ struct shfl_string *path; ++ char *link; ++ int err; ++ ++ if (!dentry) ++ return ERR_PTR(-ECHILD); ++ ++ path = vboxsf_path_from_dentry(sbi, dentry); ++ if (IS_ERR(path)) ++ return (char *)path; ++ ++ link = kzalloc(PATH_MAX, GFP_KERNEL); ++ if (!link) { ++ __putname(path); ++ return ERR_PTR(-ENOMEM); ++ } ++ ++ err = vboxsf_readlink(sbi->root, path, PATH_MAX, link); ++ __putname(path); ++ if (err) { ++ kfree(link); ++ return ERR_PTR(err); ++ } ++ ++ set_delayed_call(done, kfree_link, link); ++ return link; ++} ++ ++const struct inode_operations vboxsf_lnk_iops = { ++ .get_link = vboxsf_get_link ++}; +diff --git a/drivers/staging/vboxsf/shfl_hostintf.h b/drivers/staging/vboxsf/shfl_hostintf.h +new file mode 100644 +index 000000000000..aca829062c12 +--- /dev/null ++++ b/drivers/staging/vboxsf/shfl_hostintf.h +@@ -0,0 +1,901 @@ ++/* SPDX-License-Identifier: MIT */ ++/* ++ * VirtualBox Shared Folders: host interface definition. ++ * ++ * Copyright (C) 2006-2018 Oracle Corporation ++ */ ++ ++#ifndef SHFL_HOSTINTF_H ++#define SHFL_HOSTINTF_H ++ ++#include ++ ++/* The max in/out buffer size for a FN_READ or FN_WRITE call */ ++#define SHFL_MAX_RW_COUNT (16 * SZ_1M) ++ ++/* ++ * Structures shared between guest and the service ++ * can be relocated and use offsets to point to variable ++ * length parts. ++ * ++ * Shared folders protocol works with handles. ++ * Before doing any action on a file system object, ++ * one have to obtain the object handle via a SHFL_FN_CREATE ++ * request. A handle must be closed with SHFL_FN_CLOSE. ++ */ ++ ++enum { ++ SHFL_FN_QUERY_MAPPINGS = 1, /* Query mappings changes. */ ++ SHFL_FN_QUERY_MAP_NAME = 2, /* Query map name. */ ++ SHFL_FN_CREATE = 3, /* Open/create object. */ ++ SHFL_FN_CLOSE = 4, /* Close object handle. */ ++ SHFL_FN_READ = 5, /* Read object content. */ ++ SHFL_FN_WRITE = 6, /* Write new object content. */ ++ SHFL_FN_LOCK = 7, /* Lock/unlock a range in the object. */ ++ SHFL_FN_LIST = 8, /* List object content. */ ++ SHFL_FN_INFORMATION = 9, /* Query/set object information. */ ++ /* Note function number 10 is not used! */ ++ SHFL_FN_REMOVE = 11, /* Remove object */ ++ SHFL_FN_MAP_FOLDER_OLD = 12, /* Map folder (legacy) */ ++ SHFL_FN_UNMAP_FOLDER = 13, /* Unmap folder */ ++ SHFL_FN_RENAME = 14, /* Rename object */ ++ SHFL_FN_FLUSH = 15, /* Flush file */ ++ SHFL_FN_SET_UTF8 = 16, /* Select UTF8 filename encoding */ ++ SHFL_FN_MAP_FOLDER = 17, /* Map folder */ ++ SHFL_FN_READLINK = 18, /* Read symlink dest (as of VBox 4.0) */ ++ SHFL_FN_SYMLINK = 19, /* Create symlink (as of VBox 4.0) */ ++ SHFL_FN_SET_SYMLINKS = 20, /* Ask host to show symlinks (4.0+) */ ++}; ++ ++/* Root handles for a mapping are of type u32, Root handles are unique. */ ++#define SHFL_ROOT_NIL UINT_MAX ++ ++/* Shared folders handle for an opened object are of type u64. */ ++#define SHFL_HANDLE_NIL ULLONG_MAX ++ ++/* Hardcoded maximum length (in chars) of a shared folder name. */ ++#define SHFL_MAX_LEN (256) ++/* Hardcoded maximum number of shared folder mapping available to the guest. */ ++#define SHFL_MAX_MAPPINGS (64) ++ ++/** Shared folder string buffer structure. */ ++struct shfl_string { ++ /** Allocated size of the string member in bytes. */ ++ u16 size; ++ ++ /** Length of string without trailing nul in bytes. */ ++ u16 length; ++ ++ /** UTF-8 or UTF-16 string. Nul terminated. */ ++ union { ++ u8 utf8[2]; ++ u16 utf16[1]; ++ u16 ucs2[1]; /* misnomer, use utf16. */ ++ } string; ++}; ++VMMDEV_ASSERT_SIZE(shfl_string, 6); ++ ++/* The size of shfl_string w/o the string part. */ ++#define SHFLSTRING_HEADER_SIZE 4 ++ ++/* Calculate size of the string. */ ++static inline u32 shfl_string_buf_size(const struct shfl_string *string) ++{ ++ return string ? SHFLSTRING_HEADER_SIZE + string->size : 0; ++} ++ ++/* Set user id on execution (S_ISUID). */ ++#define SHFL_UNIX_ISUID 0004000U ++/* Set group id on execution (S_ISGID). */ ++#define SHFL_UNIX_ISGID 0002000U ++/* Sticky bit (S_ISVTX / S_ISTXT). */ ++#define SHFL_UNIX_ISTXT 0001000U ++ ++/* Owner readable (S_IRUSR). */ ++#define SHFL_UNIX_IRUSR 0000400U ++/* Owner writable (S_IWUSR). */ ++#define SHFL_UNIX_IWUSR 0000200U ++/* Owner executable (S_IXUSR). */ ++#define SHFL_UNIX_IXUSR 0000100U ++ ++/* Group readable (S_IRGRP). */ ++#define SHFL_UNIX_IRGRP 0000040U ++/* Group writable (S_IWGRP). */ ++#define SHFL_UNIX_IWGRP 0000020U ++/* Group executable (S_IXGRP). */ ++#define SHFL_UNIX_IXGRP 0000010U ++ ++/* Other readable (S_IROTH). */ ++#define SHFL_UNIX_IROTH 0000004U ++/* Other writable (S_IWOTH). */ ++#define SHFL_UNIX_IWOTH 0000002U ++/* Other executable (S_IXOTH). */ ++#define SHFL_UNIX_IXOTH 0000001U ++ ++/* Named pipe (fifo) (S_IFIFO). */ ++#define SHFL_TYPE_FIFO 0010000U ++/* Character device (S_IFCHR). */ ++#define SHFL_TYPE_DEV_CHAR 0020000U ++/* Directory (S_IFDIR). */ ++#define SHFL_TYPE_DIRECTORY 0040000U ++/* Block device (S_IFBLK). */ ++#define SHFL_TYPE_DEV_BLOCK 0060000U ++/* Regular file (S_IFREG). */ ++#define SHFL_TYPE_FILE 0100000U ++/* Symbolic link (S_IFLNK). */ ++#define SHFL_TYPE_SYMLINK 0120000U ++/* Socket (S_IFSOCK). */ ++#define SHFL_TYPE_SOCKET 0140000U ++/* Whiteout (S_IFWHT). */ ++#define SHFL_TYPE_WHITEOUT 0160000U ++/* Type mask (S_IFMT). */ ++#define SHFL_TYPE_MASK 0170000U ++ ++/* Checks the mode flags indicate a directory (S_ISDIR). */ ++#define SHFL_IS_DIRECTORY(m) (((m) & SHFL_TYPE_MASK) == SHFL_TYPE_DIRECTORY) ++/* Checks the mode flags indicate a symbolic link (S_ISLNK). */ ++#define SHFL_IS_SYMLINK(m) (((m) & SHFL_TYPE_MASK) == SHFL_TYPE_SYMLINK) ++ ++/** The available additional information in a shfl_fsobjattr object. */ ++enum shfl_fsobjattr_add { ++ /** No additional information is available / requested. */ ++ SHFLFSOBJATTRADD_NOTHING = 1, ++ /** ++ * The additional unix attributes (shfl_fsobjattr::u::unix_attr) are ++ * available / requested. ++ */ ++ SHFLFSOBJATTRADD_UNIX, ++ /** ++ * The additional extended attribute size (shfl_fsobjattr::u::size) is ++ * available / requested. ++ */ ++ SHFLFSOBJATTRADD_EASIZE, ++ /** ++ * The last valid item (inclusive). ++ * The valid range is SHFLFSOBJATTRADD_NOTHING thru ++ * SHFLFSOBJATTRADD_LAST. ++ */ ++ SHFLFSOBJATTRADD_LAST = SHFLFSOBJATTRADD_EASIZE, ++ ++ /** The usual 32-bit hack. */ ++ SHFLFSOBJATTRADD_32BIT_SIZE_HACK = 0x7fffffff ++}; ++ ++/** ++ * Additional unix Attributes, these are available when ++ * shfl_fsobjattr.additional == SHFLFSOBJATTRADD_UNIX. ++ */ ++struct shfl_fsobjattr_unix { ++ /** ++ * The user owning the filesystem object (st_uid). ++ * This field is ~0U if not supported. ++ */ ++ u32 uid; ++ ++ /** ++ * The group the filesystem object is assigned (st_gid). ++ * This field is ~0U if not supported. ++ */ ++ u32 gid; ++ ++ /** ++ * Number of hard links to this filesystem object (st_nlink). ++ * This field is 1 if the filesystem doesn't support hardlinking or ++ * the information isn't available. ++ */ ++ u32 hardlinks; ++ ++ /** ++ * The device number of the device which this filesystem object resides ++ * on (st_dev). This field is 0 if this information is not available. ++ */ ++ u32 inode_id_device; ++ ++ /** ++ * The unique identifier (within the filesystem) of this filesystem ++ * object (st_ino). Together with inode_id_device, this field can be ++ * used as a OS wide unique id, when both their values are not 0. ++ * This field is 0 if the information is not available. ++ */ ++ u64 inode_id; ++ ++ /** ++ * User flags (st_flags). ++ * This field is 0 if this information is not available. ++ */ ++ u32 flags; ++ ++ /** ++ * The current generation number (st_gen). ++ * This field is 0 if this information is not available. ++ */ ++ u32 generation_id; ++ ++ /** ++ * The device number of a char. or block device type object (st_rdev). ++ * This field is 0 if the file isn't a char. or block device or when ++ * the OS doesn't use the major+minor device idenfication scheme. ++ */ ++ u32 device; ++} __packed; ++ ++/** Extended attribute size. */ ++struct shfl_fsobjattr_easize { ++ /** Size of EAs. */ ++ s64 cb; ++} __packed; ++ ++/** Shared folder filesystem object attributes. */ ++struct shfl_fsobjattr { ++ /** Mode flags (st_mode). SHFL_UNIX_*, SHFL_TYPE_*, and SHFL_DOS_*. */ ++ u32 mode; ++ ++ /** The additional attributes available. */ ++ enum shfl_fsobjattr_add additional; ++ ++ /** ++ * Additional attributes. ++ * ++ * Unless explicitly specified to an API, the API can provide additional ++ * data as it is provided by the underlying OS. ++ */ ++ union { ++ struct shfl_fsobjattr_unix unix_attr; ++ struct shfl_fsobjattr_easize size; ++ } __packed u; ++} __packed; ++VMMDEV_ASSERT_SIZE(shfl_fsobjattr, 44); ++ ++struct shfl_timespec { ++ s64 ns_relative_to_unix_epoch; ++}; ++ ++/** Filesystem object information structure. */ ++struct shfl_fsobjinfo { ++ /** ++ * Logical size (st_size). ++ * For normal files this is the size of the file. ++ * For symbolic links, this is the length of the path name contained ++ * in the symbolic link. ++ * For other objects this fields needs to be specified. ++ */ ++ s64 size; ++ ++ /** Disk allocation size (st_blocks * DEV_BSIZE). */ ++ s64 allocated; ++ ++ /** Time of last access (st_atime). */ ++ struct shfl_timespec access_time; ++ ++ /** Time of last data modification (st_mtime). */ ++ struct shfl_timespec modification_time; ++ ++ /** ++ * Time of last status change (st_ctime). ++ * If not available this is set to modification_time. ++ */ ++ struct shfl_timespec change_time; ++ ++ /** ++ * Time of file birth (st_birthtime). ++ * If not available this is set to change_time. ++ */ ++ struct shfl_timespec birth_time; ++ ++ /** Attributes. */ ++ struct shfl_fsobjattr attr; ++ ++} __packed; ++VMMDEV_ASSERT_SIZE(shfl_fsobjinfo, 92); ++ ++/** ++ * result of an open/create request. ++ * Along with handle value the result code ++ * identifies what has happened while ++ * trying to open the object. ++ */ ++enum shfl_create_result { ++ SHFL_NO_RESULT, ++ /** Specified path does not exist. */ ++ SHFL_PATH_NOT_FOUND, ++ /** Path to file exists, but the last component does not. */ ++ SHFL_FILE_NOT_FOUND, ++ /** File already exists and either has been opened or not. */ ++ SHFL_FILE_EXISTS, ++ /** New file was created. */ ++ SHFL_FILE_CREATED, ++ /** Existing file was replaced or overwritten. */ ++ SHFL_FILE_REPLACED ++}; ++ ++/* No flags. Initialization value. */ ++#define SHFL_CF_NONE (0x00000000) ++ ++/* ++ * Only lookup the object, do not return a handle. When this is set all other ++ * flags are ignored. ++ */ ++#define SHFL_CF_LOOKUP (0x00000001) ++ ++/* ++ * Open parent directory of specified object. ++ * Useful for the corresponding Windows FSD flag ++ * and for opening paths like \\dir\\*.* to search the 'dir'. ++ */ ++#define SHFL_CF_OPEN_TARGET_DIRECTORY (0x00000002) ++ ++/* Create/open a directory. */ ++#define SHFL_CF_DIRECTORY (0x00000004) ++ ++/* ++ * Open/create action to do if object exists ++ * and if the object does not exists. ++ * REPLACE file means atomically DELETE and CREATE. ++ * OVERWRITE file means truncating the file to 0 and ++ * setting new size. ++ * When opening an existing directory REPLACE and OVERWRITE ++ * actions are considered invalid, and cause returning ++ * FILE_EXISTS with NIL handle. ++ */ ++#define SHFL_CF_ACT_MASK_IF_EXISTS (0x000000f0) ++#define SHFL_CF_ACT_MASK_IF_NEW (0x00000f00) ++ ++/* What to do if object exists. */ ++#define SHFL_CF_ACT_OPEN_IF_EXISTS (0x00000000) ++#define SHFL_CF_ACT_FAIL_IF_EXISTS (0x00000010) ++#define SHFL_CF_ACT_REPLACE_IF_EXISTS (0x00000020) ++#define SHFL_CF_ACT_OVERWRITE_IF_EXISTS (0x00000030) ++ ++/* What to do if object does not exist. */ ++#define SHFL_CF_ACT_CREATE_IF_NEW (0x00000000) ++#define SHFL_CF_ACT_FAIL_IF_NEW (0x00000100) ++ ++/* Read/write requested access for the object. */ ++#define SHFL_CF_ACCESS_MASK_RW (0x00003000) ++ ++/* No access requested. */ ++#define SHFL_CF_ACCESS_NONE (0x00000000) ++/* Read access requested. */ ++#define SHFL_CF_ACCESS_READ (0x00001000) ++/* Write access requested. */ ++#define SHFL_CF_ACCESS_WRITE (0x00002000) ++/* Read/Write access requested. */ ++#define SHFL_CF_ACCESS_READWRITE (0x00003000) ++ ++/* Requested share access for the object. */ ++#define SHFL_CF_ACCESS_MASK_DENY (0x0000c000) ++ ++/* Allow any access. */ ++#define SHFL_CF_ACCESS_DENYNONE (0x00000000) ++/* Do not allow read. */ ++#define SHFL_CF_ACCESS_DENYREAD (0x00004000) ++/* Do not allow write. */ ++#define SHFL_CF_ACCESS_DENYWRITE (0x00008000) ++/* Do not allow access. */ ++#define SHFL_CF_ACCESS_DENYALL (0x0000c000) ++ ++/* Requested access to attributes of the object. */ ++#define SHFL_CF_ACCESS_MASK_ATTR (0x00030000) ++ ++/* No access requested. */ ++#define SHFL_CF_ACCESS_ATTR_NONE (0x00000000) ++/* Read access requested. */ ++#define SHFL_CF_ACCESS_ATTR_READ (0x00010000) ++/* Write access requested. */ ++#define SHFL_CF_ACCESS_ATTR_WRITE (0x00020000) ++/* Read/Write access requested. */ ++#define SHFL_CF_ACCESS_ATTR_READWRITE (0x00030000) ++ ++/* ++ * The file is opened in append mode. ++ * Ignored if SHFL_CF_ACCESS_WRITE is not set. ++ */ ++#define SHFL_CF_ACCESS_APPEND (0x00040000) ++ ++/** Create parameters buffer struct for SHFL_FN_CREATE call */ ++struct shfl_createparms { ++ /** Returned handle of opened object. */ ++ u64 handle; ++ ++ /** Returned result of the operation */ ++ enum shfl_create_result result; ++ ++ /** SHFL_CF_* */ ++ u32 create_flags; ++ ++ /** ++ * Attributes of object to create and ++ * returned actual attributes of opened/created object. ++ */ ++ struct shfl_fsobjinfo info; ++} __packed; ++ ++/** Shared Folder directory information */ ++struct shfl_dirinfo { ++ /** Full information about the object. */ ++ struct shfl_fsobjinfo info; ++ /** ++ * The length of the short field (number of UTF16 chars). ++ * It is 16-bit for reasons of alignment. ++ */ ++ u16 short_name_len; ++ /** ++ * The short name for 8.3 compatibility. ++ * Empty string if not available. ++ */ ++ u16 short_name[14]; ++ struct shfl_string name; ++}; ++ ++/** Shared folder filesystem properties. */ ++struct shfl_fsproperties { ++ /** ++ * The maximum size of a filesystem object name. ++ * This does not include the '\\0'. ++ */ ++ u32 max_component_len; ++ ++ /** ++ * True if the filesystem is remote. ++ * False if the filesystem is local. ++ */ ++ bool remote; ++ ++ /** ++ * True if the filesystem is case sensitive. ++ * False if the filesystem is case insensitive. ++ */ ++ bool case_sensitive; ++ ++ /** ++ * True if the filesystem is mounted read only. ++ * False if the filesystem is mounted read write. ++ */ ++ bool read_only; ++ ++ /** ++ * True if the filesystem can encode unicode object names. ++ * False if it can't. ++ */ ++ bool supports_unicode; ++ ++ /** ++ * True if the filesystem is compresses. ++ * False if it isn't or we don't know. ++ */ ++ bool compressed; ++ ++ /** ++ * True if the filesystem compresses of individual files. ++ * False if it doesn't or we don't know. ++ */ ++ bool file_compression; ++}; ++VMMDEV_ASSERT_SIZE(shfl_fsproperties, 12); ++ ++struct shfl_volinfo { ++ s64 total_allocation_bytes; ++ s64 available_allocation_bytes; ++ u32 bytes_per_allocation_unit; ++ u32 bytes_per_sector; ++ u32 serial; ++ struct shfl_fsproperties properties; ++}; ++ ++ ++/** SHFL_FN_MAP_FOLDER Parameters structure. */ ++struct shfl_map_folder { ++ /** ++ * pointer, in: ++ * Points to struct shfl_string buffer. ++ */ ++ struct vmmdev_hgcm_function_parameter path; ++ ++ /** ++ * pointer, out: SHFLROOT (u32) ++ * Root handle of the mapping which name is queried. ++ */ ++ struct vmmdev_hgcm_function_parameter root; ++ ++ /** ++ * pointer, in: UTF16 ++ * Path delimiter ++ */ ++ struct vmmdev_hgcm_function_parameter delimiter; ++ ++ /** ++ * pointer, in: SHFLROOT (u32) ++ * Case senstive flag ++ */ ++ struct vmmdev_hgcm_function_parameter case_sensitive; ++ ++}; ++ ++/* Number of parameters */ ++#define SHFL_CPARMS_MAP_FOLDER (4) ++ ++ ++/** SHFL_FN_UNMAP_FOLDER Parameters structure. */ ++struct shfl_unmap_folder { ++ /** ++ * pointer, in: SHFLROOT (u32) ++ * Root handle of the mapping which name is queried. ++ */ ++ struct vmmdev_hgcm_function_parameter root; ++ ++}; ++ ++/* Number of parameters */ ++#define SHFL_CPARMS_UNMAP_FOLDER (1) ++ ++ ++/** SHFL_FN_CREATE Parameters structure. */ ++struct shfl_create { ++ /** ++ * pointer, in: SHFLROOT (u32) ++ * Root handle of the mapping which name is queried. ++ */ ++ struct vmmdev_hgcm_function_parameter root; ++ ++ /** ++ * pointer, in: ++ * Points to struct shfl_string buffer. ++ */ ++ struct vmmdev_hgcm_function_parameter path; ++ ++ /** ++ * pointer, in/out: ++ * Points to struct shfl_createparms buffer. ++ */ ++ struct vmmdev_hgcm_function_parameter parms; ++ ++}; ++ ++/* Number of parameters */ ++#define SHFL_CPARMS_CREATE (3) ++ ++ ++/** SHFL_FN_CLOSE Parameters structure. */ ++struct shfl_close { ++ /** ++ * pointer, in: SHFLROOT (u32) ++ * Root handle of the mapping which name is queried. ++ */ ++ struct vmmdev_hgcm_function_parameter root; ++ ++ /** ++ * value64, in: ++ * SHFLHANDLE (u64) of object to close. ++ */ ++ struct vmmdev_hgcm_function_parameter handle; ++ ++}; ++ ++/* Number of parameters */ ++#define SHFL_CPARMS_CLOSE (2) ++ ++ ++/** SHFL_FN_READ Parameters structure. */ ++struct shfl_read { ++ /** ++ * pointer, in: SHFLROOT (u32) ++ * Root handle of the mapping which name is queried. ++ */ ++ struct vmmdev_hgcm_function_parameter root; ++ ++ /** ++ * value64, in: ++ * SHFLHANDLE (u64) of object to read from. ++ */ ++ struct vmmdev_hgcm_function_parameter handle; ++ ++ /** ++ * value64, in: ++ * Offset to read from. ++ */ ++ struct vmmdev_hgcm_function_parameter offset; ++ ++ /** ++ * value64, in/out: ++ * Bytes to read/How many were read. ++ */ ++ struct vmmdev_hgcm_function_parameter cb; ++ ++ /** ++ * pointer, out: ++ * Buffer to place data to. ++ */ ++ struct vmmdev_hgcm_function_parameter buffer; ++ ++}; ++ ++/* Number of parameters */ ++#define SHFL_CPARMS_READ (5) ++ ++ ++/** SHFL_FN_WRITE Parameters structure. */ ++struct shfl_write { ++ /** ++ * pointer, in: SHFLROOT (u32) ++ * Root handle of the mapping which name is queried. ++ */ ++ struct vmmdev_hgcm_function_parameter root; ++ ++ /** ++ * value64, in: ++ * SHFLHANDLE (u64) of object to write to. ++ */ ++ struct vmmdev_hgcm_function_parameter handle; ++ ++ /** ++ * value64, in: ++ * Offset to write to. ++ */ ++ struct vmmdev_hgcm_function_parameter offset; ++ ++ /** ++ * value64, in/out: ++ * Bytes to write/How many were written. ++ */ ++ struct vmmdev_hgcm_function_parameter cb; ++ ++ /** ++ * pointer, in: ++ * Data to write. ++ */ ++ struct vmmdev_hgcm_function_parameter buffer; ++ ++}; ++ ++/* Number of parameters */ ++#define SHFL_CPARMS_WRITE (5) ++ ++ ++/* ++ * SHFL_FN_LIST ++ * Listing information includes variable length RTDIRENTRY[EX] structures. ++ */ ++ ++#define SHFL_LIST_NONE 0 ++#define SHFL_LIST_RETURN_ONE 1 ++ ++/** SHFL_FN_LIST Parameters structure. */ ++struct shfl_list { ++ /** ++ * pointer, in: SHFLROOT (u32) ++ * Root handle of the mapping which name is queried. ++ */ ++ struct vmmdev_hgcm_function_parameter root; ++ ++ /** ++ * value64, in: ++ * SHFLHANDLE (u64) of object to be listed. ++ */ ++ struct vmmdev_hgcm_function_parameter handle; ++ ++ /** ++ * value32, in: ++ * List flags SHFL_LIST_*. ++ */ ++ struct vmmdev_hgcm_function_parameter flags; ++ ++ /** ++ * value32, in/out: ++ * Bytes to be used for listing information/How many bytes were used. ++ */ ++ struct vmmdev_hgcm_function_parameter cb; ++ ++ /** ++ * pointer, in/optional ++ * Points to struct shfl_string buffer that specifies a search path. ++ */ ++ struct vmmdev_hgcm_function_parameter path; ++ ++ /** ++ * pointer, out: ++ * Buffer to place listing information to. (struct shfl_dirinfo) ++ */ ++ struct vmmdev_hgcm_function_parameter buffer; ++ ++ /** ++ * value32, in/out: ++ * Indicates a key where the listing must be resumed. ++ * in: 0 means start from begin of object. ++ * out: 0 means listing completed. ++ */ ++ struct vmmdev_hgcm_function_parameter resume_point; ++ ++ /** ++ * pointer, out: ++ * Number of files returned ++ */ ++ struct vmmdev_hgcm_function_parameter file_count; ++}; ++ ++/* Number of parameters */ ++#define SHFL_CPARMS_LIST (8) ++ ++ ++/** SHFL_FN_READLINK Parameters structure. */ ++struct shfl_readLink { ++ /** ++ * pointer, in: SHFLROOT (u32) ++ * Root handle of the mapping which name is queried. ++ */ ++ struct vmmdev_hgcm_function_parameter root; ++ ++ /** ++ * pointer, in: ++ * Points to struct shfl_string buffer. ++ */ ++ struct vmmdev_hgcm_function_parameter path; ++ ++ /** ++ * pointer, out: ++ * Buffer to place data to. ++ */ ++ struct vmmdev_hgcm_function_parameter buffer; ++ ++}; ++ ++/* Number of parameters */ ++#define SHFL_CPARMS_READLINK (3) ++ ++ ++/* SHFL_FN_INFORMATION */ ++ ++/* Mask of Set/Get bit. */ ++#define SHFL_INFO_MODE_MASK (0x1) ++/* Get information */ ++#define SHFL_INFO_GET (0x0) ++/* Set information */ ++#define SHFL_INFO_SET (0x1) ++ ++/* Get name of the object. */ ++#define SHFL_INFO_NAME (0x2) ++/* Set size of object (extend/trucate); only applies to file objects */ ++#define SHFL_INFO_SIZE (0x4) ++/* Get/Set file object info. */ ++#define SHFL_INFO_FILE (0x8) ++/* Get volume information. */ ++#define SHFL_INFO_VOLUME (0x10) ++ ++/** SHFL_FN_INFORMATION Parameters structure. */ ++struct shfl_information { ++ /** ++ * pointer, in: SHFLROOT (u32) ++ * Root handle of the mapping which name is queried. ++ */ ++ struct vmmdev_hgcm_function_parameter root; ++ ++ /** ++ * value64, in: ++ * SHFLHANDLE (u64) of object to be listed. ++ */ ++ struct vmmdev_hgcm_function_parameter handle; ++ ++ /** ++ * value32, in: ++ * SHFL_INFO_* ++ */ ++ struct vmmdev_hgcm_function_parameter flags; ++ ++ /** ++ * value32, in/out: ++ * Bytes to be used for information/How many bytes were used. ++ */ ++ struct vmmdev_hgcm_function_parameter cb; ++ ++ /** ++ * pointer, in/out: ++ * Information to be set/get (shfl_fsobjinfo or shfl_string). Do not ++ * forget to set the shfl_fsobjinfo::attr::additional for a get ++ * operation as well. ++ */ ++ struct vmmdev_hgcm_function_parameter info; ++ ++}; ++ ++/* Number of parameters */ ++#define SHFL_CPARMS_INFORMATION (5) ++ ++ ++/* SHFL_FN_REMOVE */ ++ ++#define SHFL_REMOVE_FILE (0x1) ++#define SHFL_REMOVE_DIR (0x2) ++#define SHFL_REMOVE_SYMLINK (0x4) ++ ++/** SHFL_FN_REMOVE Parameters structure. */ ++struct shfl_remove { ++ /** ++ * pointer, in: SHFLROOT (u32) ++ * Root handle of the mapping which name is queried. ++ */ ++ struct vmmdev_hgcm_function_parameter root; ++ ++ /** ++ * pointer, in: ++ * Points to struct shfl_string buffer. ++ */ ++ struct vmmdev_hgcm_function_parameter path; ++ ++ /** ++ * value32, in: ++ * remove flags (file/directory) ++ */ ++ struct vmmdev_hgcm_function_parameter flags; ++ ++}; ++ ++#define SHFL_CPARMS_REMOVE (3) ++ ++ ++/* SHFL_FN_RENAME */ ++ ++#define SHFL_RENAME_FILE (0x1) ++#define SHFL_RENAME_DIR (0x2) ++#define SHFL_RENAME_REPLACE_IF_EXISTS (0x4) ++ ++/** SHFL_FN_RENAME Parameters structure. */ ++struct shfl_rename { ++ /** ++ * pointer, in: SHFLROOT (u32) ++ * Root handle of the mapping which name is queried. ++ */ ++ struct vmmdev_hgcm_function_parameter root; ++ ++ /** ++ * pointer, in: ++ * Points to struct shfl_string src. ++ */ ++ struct vmmdev_hgcm_function_parameter src; ++ ++ /** ++ * pointer, in: ++ * Points to struct shfl_string dest. ++ */ ++ struct vmmdev_hgcm_function_parameter dest; ++ ++ /** ++ * value32, in: ++ * rename flags (file/directory) ++ */ ++ struct vmmdev_hgcm_function_parameter flags; ++ ++}; ++ ++#define SHFL_CPARMS_RENAME (4) ++ ++ ++/** SHFL_FN_SYMLINK Parameters structure. */ ++struct shfl_symlink { ++ /** ++ * pointer, in: SHFLROOT (u32) ++ * Root handle of the mapping which name is queried. ++ */ ++ struct vmmdev_hgcm_function_parameter root; ++ ++ /** ++ * pointer, in: ++ * Points to struct shfl_string of path for the new symlink. ++ */ ++ struct vmmdev_hgcm_function_parameter new_path; ++ ++ /** ++ * pointer, in: ++ * Points to struct shfl_string of destination for symlink. ++ */ ++ struct vmmdev_hgcm_function_parameter old_path; ++ ++ /** ++ * pointer, out: ++ * Information about created symlink. ++ */ ++ struct vmmdev_hgcm_function_parameter info; ++ ++}; ++ ++#define SHFL_CPARMS_SYMLINK (4) ++ ++#endif +diff --git a/drivers/staging/vboxsf/super.c b/drivers/staging/vboxsf/super.c +new file mode 100644 +index 000000000000..3913ffafa83b +--- /dev/null ++++ b/drivers/staging/vboxsf/super.c +@@ -0,0 +1,499 @@ ++// SPDX-License-Identifier: MIT ++/* ++ * VirtualBox Guest Shared Folders support: Virtual File System. ++ * ++ * Module initialization/finalization ++ * File system registration/deregistration ++ * Superblock reading ++ * Few utility functions ++ * ++ * Copyright (C) 2006-2018 Oracle Corporation ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "vfsmod.h" ++ ++#define VBOXSF_SUPER_MAGIC 0x786f4256 /* 'VBox' little endian */ ++ ++#define VBSF_MOUNT_SIGNATURE_BYTE_0 ('\000') ++#define VBSF_MOUNT_SIGNATURE_BYTE_1 ('\377') ++#define VBSF_MOUNT_SIGNATURE_BYTE_2 ('\376') ++#define VBSF_MOUNT_SIGNATURE_BYTE_3 ('\375') ++ ++static int follow_symlinks; ++module_param(follow_symlinks, int, 0444); ++MODULE_PARM_DESC(follow_symlinks, ++ "Let host resolve symlinks rather than showing them"); ++ ++static DEFINE_IDA(vboxsf_bdi_ida); ++static DEFINE_MUTEX(vboxsf_setup_mutex); ++static bool vboxsf_setup_done; ++static struct super_operations vboxsf_super_ops; /* forward declaration */ ++static struct kmem_cache *vboxsf_inode_cachep; ++ ++static char * const vboxsf_default_nls = CONFIG_NLS_DEFAULT; ++ ++enum { opt_nls, opt_uid, opt_gid, opt_ttl, opt_dmode, opt_fmode, ++ opt_dmask, opt_fmask }; ++ ++static const struct fs_parameter_spec vboxsf_param_specs[] = { ++ fsparam_string ("nls", opt_nls), ++ fsparam_u32 ("uid", opt_uid), ++ fsparam_u32 ("gid", opt_gid), ++ fsparam_u32 ("ttl", opt_ttl), ++ fsparam_u32oct ("dmode", opt_dmode), ++ fsparam_u32oct ("fmode", opt_fmode), ++ fsparam_u32oct ("dmask", opt_dmask), ++ fsparam_u32oct ("fmask", opt_fmask), ++ {} ++}; ++ ++static const struct fs_parameter_description vboxsf_fs_parameters = { ++ .name = "vboxsf", ++ .specs = vboxsf_param_specs, ++}; ++ ++static int vboxsf_parse_param(struct fs_context *fc, struct fs_parameter *param) ++{ ++ struct vboxsf_fs_context *ctx = fc->fs_private; ++ struct fs_parse_result result; ++ kuid_t uid; ++ kgid_t gid; ++ int opt; ++ ++ opt = fs_parse(fc, &vboxsf_fs_parameters, param, &result); ++ if (opt < 0) ++ return opt; ++ ++ switch (opt) { ++ case opt_nls: ++ if (fc->purpose != FS_CONTEXT_FOR_MOUNT) { ++ vbg_err("vboxsf: Cannot reconfigure nls option\n"); ++ return -EINVAL; ++ } ++ ctx->nls_name = param->string; ++ param->string = NULL; ++ break; ++ case opt_uid: ++ uid = make_kuid(current_user_ns(), result.uint_32); ++ if (!uid_valid(uid)) ++ return -EINVAL; ++ ctx->o.uid = uid; ++ break; ++ case opt_gid: ++ gid = make_kgid(current_user_ns(), result.uint_32); ++ if (!gid_valid(gid)) ++ return -EINVAL; ++ ctx->o.gid = gid; ++ break; ++ case opt_ttl: ++ ctx->o.ttl = msecs_to_jiffies(result.uint_32); ++ break; ++ case opt_dmode: ++ if (result.uint_32 & ~0777) ++ return -EINVAL; ++ ctx->o.dmode = result.uint_32; ++ ctx->o.dmode_set = true; ++ break; ++ case opt_fmode: ++ if (result.uint_32 & ~0777) ++ return -EINVAL; ++ ctx->o.fmode = result.uint_32; ++ ctx->o.fmode_set = true; ++ break; ++ case opt_dmask: ++ if (result.uint_32 & ~07777) ++ return -EINVAL; ++ ctx->o.dmask = result.uint_32; ++ break; ++ case opt_fmask: ++ if (result.uint_32 & ~07777) ++ return -EINVAL; ++ ctx->o.fmask = result.uint_32; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int vboxsf_fill_super(struct super_block *sb, struct fs_context *fc) ++{ ++ struct vboxsf_fs_context *ctx = fc->fs_private; ++ struct shfl_string *folder_name, root_path; ++ struct vboxsf_sbi *sbi; ++ struct dentry *droot; ++ struct inode *iroot; ++ char *nls_name; ++ size_t size; ++ int err; ++ ++ if (!fc->source) ++ return -EINVAL; ++ ++ sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); ++ if (!sbi) ++ return -ENOMEM; ++ ++ sbi->o = ctx->o; ++ idr_init(&sbi->ino_idr); ++ spin_lock_init(&sbi->ino_idr_lock); ++ sbi->next_generation = 1; ++ sbi->bdi_id = -1; ++ ++ /* Load nls if not utf8 */ ++ nls_name = ctx->nls_name ? ctx->nls_name : vboxsf_default_nls; ++ if (strcmp(nls_name, "utf8") != 0) { ++ if (nls_name == vboxsf_default_nls) ++ sbi->nls = load_nls_default(); ++ else ++ sbi->nls = load_nls(nls_name); ++ ++ if (!sbi->nls) { ++ vbg_err("vboxsf: Count not load '%s' nls\n", nls_name); ++ err = -EINVAL; ++ goto fail_free; ++ } ++ } ++ ++ sbi->bdi_id = ida_simple_get(&vboxsf_bdi_ida, 0, 0, GFP_KERNEL); ++ if (sbi->bdi_id < 0) { ++ err = sbi->bdi_id; ++ goto fail_free; ++ } ++ ++ err = super_setup_bdi_name(sb, "vboxsf-%s.%d", fc->source, sbi->bdi_id); ++ if (err) ++ goto fail_free; ++ ++ /* Turn source into a shfl_string and map the folder */ ++ size = strlen(fc->source) + 1; ++ folder_name = kmalloc(SHFLSTRING_HEADER_SIZE + size, GFP_KERNEL); ++ if (!folder_name) ++ goto fail_free; ++ folder_name->size = size; ++ folder_name->length = size - 1; ++ strlcpy(folder_name->string.utf8, fc->source, size); ++ err = vboxsf_map_folder(folder_name, &sbi->root); ++ kfree(folder_name); ++ if (err) { ++ vbg_err("vboxsf: Host rejected mount of '%s' with error %d\n", ++ fc->source, err); ++ goto fail_free; ++ } ++ ++ root_path.length = 1; ++ root_path.size = 2; ++ root_path.string.utf8[0] = '/'; ++ root_path.string.utf8[1] = 0; ++ err = vboxsf_stat(sbi, &root_path, &sbi->root_info); ++ if (err) ++ goto fail_unmap; ++ ++ sb->s_magic = VBOXSF_SUPER_MAGIC; ++ sb->s_blocksize = 1024; ++ sb->s_maxbytes = MAX_LFS_FILESIZE; ++ sb->s_op = &vboxsf_super_ops; ++ sb->s_d_op = &vboxsf_dentry_ops; ++ ++ iroot = iget_locked(sb, 0); ++ if (!iroot) { ++ err = -ENOMEM; ++ goto fail_unmap; ++ } ++ vboxsf_init_inode(sbi, iroot, &sbi->root_info); ++ unlock_new_inode(iroot); ++ ++ droot = d_make_root(iroot); ++ if (!droot) { ++ err = -ENOMEM; ++ goto fail_unmap; ++ } ++ ++ sb->s_root = droot; ++ sb->s_fs_info = sbi; ++ return 0; ++ ++fail_unmap: ++ vboxsf_unmap_folder(sbi->root); ++fail_free: ++ if (sbi->bdi_id >= 0) ++ ida_simple_remove(&vboxsf_bdi_ida, sbi->bdi_id); ++ if (sbi->nls) ++ unload_nls(sbi->nls); ++ idr_destroy(&sbi->ino_idr); ++ kfree(sbi); ++ return err; ++} ++ ++static void vboxsf_inode_init_once(void *data) ++{ ++ struct vboxsf_inode *sf_i = data; ++ ++ mutex_init(&sf_i->handle_list_mutex); ++ inode_init_once(&sf_i->vfs_inode); ++} ++ ++static struct inode *vboxsf_alloc_inode(struct super_block *sb) ++{ ++ struct vboxsf_inode *sf_i; ++ ++ sf_i = kmem_cache_alloc(vboxsf_inode_cachep, GFP_NOFS); ++ if (!sf_i) ++ return NULL; ++ ++ sf_i->force_restat = 0; ++ INIT_LIST_HEAD(&sf_i->handle_list); ++ ++ return &sf_i->vfs_inode; ++} ++ ++static void vboxsf_free_inode(struct inode *inode) ++{ ++ struct vboxsf_sbi *sbi = VBOXSF_SBI(inode->i_sb); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&sbi->ino_idr_lock, flags); ++ idr_remove(&sbi->ino_idr, inode->i_ino); ++ spin_unlock_irqrestore(&sbi->ino_idr_lock, flags); ++ kmem_cache_free(vboxsf_inode_cachep, VBOXSF_I(inode)); ++} ++ ++static void vboxsf_put_super(struct super_block *sb) ++{ ++ struct vboxsf_sbi *sbi = VBOXSF_SBI(sb); ++ ++ vboxsf_unmap_folder(sbi->root); ++ if (sbi->bdi_id >= 0) ++ ida_simple_remove(&vboxsf_bdi_ida, sbi->bdi_id); ++ if (sbi->nls) ++ unload_nls(sbi->nls); ++ ++ /* ++ * vboxsf_free_inode uses the idr, make sure all delayed rcu free ++ * inodes are flushed. ++ */ ++ rcu_barrier(); ++ idr_destroy(&sbi->ino_idr); ++ kfree(sbi); ++} ++ ++static int vboxsf_statfs(struct dentry *dentry, struct kstatfs *stat) ++{ ++ struct super_block *sb = dentry->d_sb; ++ struct shfl_volinfo shfl_volinfo; ++ struct vboxsf_sbi *sbi; ++ u32 buf_len; ++ int err; ++ ++ sbi = VBOXSF_SBI(sb); ++ buf_len = sizeof(shfl_volinfo); ++ err = vboxsf_fsinfo(sbi->root, 0, SHFL_INFO_GET | SHFL_INFO_VOLUME, ++ &buf_len, &shfl_volinfo); ++ if (err) ++ return err; ++ ++ stat->f_type = VBOXSF_SUPER_MAGIC; ++ stat->f_bsize = shfl_volinfo.bytes_per_allocation_unit; ++ ++ do_div(shfl_volinfo.total_allocation_bytes, ++ shfl_volinfo.bytes_per_allocation_unit); ++ stat->f_blocks = shfl_volinfo.total_allocation_bytes; ++ ++ do_div(shfl_volinfo.available_allocation_bytes, ++ shfl_volinfo.bytes_per_allocation_unit); ++ stat->f_bfree = shfl_volinfo.available_allocation_bytes; ++ stat->f_bavail = shfl_volinfo.available_allocation_bytes; ++ ++ stat->f_files = 1000; ++ /* ++ * Don't return 0 here since the guest may then think that it is not ++ * possible to create any more files. ++ */ ++ stat->f_ffree = 1000000; ++ stat->f_fsid.val[0] = 0; ++ stat->f_fsid.val[1] = 0; ++ stat->f_namelen = 255; ++ return 0; ++} ++ ++static struct super_operations vboxsf_super_ops = { ++ .alloc_inode = vboxsf_alloc_inode, ++ .free_inode = vboxsf_free_inode, ++ .put_super = vboxsf_put_super, ++ .statfs = vboxsf_statfs, ++}; ++ ++static int vboxsf_setup(void) ++{ ++ int err; ++ ++ mutex_lock(&vboxsf_setup_mutex); ++ ++ if (vboxsf_setup_done) ++ goto success; ++ ++ vboxsf_inode_cachep = ++ kmem_cache_create("vboxsf_inode_cache", ++ sizeof(struct vboxsf_inode), 0, ++ (SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD | ++ SLAB_ACCOUNT), ++ vboxsf_inode_init_once); ++ if (!vboxsf_inode_cachep) { ++ err = -ENOMEM; ++ goto fail_nomem; ++ } ++ ++ err = vboxsf_connect(); ++ if (err) { ++ vbg_err("vboxsf: err %d connecting to guest PCI-device\n", err); ++ vbg_err("vboxsf: make sure you are inside a VirtualBox VM\n"); ++ vbg_err("vboxsf: and check dmesg for vboxguest errors\n"); ++ goto fail_free_cache; ++ } ++ ++ err = vboxsf_set_utf8(); ++ if (err) { ++ vbg_err("vboxsf_setutf8 error %d\n", err); ++ goto fail_disconnect; ++ } ++ ++ if (!follow_symlinks) { ++ err = vboxsf_set_symlinks(); ++ if (err) ++ vbg_warn("vboxsf: Unable to show symlinks: %d\n", err); ++ } ++ ++ vboxsf_setup_done = true; ++success: ++ mutex_unlock(&vboxsf_setup_mutex); ++ return 0; ++ ++fail_disconnect: ++ vboxsf_disconnect(); ++fail_free_cache: ++ kmem_cache_destroy(vboxsf_inode_cachep); ++fail_nomem: ++ mutex_unlock(&vboxsf_setup_mutex); ++ return err; ++} ++ ++static int vboxsf_parse_monolithic(struct fs_context *fc, void *data) ++{ ++ char *options = data; ++ ++ if (options && options[0] == VBSF_MOUNT_SIGNATURE_BYTE_0 && ++ options[1] == VBSF_MOUNT_SIGNATURE_BYTE_1 && ++ options[2] == VBSF_MOUNT_SIGNATURE_BYTE_2 && ++ options[3] == VBSF_MOUNT_SIGNATURE_BYTE_3) { ++ vbg_err("vboxsf: Old binary mount data not supported, remove obsolete mount.vboxsf and/or update your VBoxService.\n"); ++ return -EINVAL; ++ } ++ ++ return generic_parse_monolithic(fc, data); ++} ++ ++static int vboxsf_get_tree(struct fs_context *fc) ++{ ++ int err; ++ ++ err = vboxsf_setup(); ++ if (err) ++ return err; ++ ++ return vfs_get_super(fc, vfs_get_independent_super, vboxsf_fill_super); ++} ++ ++static int vboxsf_reconfigure(struct fs_context *fc) ++{ ++ struct vboxsf_sbi *sbi = VBOXSF_SBI(fc->root->d_sb); ++ struct vboxsf_fs_context *ctx = fc->fs_private; ++ struct inode *iroot; ++ ++ iroot = ilookup(fc->root->d_sb, 0); ++ if (!iroot) ++ return -ENOENT; ++ ++ /* Apply changed options to the root inode */ ++ sbi->o = ctx->o; ++ vboxsf_init_inode(sbi, iroot, &sbi->root_info); ++ ++ return 0; ++} ++ ++static void vboxsf_free_fc(struct fs_context *fc) ++{ ++ struct vboxsf_fs_context *ctx = fc->fs_private; ++ ++ kfree(ctx->nls_name); ++ kfree(ctx); ++} ++ ++static const struct fs_context_operations vboxsf_context_ops = { ++ .free = vboxsf_free_fc, ++ .parse_param = vboxsf_parse_param, ++ .parse_monolithic = vboxsf_parse_monolithic, ++ .get_tree = vboxsf_get_tree, ++ .reconfigure = vboxsf_reconfigure, ++}; ++ ++static int vboxsf_init_fs_context(struct fs_context *fc) ++{ ++ struct vboxsf_fs_context *ctx; ++ ++ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); ++ if (!ctx) ++ return -ENOMEM; ++ ++ current_uid_gid(&ctx->o.uid, &ctx->o.gid); ++ ++ fc->fs_private = ctx; ++ fc->ops = &vboxsf_context_ops; ++ return 0; ++} ++ ++static struct file_system_type vboxsf_fs_type = { ++ .owner = THIS_MODULE, ++ .name = "vboxsf", ++ .init_fs_context = vboxsf_init_fs_context, ++ .parameters = &vboxsf_fs_parameters, ++ .kill_sb = kill_anon_super ++}; ++ ++/* Module initialization/finalization handlers */ ++static int __init vboxsf_init(void) ++{ ++ return register_filesystem(&vboxsf_fs_type); ++} ++ ++static void __exit vboxsf_fini(void) ++{ ++ unregister_filesystem(&vboxsf_fs_type); ++ ++ mutex_lock(&vboxsf_setup_mutex); ++ if (vboxsf_setup_done) { ++ vboxsf_disconnect(); ++ /* ++ * Make sure all delayed rcu free inodes are flushed ++ * before we destroy the cache. ++ */ ++ rcu_barrier(); ++ kmem_cache_destroy(vboxsf_inode_cachep); ++ } ++ mutex_unlock(&vboxsf_setup_mutex); ++} ++ ++module_init(vboxsf_init); ++module_exit(vboxsf_fini); ++ ++MODULE_DESCRIPTION("Oracle VM VirtualBox Module for Host File System Access"); ++MODULE_AUTHOR("Oracle Corporation"); ++MODULE_LICENSE("GPL v2"); ++MODULE_ALIAS_FS("vboxsf"); +diff --git a/drivers/staging/vboxsf/utils.c b/drivers/staging/vboxsf/utils.c +new file mode 100644 +index 000000000000..1870b69c824e +--- /dev/null ++++ b/drivers/staging/vboxsf/utils.c +@@ -0,0 +1,550 @@ ++// SPDX-License-Identifier: MIT ++/* ++ * VirtualBox Guest Shared Folders support: Utility functions. ++ * Mainly conversion from/to VirtualBox/Linux data structures. ++ * ++ * Copyright (C) 2006-2018 Oracle Corporation ++ */ ++ ++#include ++#include ++#include ++#include ++#include "vfsmod.h" ++ ++struct inode *vboxsf_new_inode(struct super_block *sb) ++{ ++ struct vboxsf_sbi *sbi = VBOXSF_SBI(sb); ++ struct inode *inode; ++ unsigned long flags; ++ int cursor, ret; ++ u32 gen; ++ ++ inode = new_inode(sb); ++ if (!inode) ++ return ERR_PTR(-ENOMEM); ++ ++ idr_preload(GFP_KERNEL); ++ spin_lock_irqsave(&sbi->ino_idr_lock, flags); ++ cursor = idr_get_cursor(&sbi->ino_idr); ++ ret = idr_alloc_cyclic(&sbi->ino_idr, inode, 1, 0, GFP_ATOMIC); ++ if (ret >= 0 && ret < cursor) ++ sbi->next_generation++; ++ gen = sbi->next_generation; ++ spin_unlock_irqrestore(&sbi->ino_idr_lock, flags); ++ idr_preload_end(); ++ ++ if (ret < 0) { ++ iput(inode); ++ return ERR_PTR(ret); ++ } ++ ++ inode->i_ino = ret; ++ inode->i_generation = gen; ++ return inode; ++} ++ ++/* set [inode] attributes based on [info], uid/gid based on [sbi] */ ++void vboxsf_init_inode(struct vboxsf_sbi *sbi, struct inode *inode, ++ const struct shfl_fsobjinfo *info) ++{ ++ const struct shfl_fsobjattr *attr; ++ s64 allocated; ++ int mode; ++ ++ attr = &info->attr; ++ ++#define mode_set(r) ((attr->mode & (SHFL_UNIX_##r)) ? (S_##r) : 0) ++ ++ mode = mode_set(IRUSR); ++ mode |= mode_set(IWUSR); ++ mode |= mode_set(IXUSR); ++ ++ mode |= mode_set(IRGRP); ++ mode |= mode_set(IWGRP); ++ mode |= mode_set(IXGRP); ++ ++ mode |= mode_set(IROTH); ++ mode |= mode_set(IWOTH); ++ mode |= mode_set(IXOTH); ++ ++#undef mode_set ++ ++ /* We use the host-side values for these */ ++ inode->i_flags |= S_NOATIME | S_NOCMTIME; ++ inode->i_mapping->a_ops = &vboxsf_reg_aops; ++ ++ if (SHFL_IS_DIRECTORY(attr->mode)) { ++ inode->i_mode = sbi->o.dmode_set ? sbi->o.dmode : mode; ++ inode->i_mode &= ~sbi->o.dmask; ++ inode->i_mode |= S_IFDIR; ++ inode->i_op = &vboxsf_dir_iops; ++ inode->i_fop = &vboxsf_dir_fops; ++ /* ++ * XXX: this probably should be set to the number of entries ++ * in the directory plus two (. ..) ++ */ ++ set_nlink(inode, 1); ++ } else if (SHFL_IS_SYMLINK(attr->mode)) { ++ inode->i_mode = sbi->o.fmode_set ? sbi->o.fmode : mode; ++ inode->i_mode &= ~sbi->o.fmask; ++ inode->i_mode |= S_IFLNK; ++ inode->i_op = &vboxsf_lnk_iops; ++ set_nlink(inode, 1); ++ } else { ++ inode->i_mode = sbi->o.fmode_set ? sbi->o.fmode : mode; ++ inode->i_mode &= ~sbi->o.fmask; ++ inode->i_mode |= S_IFREG; ++ inode->i_op = &vboxsf_reg_iops; ++ inode->i_fop = &vboxsf_reg_fops; ++ set_nlink(inode, 1); ++ } ++ ++ inode->i_uid = sbi->o.uid; ++ inode->i_gid = sbi->o.gid; ++ ++ inode->i_size = info->size; ++ inode->i_blkbits = 12; ++ /* i_blocks always in units of 512 bytes! */ ++ allocated = info->allocated + 511; ++ do_div(allocated, 512); ++ inode->i_blocks = allocated; ++ ++ inode->i_atime = ns_to_timespec64( ++ info->access_time.ns_relative_to_unix_epoch); ++ inode->i_ctime = ns_to_timespec64( ++ info->change_time.ns_relative_to_unix_epoch); ++ inode->i_mtime = ns_to_timespec64( ++ info->modification_time.ns_relative_to_unix_epoch); ++} ++ ++int vboxsf_create_at_dentry(struct dentry *dentry, ++ struct shfl_createparms *params) ++{ ++ struct vboxsf_sbi *sbi = VBOXSF_SBI(dentry->d_sb); ++ struct shfl_string *path; ++ int err; ++ ++ path = vboxsf_path_from_dentry(sbi, dentry); ++ if (IS_ERR(path)) ++ return PTR_ERR(path); ++ ++ err = vboxsf_create(sbi->root, path, params); ++ __putname(path); ++ ++ return err; ++} ++ ++int vboxsf_stat(struct vboxsf_sbi *sbi, struct shfl_string *path, ++ struct shfl_fsobjinfo *info) ++{ ++ struct shfl_createparms params = {}; ++ int err; ++ ++ params.handle = SHFL_HANDLE_NIL; ++ params.create_flags = SHFL_CF_LOOKUP | SHFL_CF_ACT_FAIL_IF_NEW; ++ ++ err = vboxsf_create(sbi->root, path, ¶ms); ++ if (err) ++ return err; ++ ++ if (params.result != SHFL_FILE_EXISTS) ++ return -ENOENT; ++ ++ if (info) ++ *info = params.info; ++ ++ return 0; ++} ++ ++int vboxsf_stat_dentry(struct dentry *dentry, struct shfl_fsobjinfo *info) ++{ ++ struct vboxsf_sbi *sbi = VBOXSF_SBI(dentry->d_sb); ++ struct shfl_string *path; ++ int err; ++ ++ path = vboxsf_path_from_dentry(sbi, dentry); ++ if (IS_ERR(path)) ++ return PTR_ERR(path); ++ ++ err = vboxsf_stat(sbi, path, info); ++ __putname(path); ++ return err; ++} ++ ++int vboxsf_inode_revalidate(struct dentry *dentry) ++{ ++ struct vboxsf_sbi *sbi = VBOXSF_SBI(dentry->d_sb); ++ struct vboxsf_inode *sf_i; ++ struct shfl_fsobjinfo info; ++ struct timespec64 prev_mtime; ++ struct inode *inode; ++ int err; ++ ++ if (!dentry || !d_really_is_positive(dentry)) ++ return -EINVAL; ++ ++ inode = d_inode(dentry); ++ prev_mtime = inode->i_mtime; ++ sf_i = VBOXSF_I(inode); ++ if (!sf_i->force_restat) { ++ if (time_before(jiffies, dentry->d_time + sbi->o.ttl)) ++ return 0; ++ } ++ ++ err = vboxsf_stat_dentry(dentry, &info); ++ if (err) ++ return err; ++ ++ dentry->d_time = jiffies; ++ sf_i->force_restat = 0; ++ vboxsf_init_inode(sbi, inode, &info); ++ ++ /* ++ * If the file was changed on the host side we need to invalidate the ++ * page-cache for it. Note this also gets triggered by our own writes, ++ * this is unavoidable. ++ */ ++ if (timespec64_compare(&inode->i_mtime, &prev_mtime) > 0) ++ invalidate_inode_pages2(inode->i_mapping); ++ ++ return 0; ++} ++ ++int vboxsf_getattr(const struct path *path, struct kstat *kstat, ++ u32 request_mask, unsigned int flags) ++{ ++ int err; ++ struct dentry *dentry = path->dentry; ++ struct inode *inode = d_inode(dentry); ++ struct vboxsf_inode *sf_i = VBOXSF_I(inode); ++ ++ switch (flags & AT_STATX_SYNC_TYPE) { ++ case AT_STATX_DONT_SYNC: ++ err = 0; ++ break; ++ case AT_STATX_FORCE_SYNC: ++ sf_i->force_restat = 1; ++ /* fall-through */ ++ default: ++ err = vboxsf_inode_revalidate(dentry); ++ } ++ if (err) ++ return err; ++ ++ generic_fillattr(d_inode(dentry), kstat); ++ return 0; ++} ++ ++int vboxsf_setattr(struct dentry *dentry, struct iattr *iattr) ++{ ++ struct vboxsf_inode *sf_i = VBOXSF_I(d_inode(dentry)); ++ struct vboxsf_sbi *sbi = VBOXSF_SBI(dentry->d_sb); ++ struct shfl_createparms params = {}; ++ struct shfl_fsobjinfo info = {}; ++ u32 buf_len; ++ int err; ++ ++ params.handle = SHFL_HANDLE_NIL; ++ params.create_flags = SHFL_CF_ACT_OPEN_IF_EXISTS | ++ SHFL_CF_ACT_FAIL_IF_NEW | ++ SHFL_CF_ACCESS_ATTR_WRITE; ++ ++ /* this is at least required for Posix hosts */ ++ if (iattr->ia_valid & ATTR_SIZE) ++ params.create_flags |= SHFL_CF_ACCESS_WRITE; ++ ++ err = vboxsf_create_at_dentry(dentry, ¶ms); ++ if (err || params.result != SHFL_FILE_EXISTS) ++ return err ? err : -ENOENT; ++ ++#define mode_set(r) ((iattr->ia_mode & (S_##r)) ? SHFL_UNIX_##r : 0) ++ ++ /* ++ * Setting the file size and setting the other attributes has to ++ * be handled separately. ++ */ ++ if (iattr->ia_valid & (ATTR_MODE | ATTR_ATIME | ATTR_MTIME)) { ++ if (iattr->ia_valid & ATTR_MODE) { ++ info.attr.mode = mode_set(IRUSR); ++ info.attr.mode |= mode_set(IWUSR); ++ info.attr.mode |= mode_set(IXUSR); ++ info.attr.mode |= mode_set(IRGRP); ++ info.attr.mode |= mode_set(IWGRP); ++ info.attr.mode |= mode_set(IXGRP); ++ info.attr.mode |= mode_set(IROTH); ++ info.attr.mode |= mode_set(IWOTH); ++ info.attr.mode |= mode_set(IXOTH); ++ ++ if (iattr->ia_mode & S_IFDIR) ++ info.attr.mode |= SHFL_TYPE_DIRECTORY; ++ else ++ info.attr.mode |= SHFL_TYPE_FILE; ++ } ++ ++ if (iattr->ia_valid & ATTR_ATIME) ++ info.access_time.ns_relative_to_unix_epoch = ++ timespec64_to_ns(&iattr->ia_atime); ++ ++ if (iattr->ia_valid & ATTR_MTIME) ++ info.modification_time.ns_relative_to_unix_epoch = ++ timespec64_to_ns(&iattr->ia_mtime); ++ ++ /* ++ * Ignore ctime (inode change time) as it can't be set ++ * from userland anyway. ++ */ ++ ++ buf_len = sizeof(info); ++ err = vboxsf_fsinfo(sbi->root, params.handle, ++ SHFL_INFO_SET | SHFL_INFO_FILE, &buf_len, ++ &info); ++ if (err) { ++ vboxsf_close(sbi->root, params.handle); ++ return err; ++ } ++ ++ /* the host may have given us different attr then requested */ ++ sf_i->force_restat = 1; ++ } ++ ++#undef mode_set ++ ++ if (iattr->ia_valid & ATTR_SIZE) { ++ memset(&info, 0, sizeof(info)); ++ info.size = iattr->ia_size; ++ buf_len = sizeof(info); ++ err = vboxsf_fsinfo(sbi->root, params.handle, ++ SHFL_INFO_SET | SHFL_INFO_SIZE, &buf_len, ++ &info); ++ if (err) { ++ vboxsf_close(sbi->root, params.handle); ++ return err; ++ } ++ ++ /* the host may have given us different attr then requested */ ++ sf_i->force_restat = 1; ++ } ++ ++ vboxsf_close(sbi->root, params.handle); ++ ++ /* Update the inode with what the host has actually given us. */ ++ if (sf_i->force_restat) ++ vboxsf_inode_revalidate(dentry); ++ ++ return 0; ++} ++ ++/* ++ * [dentry] contains string encoded in coding system that corresponds ++ * to [sbi]->nls, we must convert it to UTF8 here. ++ * Returns a shfl_string allocated through __getname (must be freed using ++ * __putname), or an ERR_PTR on error. ++ */ ++struct shfl_string *vboxsf_path_from_dentry(struct vboxsf_sbi *sbi, ++ struct dentry *dentry) ++{ ++ struct shfl_string *shfl_path; ++ int path_len, out_len, nb; ++ char *buf, *path; ++ wchar_t uni; ++ u8 *out; ++ ++ buf = __getname(); ++ if (!buf) ++ return ERR_PTR(-ENOMEM); ++ ++ path = dentry_path_raw(dentry, buf, PATH_MAX); ++ if (IS_ERR(path)) { ++ __putname(buf); ++ return (struct shfl_string *)path; ++ } ++ path_len = strlen(path); ++ ++ if (sbi->nls) { ++ shfl_path = __getname(); ++ if (!shfl_path) { ++ __putname(buf); ++ return ERR_PTR(-ENOMEM); ++ } ++ ++ out = shfl_path->string.utf8; ++ out_len = PATH_MAX - SHFLSTRING_HEADER_SIZE - 1; ++ ++ while (path_len) { ++ nb = sbi->nls->char2uni(path, path_len, &uni); ++ if (nb < 0) { ++ __putname(shfl_path); ++ __putname(buf); ++ return ERR_PTR(-EINVAL); ++ } ++ path += nb; ++ path_len -= nb; ++ ++ nb = utf32_to_utf8(uni, out, out_len); ++ if (nb < 0) { ++ __putname(shfl_path); ++ __putname(buf); ++ return ERR_PTR(-ENAMETOOLONG); ++ } ++ out += nb; ++ out_len -= nb; ++ } ++ *out = 0; ++ shfl_path->length = out - shfl_path->string.utf8; ++ shfl_path->size = shfl_path->length + 1; ++ __putname(buf); ++ } else { ++ if ((SHFLSTRING_HEADER_SIZE + path_len + 1) > PATH_MAX) { ++ __putname(buf); ++ return ERR_PTR(-ENAMETOOLONG); ++ } ++ /* ++ * dentry_path stores the name at the end of buf, but the ++ * shfl_string string we return must be properly aligned. ++ */ ++ shfl_path = (struct shfl_string *)buf; ++ memmove(shfl_path->string.utf8, path, path_len); ++ shfl_path->string.utf8[path_len] = 0; ++ shfl_path->length = path_len; ++ shfl_path->size = path_len + 1; ++ } ++ ++ return shfl_path; ++} ++ ++int vboxsf_nlscpy(struct vboxsf_sbi *sbi, char *name, size_t name_bound_len, ++ const unsigned char *utf8_name, size_t utf8_len) ++{ ++ const char *in; ++ char *out; ++ size_t out_len; ++ size_t out_bound_len; ++ size_t in_bound_len; ++ ++ in = utf8_name; ++ in_bound_len = utf8_len; ++ ++ out = name; ++ out_len = 0; ++ /* Reserve space for terminating 0 */ ++ out_bound_len = name_bound_len - 1; ++ ++ while (in_bound_len) { ++ int nb; ++ unicode_t uni; ++ ++ nb = utf8_to_utf32(in, in_bound_len, &uni); ++ if (nb < 0) ++ return -EINVAL; ++ ++ in += nb; ++ in_bound_len -= nb; ++ ++ nb = sbi->nls->uni2char(uni, out, out_bound_len); ++ if (nb < 0) ++ return nb; ++ ++ out += nb; ++ out_bound_len -= nb; ++ out_len += nb; ++ } ++ ++ *out = 0; ++ ++ return 0; ++} ++ ++static struct vboxsf_dir_buf *vboxsf_dir_buf_alloc(struct list_head *list) ++{ ++ struct vboxsf_dir_buf *b; ++ ++ b = kmalloc(sizeof(*b), GFP_KERNEL); ++ if (!b) ++ return NULL; ++ ++ b->buf = kmalloc(DIR_BUFFER_SIZE, GFP_KERNEL); ++ if (!b->buf) { ++ kfree(b); ++ return NULL; ++ } ++ ++ b->entries = 0; ++ b->used = 0; ++ b->free = DIR_BUFFER_SIZE; ++ list_add(&b->head, list); ++ ++ return b; ++} ++ ++static void vboxsf_dir_buf_free(struct vboxsf_dir_buf *b) ++{ ++ list_del(&b->head); ++ kfree(b->buf); ++ kfree(b); ++} ++ ++struct vboxsf_dir_info *vboxsf_dir_info_alloc(void) ++{ ++ struct vboxsf_dir_info *p; ++ ++ p = kmalloc(sizeof(*p), GFP_KERNEL); ++ if (!p) ++ return NULL; ++ ++ INIT_LIST_HEAD(&p->info_list); ++ return p; ++} ++ ++void vboxsf_dir_info_free(struct vboxsf_dir_info *p) ++{ ++ struct list_head *list, *pos, *tmp; ++ ++ list = &p->info_list; ++ list_for_each_safe(pos, tmp, list) { ++ struct vboxsf_dir_buf *b; ++ ++ b = list_entry(pos, struct vboxsf_dir_buf, head); ++ vboxsf_dir_buf_free(b); ++ } ++ kfree(p); ++} ++ ++int vboxsf_dir_read_all(struct vboxsf_sbi *sbi, struct vboxsf_dir_info *sf_d, ++ u64 handle) ++{ ++ struct vboxsf_dir_buf *b; ++ u32 entries, size; ++ int err = 0; ++ void *buf; ++ ++ /* vboxsf_dirinfo returns 1 on end of dir */ ++ while (err == 0) { ++ b = vboxsf_dir_buf_alloc(&sf_d->info_list); ++ if (!b) { ++ err = -ENOMEM; ++ break; ++ } ++ ++ buf = b->buf; ++ size = b->free; ++ ++ err = vboxsf_dirinfo(sbi->root, handle, NULL, 0, 0, ++ &size, buf, &entries); ++ if (err < 0) ++ break; ++ ++ b->entries += entries; ++ b->free -= size; ++ b->used += size; ++ } ++ ++ if (b && b->used == 0) ++ vboxsf_dir_buf_free(b); ++ ++ /* -EILSEQ means the host could not translate a filename, ignore */ ++ if (err > 0 || err == -EILSEQ) ++ err = 0; ++ ++ return err; ++} +diff --git a/drivers/staging/vboxsf/vboxsf_wrappers.c b/drivers/staging/vboxsf/vboxsf_wrappers.c +new file mode 100644 +index 000000000000..bfc78a097dae +--- /dev/null ++++ b/drivers/staging/vboxsf/vboxsf_wrappers.c +@@ -0,0 +1,371 @@ ++// SPDX-License-Identifier: MIT ++/* ++ * Wrapper functions for the shfl host calls. ++ * ++ * Copyright (C) 2006-2018 Oracle Corporation ++ */ ++ ++#include ++#include ++#include ++#include ++#include "vfsmod.h" ++ ++#define SHFL_REQUEST \ ++ (VMMDEV_REQUESTOR_KERNEL | VMMDEV_REQUESTOR_USR_DRV_OTHER | \ ++ VMMDEV_REQUESTOR_CON_DONT_KNOW | VMMDEV_REQUESTOR_TRUST_NOT_GIVEN) ++ ++static u32 vboxsf_client_id; ++ ++int vboxsf_connect(void) ++{ ++ struct vbg_dev *gdev; ++ struct vmmdev_hgcm_service_location loc; ++ int err, vbox_status; ++ ++ loc.type = VMMDEV_HGCM_LOC_LOCALHOST_EXISTING; ++ strcpy(loc.u.localhost.service_name, "VBoxSharedFolders"); ++ ++ gdev = vbg_get_gdev(); ++ if (IS_ERR(gdev)) ++ return -ENODEV; /* No guest-device */ ++ ++ err = vbg_hgcm_connect(gdev, SHFL_REQUEST, &loc, ++ &vboxsf_client_id, &vbox_status); ++ vbg_put_gdev(gdev); ++ ++ return err ? err : vbg_status_code_to_errno(vbox_status); ++} ++ ++void vboxsf_disconnect(void) ++{ ++ struct vbg_dev *gdev; ++ int vbox_status; ++ ++ gdev = vbg_get_gdev(); ++ if (IS_ERR(gdev)) ++ return; /* guest-device is gone, already disconnected */ ++ ++ vbg_hgcm_disconnect(gdev, SHFL_REQUEST, vboxsf_client_id, &vbox_status); ++ vbg_put_gdev(gdev); ++} ++ ++static int vboxsf_call(u32 function, void *parms, u32 parm_count, int *status) ++{ ++ struct vbg_dev *gdev; ++ int err, vbox_status; ++ ++ gdev = vbg_get_gdev(); ++ if (IS_ERR(gdev)) ++ return -ESHUTDOWN; /* guest-dev removed underneath us */ ++ ++ err = vbg_hgcm_call(gdev, SHFL_REQUEST, vboxsf_client_id, function, ++ U32_MAX, parms, parm_count, &vbox_status); ++ vbg_put_gdev(gdev); ++ ++ if (err < 0) ++ return err; ++ ++ if (status) ++ *status = vbox_status; ++ ++ return vbg_status_code_to_errno(vbox_status); ++} ++ ++int vboxsf_map_folder(struct shfl_string *folder_name, u32 *root) ++{ ++ struct shfl_map_folder parms; ++ int err, status; ++ ++ parms.path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL; ++ parms.path.u.pointer.size = shfl_string_buf_size(folder_name); ++ parms.path.u.pointer.u.linear_addr = (uintptr_t)folder_name; ++ ++ parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; ++ parms.root.u.value32 = 0; ++ ++ parms.delimiter.type = VMMDEV_HGCM_PARM_TYPE_32BIT; ++ parms.delimiter.u.value32 = '/'; ++ ++ parms.case_sensitive.type = VMMDEV_HGCM_PARM_TYPE_32BIT; ++ parms.case_sensitive.u.value32 = 1; ++ ++ err = vboxsf_call(SHFL_FN_MAP_FOLDER, &parms, SHFL_CPARMS_MAP_FOLDER, ++ &status); ++ if (err == -ENOSYS && status == VERR_NOT_IMPLEMENTED) ++ vbg_err("%s: Error host is too old\n", __func__); ++ ++ *root = parms.root.u.value32; ++ return err; ++} ++ ++int vboxsf_unmap_folder(u32 root) ++{ ++ struct shfl_unmap_folder parms; ++ ++ parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; ++ parms.root.u.value32 = root; ++ ++ return vboxsf_call(SHFL_FN_UNMAP_FOLDER, &parms, ++ SHFL_CPARMS_UNMAP_FOLDER, NULL); ++} ++ ++/** ++ * vboxsf_create - Create a new file or folder ++ * @root: Root of the shared folder in which to create the file ++ * @parsed_path: The path of the file or folder relative to the shared folder ++ * @param: create_parms Parameters for file/folder creation. ++ * ++ * Create a new file or folder or open an existing one in a shared folder. ++ * Note this function always returns 0 / success unless an exceptional condition ++ * occurs - out of memory, invalid arguments, etc. If the file or folder could ++ * not be opened or created, create_parms->handle will be set to ++ * SHFL_HANDLE_NIL on return. In this case the value in create_parms->result ++ * provides information as to why (e.g. SHFL_FILE_EXISTS), create_parms->result ++ * is also set on success as additional information. ++ * ++ * Returns: ++ * 0 or negative errno value. ++ */ ++int vboxsf_create(u32 root, struct shfl_string *parsed_path, ++ struct shfl_createparms *create_parms) ++{ ++ struct shfl_create parms; ++ ++ parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; ++ parms.root.u.value32 = root; ++ ++ parms.path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL; ++ parms.path.u.pointer.size = shfl_string_buf_size(parsed_path); ++ parms.path.u.pointer.u.linear_addr = (uintptr_t)parsed_path; ++ ++ parms.parms.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL; ++ parms.parms.u.pointer.size = sizeof(struct shfl_createparms); ++ parms.parms.u.pointer.u.linear_addr = (uintptr_t)create_parms; ++ ++ return vboxsf_call(SHFL_FN_CREATE, &parms, SHFL_CPARMS_CREATE, NULL); ++} ++ ++int vboxsf_close(u32 root, u64 handle) ++{ ++ struct shfl_close parms; ++ ++ parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; ++ parms.root.u.value32 = root; ++ ++ parms.handle.type = VMMDEV_HGCM_PARM_TYPE_64BIT; ++ parms.handle.u.value64 = handle; ++ ++ return vboxsf_call(SHFL_FN_CLOSE, &parms, SHFL_CPARMS_CLOSE, NULL); ++} ++ ++int vboxsf_remove(u32 root, struct shfl_string *parsed_path, u32 flags) ++{ ++ struct shfl_remove parms; ++ ++ parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; ++ parms.root.u.value32 = root; ++ ++ parms.path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN; ++ parms.path.u.pointer.size = shfl_string_buf_size(parsed_path); ++ parms.path.u.pointer.u.linear_addr = (uintptr_t)parsed_path; ++ ++ parms.flags.type = VMMDEV_HGCM_PARM_TYPE_32BIT; ++ parms.flags.u.value32 = flags; ++ ++ return vboxsf_call(SHFL_FN_REMOVE, &parms, SHFL_CPARMS_REMOVE, NULL); ++} ++ ++int vboxsf_rename(u32 root, struct shfl_string *src_path, ++ struct shfl_string *dest_path, u32 flags) ++{ ++ struct shfl_rename parms; ++ ++ parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; ++ parms.root.u.value32 = root; ++ ++ parms.src.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN; ++ parms.src.u.pointer.size = shfl_string_buf_size(src_path); ++ parms.src.u.pointer.u.linear_addr = (uintptr_t)src_path; ++ ++ parms.dest.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN; ++ parms.dest.u.pointer.size = shfl_string_buf_size(dest_path); ++ parms.dest.u.pointer.u.linear_addr = (uintptr_t)dest_path; ++ ++ parms.flags.type = VMMDEV_HGCM_PARM_TYPE_32BIT; ++ parms.flags.u.value32 = flags; ++ ++ return vboxsf_call(SHFL_FN_RENAME, &parms, SHFL_CPARMS_RENAME, NULL); ++} ++ ++int vboxsf_read(u32 root, u64 handle, u64 offset, u32 *buf_len, u8 *buf) ++{ ++ struct shfl_read parms; ++ int err; ++ ++ parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; ++ parms.root.u.value32 = root; ++ ++ parms.handle.type = VMMDEV_HGCM_PARM_TYPE_64BIT; ++ parms.handle.u.value64 = handle; ++ parms.offset.type = VMMDEV_HGCM_PARM_TYPE_64BIT; ++ parms.offset.u.value64 = offset; ++ parms.cb.type = VMMDEV_HGCM_PARM_TYPE_32BIT; ++ parms.cb.u.value32 = *buf_len; ++ parms.buffer.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_OUT; ++ parms.buffer.u.pointer.size = *buf_len; ++ parms.buffer.u.pointer.u.linear_addr = (uintptr_t)buf; ++ ++ err = vboxsf_call(SHFL_FN_READ, &parms, SHFL_CPARMS_READ, NULL); ++ ++ *buf_len = parms.cb.u.value32; ++ return err; ++} ++ ++int vboxsf_write(u32 root, u64 handle, u64 offset, u32 *buf_len, u8 *buf) ++{ ++ struct shfl_write parms; ++ int err; ++ ++ parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; ++ parms.root.u.value32 = root; ++ ++ parms.handle.type = VMMDEV_HGCM_PARM_TYPE_64BIT; ++ parms.handle.u.value64 = handle; ++ parms.offset.type = VMMDEV_HGCM_PARM_TYPE_64BIT; ++ parms.offset.u.value64 = offset; ++ parms.cb.type = VMMDEV_HGCM_PARM_TYPE_32BIT; ++ parms.cb.u.value32 = *buf_len; ++ parms.buffer.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN; ++ parms.buffer.u.pointer.size = *buf_len; ++ parms.buffer.u.pointer.u.linear_addr = (uintptr_t)buf; ++ ++ err = vboxsf_call(SHFL_FN_WRITE, &parms, SHFL_CPARMS_WRITE, NULL); ++ ++ *buf_len = parms.cb.u.value32; ++ return err; ++} ++ ++/* Returns 0 on success, 1 on end-of-dir, negative errno otherwise */ ++int vboxsf_dirinfo(u32 root, u64 handle, ++ struct shfl_string *parsed_path, u32 flags, u32 index, ++ u32 *buf_len, struct shfl_dirinfo *buf, u32 *file_count) ++{ ++ struct shfl_list parms; ++ int err, status; ++ ++ parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; ++ parms.root.u.value32 = root; ++ ++ parms.handle.type = VMMDEV_HGCM_PARM_TYPE_64BIT; ++ parms.handle.u.value64 = handle; ++ parms.flags.type = VMMDEV_HGCM_PARM_TYPE_32BIT; ++ parms.flags.u.value32 = flags; ++ parms.cb.type = VMMDEV_HGCM_PARM_TYPE_32BIT; ++ parms.cb.u.value32 = *buf_len; ++ if (parsed_path) { ++ parms.path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN; ++ parms.path.u.pointer.size = shfl_string_buf_size(parsed_path); ++ parms.path.u.pointer.u.linear_addr = (uintptr_t)parsed_path; ++ } else { ++ parms.path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_IN; ++ parms.path.u.pointer.size = 0; ++ parms.path.u.pointer.u.linear_addr = 0; ++ } ++ ++ parms.buffer.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_OUT; ++ parms.buffer.u.pointer.size = *buf_len; ++ parms.buffer.u.pointer.u.linear_addr = (uintptr_t)buf; ++ ++ parms.resume_point.type = VMMDEV_HGCM_PARM_TYPE_32BIT; ++ parms.resume_point.u.value32 = index; ++ parms.file_count.type = VMMDEV_HGCM_PARM_TYPE_32BIT; ++ parms.file_count.u.value32 = 0; /* out parameter only */ ++ ++ err = vboxsf_call(SHFL_FN_LIST, &parms, SHFL_CPARMS_LIST, &status); ++ if (err == -ENODATA && status == VERR_NO_MORE_FILES) ++ err = 1; ++ ++ *buf_len = parms.cb.u.value32; ++ *file_count = parms.file_count.u.value32; ++ return err; ++} ++ ++int vboxsf_fsinfo(u32 root, u64 handle, u32 flags, ++ u32 *buf_len, void *buf) ++{ ++ struct shfl_information parms; ++ int err; ++ ++ parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; ++ parms.root.u.value32 = root; ++ ++ parms.handle.type = VMMDEV_HGCM_PARM_TYPE_64BIT; ++ parms.handle.u.value64 = handle; ++ parms.flags.type = VMMDEV_HGCM_PARM_TYPE_32BIT; ++ parms.flags.u.value32 = flags; ++ parms.cb.type = VMMDEV_HGCM_PARM_TYPE_32BIT; ++ parms.cb.u.value32 = *buf_len; ++ parms.info.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL; ++ parms.info.u.pointer.size = *buf_len; ++ parms.info.u.pointer.u.linear_addr = (uintptr_t)buf; ++ ++ err = vboxsf_call(SHFL_FN_INFORMATION, &parms, SHFL_CPARMS_INFORMATION, ++ NULL); ++ ++ *buf_len = parms.cb.u.value32; ++ return err; ++} ++ ++int vboxsf_readlink(u32 root, struct shfl_string *parsed_path, ++ u32 buf_len, u8 *buf) ++{ ++ struct shfl_readLink parms; ++ ++ parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; ++ parms.root.u.value32 = root; ++ ++ parms.path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN; ++ parms.path.u.pointer.size = shfl_string_buf_size(parsed_path); ++ parms.path.u.pointer.u.linear_addr = (uintptr_t)parsed_path; ++ ++ parms.buffer.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_OUT; ++ parms.buffer.u.pointer.size = buf_len; ++ parms.buffer.u.pointer.u.linear_addr = (uintptr_t)buf; ++ ++ return vboxsf_call(SHFL_FN_READLINK, &parms, SHFL_CPARMS_READLINK, ++ NULL); ++} ++ ++int vboxsf_symlink(u32 root, struct shfl_string *new_path, ++ struct shfl_string *old_path, struct shfl_fsobjinfo *buf) ++{ ++ struct shfl_symlink parms; ++ ++ parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; ++ parms.root.u.value32 = root; ++ ++ parms.new_path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN; ++ parms.new_path.u.pointer.size = shfl_string_buf_size(new_path); ++ parms.new_path.u.pointer.u.linear_addr = (uintptr_t)new_path; ++ ++ parms.old_path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN; ++ parms.old_path.u.pointer.size = shfl_string_buf_size(old_path); ++ parms.old_path.u.pointer.u.linear_addr = (uintptr_t)old_path; ++ ++ parms.info.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_OUT; ++ parms.info.u.pointer.size = sizeof(struct shfl_fsobjinfo); ++ parms.info.u.pointer.u.linear_addr = (uintptr_t)buf; ++ ++ return vboxsf_call(SHFL_FN_SYMLINK, &parms, SHFL_CPARMS_SYMLINK, NULL); ++} ++ ++int vboxsf_set_utf8(void) ++{ ++ return vboxsf_call(SHFL_FN_SET_UTF8, NULL, 0, NULL); ++} ++ ++int vboxsf_set_symlinks(void) ++{ ++ return vboxsf_call(SHFL_FN_SET_SYMLINKS, NULL, 0, NULL); ++} +diff --git a/drivers/staging/vboxsf/vfsmod.h b/drivers/staging/vboxsf/vfsmod.h +new file mode 100644 +index 000000000000..de650d65fbe4 +--- /dev/null ++++ b/drivers/staging/vboxsf/vfsmod.h +@@ -0,0 +1,138 @@ ++/* SPDX-License-Identifier: MIT */ ++/* ++ * VirtualBox Guest Shared Folders support: module header. ++ * ++ * Copyright (C) 2006-2018 Oracle Corporation ++ */ ++ ++#ifndef VFSMOD_H ++#define VFSMOD_H ++ ++#include ++#include ++#include ++#include "shfl_hostintf.h" ++ ++#define DIR_BUFFER_SIZE SZ_16K ++ ++/* The cast is to prevent assignment of void * to pointers of arbitrary type */ ++#define VBOXSF_SBI(sb) ((struct vboxsf_sbi *)(sb)->s_fs_info) ++#define VBOXSF_I(i) container_of(i, struct vboxsf_inode, vfs_inode) ++ ++struct vboxsf_options { ++ unsigned long ttl; ++ kuid_t uid; ++ kgid_t gid; ++ bool dmode_set; ++ bool fmode_set; ++ umode_t dmode; ++ umode_t fmode; ++ umode_t dmask; ++ umode_t fmask; ++}; ++ ++struct vboxsf_fs_context { ++ struct vboxsf_options o; ++ char *nls_name; ++}; ++ ++/* per-shared folder information */ ++struct vboxsf_sbi { ++ struct vboxsf_options o; ++ struct shfl_fsobjinfo root_info; ++ struct idr ino_idr; ++ spinlock_t ino_idr_lock; /* This protects ino_idr */ ++ struct nls_table *nls; ++ u32 next_generation; ++ u32 root; ++ int bdi_id; ++}; ++ ++/* per-inode information */ ++struct vboxsf_inode { ++ /* some information was changed, update data on next revalidate */ ++ int force_restat; ++ /* list of open handles for this inode + lock protecting it */ ++ struct list_head handle_list; ++ /* This mutex protects handle_list accesses */ ++ struct mutex handle_list_mutex; ++ /* The VFS inode struct */ ++ struct inode vfs_inode; ++}; ++ ++struct vboxsf_dir_info { ++ struct list_head info_list; ++}; ++ ++struct vboxsf_dir_buf { ++ size_t entries; ++ size_t free; ++ size_t used; ++ void *buf; ++ struct list_head head; ++}; ++ ++/* globals */ ++extern const struct inode_operations vboxsf_dir_iops; ++extern const struct inode_operations vboxsf_lnk_iops; ++extern const struct inode_operations vboxsf_reg_iops; ++extern const struct file_operations vboxsf_dir_fops; ++extern const struct file_operations vboxsf_reg_fops; ++extern const struct address_space_operations vboxsf_reg_aops; ++extern const struct dentry_operations vboxsf_dentry_ops; ++ ++/* from utils.c */ ++struct inode *vboxsf_new_inode(struct super_block *sb); ++void vboxsf_init_inode(struct vboxsf_sbi *sbi, struct inode *inode, ++ const struct shfl_fsobjinfo *info); ++int vboxsf_create_at_dentry(struct dentry *dentry, ++ struct shfl_createparms *params); ++int vboxsf_stat(struct vboxsf_sbi *sbi, struct shfl_string *path, ++ struct shfl_fsobjinfo *info); ++int vboxsf_stat_dentry(struct dentry *dentry, struct shfl_fsobjinfo *info); ++int vboxsf_inode_revalidate(struct dentry *dentry); ++int vboxsf_getattr(const struct path *path, struct kstat *kstat, ++ u32 request_mask, unsigned int query_flags); ++int vboxsf_setattr(struct dentry *dentry, struct iattr *iattr); ++struct shfl_string *vboxsf_path_from_dentry(struct vboxsf_sbi *sbi, ++ struct dentry *dentry); ++int vboxsf_nlscpy(struct vboxsf_sbi *sbi, char *name, size_t name_bound_len, ++ const unsigned char *utf8_name, size_t utf8_len); ++struct vboxsf_dir_info *vboxsf_dir_info_alloc(void); ++void vboxsf_dir_info_free(struct vboxsf_dir_info *p); ++int vboxsf_dir_read_all(struct vboxsf_sbi *sbi, struct vboxsf_dir_info *sf_d, ++ u64 handle); ++ ++/* from vboxsf_wrappers.c */ ++int vboxsf_connect(void); ++void vboxsf_disconnect(void); ++ ++int vboxsf_create(u32 root, struct shfl_string *parsed_path, ++ struct shfl_createparms *create_parms); ++ ++int vboxsf_close(u32 root, u64 handle); ++int vboxsf_remove(u32 root, struct shfl_string *parsed_path, u32 flags); ++int vboxsf_rename(u32 root, struct shfl_string *src_path, ++ struct shfl_string *dest_path, u32 flags); ++ ++int vboxsf_read(u32 root, u64 handle, u64 offset, u32 *buf_len, u8 *buf); ++int vboxsf_write(u32 root, u64 handle, u64 offset, u32 *buf_len, u8 *buf); ++ ++int vboxsf_dirinfo(u32 root, u64 handle, ++ struct shfl_string *parsed_path, u32 flags, u32 index, ++ u32 *buf_len, struct shfl_dirinfo *buf, u32 *file_count); ++int vboxsf_fsinfo(u32 root, u64 handle, u32 flags, ++ u32 *buf_len, void *buf); ++ ++int vboxsf_map_folder(struct shfl_string *folder_name, u32 *root); ++int vboxsf_unmap_folder(u32 root); ++ ++int vboxsf_readlink(u32 root, struct shfl_string *parsed_path, ++ u32 buf_len, u8 *buf); ++int vboxsf_symlink(u32 root, struct shfl_string *new_path, ++ struct shfl_string *old_path, struct shfl_fsobjinfo *buf); ++ ++int vboxsf_set_utf8(void); ++int vboxsf_set_symlinks(void); ++ ++#endif +-- +cgit 1.2-0.3.lf.el7 + diff --git a/kernel/kernel/files/patches/pisilinux/kernel-5.4-build-fix.patch b/kernel/kernel/files/patches/pisilinux/kernel-5.4-build-fix.patch new file mode 100644 index 00000000..c1de3106 --- /dev/null +++ b/kernel/kernel/files/patches/pisilinux/kernel-5.4-build-fix.patch @@ -0,0 +1,18 @@ +--- a/Makefile.orig 2019-11-25 03:32:01.000000000 +0300 ++++ b/Makefile 2019-12-11 03:20:12.876664698 +0300 +@@ -509,15 +509,6 @@ + # ignore whole output directory + outputmakefile: + ifdef building_out_of_srctree +- $(Q)if [ -f $(srctree)/.config -o \ +- -d $(srctree)/include/config -o \ +- -d $(srctree)/arch/$(SRCARCH)/include/generated ]; then \ +- echo >&2 "***"; \ +- echo >&2 "*** The source tree is not clean, please run 'make$(if $(findstring command line, $(origin ARCH)), ARCH=$(ARCH)) mrproper'"; \ +- echo >&2 "*** in $(abs_srctree)";\ +- echo >&2 "***"; \ +- false; \ +- fi + $(Q)ln -fsn $(srctree) source + $(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkmakefile $(srctree) + $(Q)test -e .gitignore || \ diff --git a/kernel/kernel/files/patches/pisilinux/revert-Makefile.patch b/kernel/kernel/files/patches/pisilinux/revert-Makefile.patch new file mode 100644 index 00000000..b4b37d09 --- /dev/null +++ b/kernel/kernel/files/patches/pisilinux/revert-Makefile.patch @@ -0,0 +1,780 @@ +--- a/Makefile.orig 2019-11-25 03:32:01.000000000 +0300 ++++ b/Makefile 2019-12-11 16:59:26.708807035 +0300 +@@ -3,7 +3,7 @@ + PATCHLEVEL = 4 + SUBLEVEL = 0 + EXTRAVERSION = +-NAME = Kleptomaniac Octopus ++NAME = Bobtail Squid + + # *DOCUMENTATION* + # To see a list of typical targets execute "make help" +@@ -206,16 +206,30 @@ + KBUILD_CHECKSRC = 0 + endif + +-# Use make M=dir or set the environment variable KBUILD_EXTMOD to specify the +-# directory of external module to build. Setting M= takes precedence. ++# Use make M=dir to specify directory of external module to build ++# Old syntax make ... SUBDIRS=$PWD is still supported ++# Setting the environment variable KBUILD_EXTMOD take precedence ++ifdef SUBDIRS ++ $(warning ================= WARNING ================) ++ $(warning 'SUBDIRS' will be removed after Linux 5.3) ++ $(warning ) ++ $(warning If you are building an individual subdirectory) ++ $(warning in the kernel tree, you can do like this:) ++ $(warning $$ make path/to/dir/you/want/to/build/) ++ $(warning (Do not forget the trailing slash)) ++ $(warning ) ++ $(warning If you are building an external module,) ++ $(warning Please use 'M=' or 'KBUILD_EXTMOD' instead) ++ $(warning ==========================================) ++ KBUILD_EXTMOD ?= $(SUBDIRS) ++endif ++ + ifeq ("$(origin M)", "command line") + KBUILD_EXTMOD := $(M) + endif + + export KBUILD_CHECKSRC KBUILD_EXTMOD + +-extmod-prefix = $(if $(KBUILD_EXTMOD),$(KBUILD_EXTMOD)/) +- + ifeq ($(abs_srctree),$(abs_objtree)) + # building in the source tree + srctree := . +@@ -257,62 +271,52 @@ + %asm-generic kernelversion %src-pkg + no-sync-config-targets := $(no-dot-config-targets) install %install \ + kernelrelease +-single-targets := %.a %.i %.ko %.lds %.ll %.lst %.mod %.o %.s %.symtypes %/ + +-config-build := +-mixed-build := +-need-config := 1 +-may-sync-config := 1 +-single-build := ++config-targets := 0 ++mixed-targets := 0 ++dot-config := 1 ++may-sync-config := 1 + + ifneq ($(filter $(no-dot-config-targets), $(MAKECMDGOALS)),) + ifeq ($(filter-out $(no-dot-config-targets), $(MAKECMDGOALS)),) +- need-config := ++ dot-config := 0 + endif + endif + + ifneq ($(filter $(no-sync-config-targets), $(MAKECMDGOALS)),) + ifeq ($(filter-out $(no-sync-config-targets), $(MAKECMDGOALS)),) +- may-sync-config := ++ may-sync-config := 0 + endif + endif + + ifneq ($(KBUILD_EXTMOD),) +- may-sync-config := ++ may-sync-config := 0 + endif + + ifeq ($(KBUILD_EXTMOD),) + ifneq ($(filter config %config,$(MAKECMDGOALS)),) +- config-build := 1 ++ config-targets := 1 + ifneq ($(words $(MAKECMDGOALS)),1) +- mixed-build := 1 ++ mixed-targets := 1 + endif + endif + endif + +-# We cannot build single targets and the others at the same time +-ifneq ($(filter $(single-targets), $(MAKECMDGOALS)),) +- single-build := 1 +- ifneq ($(filter-out $(single-targets), $(MAKECMDGOALS)),) +- mixed-build := 1 +- endif +-endif +- + # For "make -j clean all", "make -j mrproper defconfig all", etc. + ifneq ($(filter $(clean-targets),$(MAKECMDGOALS)),) + ifneq ($(filter-out $(clean-targets),$(MAKECMDGOALS)),) +- mixed-build := 1 ++ mixed-targets := 1 + endif + endif + + # install and modules_install need also be processed one by one + ifneq ($(filter install,$(MAKECMDGOALS)),) + ifneq ($(filter modules_install,$(MAKECMDGOALS)),) +- mixed-build := 1 ++ mixed-targets := 1 + endif + endif + +-ifdef mixed-build ++ifeq ($(mixed-targets),1) + # =========================================================================== + # We're called with mixed targets (*config and build targets). + # Handle them one by one. +@@ -328,7 +332,7 @@ + $(MAKE) -f $(srctree)/Makefile $$i; \ + done + +-else # !mixed-build ++else + + include scripts/Kbuild.include + +@@ -388,7 +392,9 @@ + export KCONFIG_CONFIG + + # SHELL used by kbuild +-CONFIG_SHELL := sh ++CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \ ++ else if [ -x /bin/bash ]; then echo /bin/bash; \ ++ else echo sh; fi ; fi) + + HOST_LFS_CFLAGS := $(shell getconf LFS_CFLAGS 2>/dev/null) + HOST_LFS_LDFLAGS := $(shell getconf LFS_LDFLAGS 2>/dev/null) +@@ -425,7 +431,6 @@ + PYTHON2 = python2 + PYTHON3 = python3 + CHECK = sparse +-BASH = bash + + CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ \ + -Wbitwise -Wno-return-void -Wno-unknown-attribute $(CF) +@@ -465,13 +470,12 @@ + KBUILD_CFLAGS_KERNEL := + KBUILD_AFLAGS_MODULE := -DMODULE + KBUILD_CFLAGS_MODULE := -DMODULE +-KBUILD_LDFLAGS_MODULE := +-export KBUILD_LDS_MODULE := $(srctree)/scripts/module-common.lds ++KBUILD_LDFLAGS_MODULE := -T $(srctree)/scripts/module-common.lds + KBUILD_LDFLAGS := + GCC_PLUGINS_CFLAGS := + CLANG_FLAGS := + +-export ARCH SRCARCH CONFIG_SHELL BASH HOSTCC KBUILD_HOSTCFLAGS CROSS_COMPILE AS LD CC ++export ARCH SRCARCH CONFIG_SHELL HOSTCC KBUILD_HOSTCFLAGS CROSS_COMPILE AS LD CC + export CPP AR NM STRIP OBJCOPY OBJDUMP OBJSIZE PAHOLE LEX YACC AWK INSTALLKERNEL + export PERL PYTHON PYTHON2 PYTHON3 CHECK CHECKFLAGS MAKE UTS_MACHINE HOSTCXX + export KBUILD_HOSTCXXFLAGS KBUILD_HOSTLDFLAGS KBUILD_HOSTLDLIBS LDFLAGS_MODULE +@@ -482,6 +486,7 @@ + export KBUILD_AFLAGS AFLAGS_KERNEL AFLAGS_MODULE + export KBUILD_AFLAGS_MODULE KBUILD_CFLAGS_MODULE KBUILD_LDFLAGS_MODULE + export KBUILD_AFLAGS_KERNEL KBUILD_CFLAGS_KERNEL ++export KBUILD_ARFLAGS + + # Files to ignore in find ... statements + +@@ -501,7 +506,6 @@ + $(Q)rm -f .tmp_quiet_recordmcount + + PHONY += outputmakefile +-# Before starting out-of-tree build, make sure the source tree is clean. + # outputmakefile generates a Makefile in the output directory, if using a + # separate output directory. This allows convenient use of make in the + # output directory. +@@ -509,15 +513,6 @@ + # ignore whole output directory + outputmakefile: + ifdef building_out_of_srctree +- $(Q)if [ -f $(srctree)/.config -o \ +- -d $(srctree)/include/config -o \ +- -d $(srctree)/arch/$(SRCARCH)/include/generated ]; then \ +- echo >&2 "***"; \ +- echo >&2 "*** The source tree is not clean, please run 'make$(if $(findstring command line, $(origin ARCH)), ARCH=$(ARCH)) mrproper'"; \ +- echo >&2 "*** in $(abs_srctree)";\ +- echo >&2 "***"; \ +- false; \ +- fi + $(Q)ln -fsn $(srctree) source + $(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkmakefile $(srctree) + $(Q)test -e .gitignore || \ +@@ -549,7 +544,7 @@ + # and from include/config/auto.conf.cmd to detect the compiler upgrade. + CC_VERSION_TEXT = $(shell $(CC) --version 2>/dev/null | head -n 1) + +-ifdef config-build ++ifeq ($(config-targets),1) + # =========================================================================== + # *config targets only - make sure prerequisites are updated, and descend + # in scripts/kconfig to make the *config target +@@ -560,13 +555,13 @@ + include arch/$(SRCARCH)/Makefile + export KBUILD_DEFCONFIG KBUILD_KCONFIG CC_VERSION_TEXT + +-config: outputmakefile scripts_basic FORCE ++config: scripts_basic outputmakefile FORCE + $(Q)$(MAKE) $(build)=scripts/kconfig $@ + +-%config: outputmakefile scripts_basic FORCE ++%config: scripts_basic outputmakefile FORCE + $(Q)$(MAKE) $(build)=scripts/kconfig $@ + +-else #!config-build ++else + # =========================================================================== + # Build targets only - this includes vmlinux, arch specific targets, clean + # targets and others. In general all targets except *config targets. +@@ -599,7 +594,7 @@ + # in addition to whatever we do anyway. + # Just "make" or "make all" shall build modules as well + +-ifneq ($(filter all _all modules nsdeps,$(MAKECMDGOALS)),) ++ifneq ($(filter all _all modules,$(MAKECMDGOALS)),) + KBUILD_MODULES := 1 + endif + +@@ -609,7 +604,7 @@ + + export KBUILD_MODULES KBUILD_BUILTIN + +-ifdef need-config ++ifeq ($(dot-config),1) + include include/config/auto.conf + endif + +@@ -650,10 +645,15 @@ + export RETPOLINE_CFLAGS + export RETPOLINE_VDSO_CFLAGS + ++# The arch Makefile can set ARCH_{CPP,A,C}FLAGS to override the default ++# values of the respective KBUILD_* variables ++ARCH_CPPFLAGS := ++ARCH_AFLAGS := ++ARCH_CFLAGS := + include arch/$(SRCARCH)/Makefile + +-ifdef need-config +-ifdef may-sync-config ++ifeq ($(dot-config),1) ++ifeq ($(may-sync-config),1) + # Read in dependencies to all Kconfig* files, make sure to run syncconfig if + # changes are detected. This should be included after arch/$(SRCARCH)/Makefile + # because some architectures define CROSS_COMPILE there. +@@ -676,7 +676,7 @@ + # The syncconfig should be executed only once to make all the targets. + %/auto.conf %/auto.conf.cmd %/tristate.conf: $(KCONFIG_CONFIG) + $(Q)$(MAKE) -f $(srctree)/Makefile syncconfig +-else # !may-sync-config ++else + # External modules and some install targets need include/generated/autoconf.h + # and include/config/auto.conf but do not care if they are up-to-date. + # Use auto.conf to trigger the test +@@ -692,7 +692,7 @@ + /bin/false) + + endif # may-sync-config +-endif # need-config ++endif # $(dot-config) + + KBUILD_CFLAGS += $(call cc-option,-fno-delete-null-pointer-checks,) + KBUILD_CFLAGS += $(call cc-disable-warning,frame-address,) +@@ -700,12 +700,10 @@ + KBUILD_CFLAGS += $(call cc-disable-warning, format-overflow) + KBUILD_CFLAGS += $(call cc-disable-warning, address-of-packed-member) + +-ifdef CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE +-KBUILD_CFLAGS += -O2 +-else ifdef CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE_O3 +-KBUILD_CFLAGS += -O3 +-else ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE +-KBUILD_CFLAGS += -Os ++ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE ++KBUILD_CFLAGS += -Os ++else ++KBUILD_CFLAGS += -O2 + endif + + ifdef CONFIG_CC_DISABLE_WARN_MAYBE_UNINITIALIZED +@@ -753,11 +751,6 @@ + # These warnings generated too much noise in a regular build. + # Use make W=1 to enable them (see scripts/Makefile.extrawarn) + KBUILD_CFLAGS += -Wno-unused-but-set-variable +- +-# Warn about unmarked fall-throughs in switch statement. +-# Disabled for clang while comment to attribute conversion happens and +-# https://github.com/ClangBuiltLinux/linux/issues/636 is discussed. +-KBUILD_CFLAGS += $(call cc-option,-Wimplicit-fallthrough,) + endif + + KBUILD_CFLAGS += $(call cc-disable-warning, unused-const-variable) +@@ -852,6 +845,9 @@ + # warn about C99 declaration after statement + KBUILD_CFLAGS += -Wdeclaration-after-statement + ++# Warn about unmarked fall-throughs in switch statement. ++KBUILD_CFLAGS += $(call cc-option,-Wimplicit-fallthrough,) ++ + # Variable Length Arrays (VLAs) should not be used anywhere in the kernel + KBUILD_CFLAGS += -Wvla + +@@ -897,14 +893,18 @@ + KBUILD_CFLAGS += $(call cc-option,-fcf-protection=none) + endif + ++# use the deterministic mode of AR if available ++KBUILD_ARFLAGS := $(call ar-option,D) ++ + include scripts/Makefile.kasan + include scripts/Makefile.extrawarn + include scripts/Makefile.ubsan + +-# Add user supplied CPPFLAGS, AFLAGS and CFLAGS as the last assignments +-KBUILD_CPPFLAGS += $(KCPPFLAGS) +-KBUILD_AFLAGS += $(KAFLAGS) +-KBUILD_CFLAGS += $(KCFLAGS) ++# Add any arch overrides and user supplied CPPFLAGS, AFLAGS and CFLAGS as the ++# last assignments ++KBUILD_CPPFLAGS += $(ARCH_CPPFLAGS) $(KCPPFLAGS) ++KBUILD_AFLAGS += $(ARCH_AFLAGS) $(KAFLAGS) ++KBUILD_CFLAGS += $(ARCH_CFLAGS) $(KCFLAGS) + + KBUILD_LDFLAGS_MODULE += --build-id + LDFLAGS_vmlinux += --build-id +@@ -913,13 +913,6 @@ + LDFLAGS_vmlinux += $(call ld-option, -X,) + endif + +-ifeq ($(CONFIG_RELR),y) +-LDFLAGS_vmlinux += --pack-dyn-relocs=relr +-endif +- +-# make the checker run with the right architecture +-CHECKFLAGS += --arch=$(ARCH) +- + # insure the checker run with the right endianness + CHECKFLAGS += $(if $(CONFIG_CPU_BIG_ENDIAN),-mbig-endian,-mlittle-endian) + +@@ -1010,7 +1003,7 @@ + + PHONY += prepare0 + +-export MODORDER := $(extmod-prefix)modules.order ++export MODORDER := $(if $(KBUILD_EXTMOD),$(KBUILD_EXTMOD)/)modules.order + + ifeq ($(KBUILD_EXTMOD),) + core-y += kernel/ certs/ mm/ fs/ ipc/ security/ crypto/ block/ +@@ -1023,9 +1016,6 @@ + $(patsubst %/,%,$(filter %/, $(init-) $(core-) \ + $(drivers-) $(net-) $(libs-) $(virt-)))) + +-build-dirs := $(vmlinux-dirs) +-clean-dirs := $(vmlinux-alldirs) +- + init-y := $(patsubst %/, %/built-in.a, $(init-y)) + core-y := $(patsubst %/, %/built-in.a, $(core-y)) + drivers-y := $(patsubst %/, %/built-in.a, $(drivers-y)) +@@ -1040,7 +1030,7 @@ + export KBUILD_VMLINUX_LIBS := $(libs-y1) + export KBUILD_LDS := arch/$(SRCARCH)/kernel/vmlinux.lds + export LDFLAGS_vmlinux +-# used by scripts/Makefile.package ++# used by scripts/package/Makefile + export KBUILD_ALLDIRS := $(sort $(filter-out arch/%,$(vmlinux-alldirs)) LICENSES arch include scripts tools) + + vmlinux-deps := $(KBUILD_LDS) $(KBUILD_VMLINUX_OBJS) $(KBUILD_VMLINUX_LIBS) +@@ -1048,7 +1038,7 @@ + # Recurse until adjust_autoksyms.sh is satisfied + PHONY += autoksyms_recursive + ifdef CONFIG_TRIM_UNUSED_KSYMS +-autoksyms_recursive: descend modules.order ++autoksyms_recursive: $(vmlinux-deps) modules.order + $(Q)$(CONFIG_SHELL) $(srctree)/scripts/adjust_autoksyms.sh \ + "$(MAKE) -f $(srctree)/Makefile vmlinux" + endif +@@ -1080,7 +1070,17 @@ + + # The actual objects are generated when descending, + # make sure no implicit rule kicks in +-$(sort $(vmlinux-deps)): descend ; ++$(sort $(vmlinux-deps)): $(vmlinux-dirs) ; ++ ++# Handle descending into subdirectories listed in $(vmlinux-dirs) ++# Preset locale variables to speed up the build process. Limit locale ++# tweaks to this spot to avoid wrong language settings when running ++# make menuconfig etc. ++# Error messages still appears in the original language ++ ++PHONY += $(vmlinux-dirs) ++$(vmlinux-dirs): prepare ++ $(Q)$(MAKE) $(build)=$@ need-builtin=1 need-modorder=1 + + filechk_kernel.release = \ + echo "$(KERNELVERSION)$$($(CONFIG_SHELL) $(srctree)/scripts/setlocalversion $(srctree))" +@@ -1102,9 +1102,24 @@ + # archprepare is used in arch Makefiles and when processed asm symlink, + # version.h and scripts_basic is processed / created. + +-PHONY += prepare archprepare ++PHONY += prepare archprepare prepare3 + +-archprepare: outputmakefile archheaders archscripts scripts include/config/kernel.release \ ++# prepare3 is used to check if we are building in a separate output directory, ++# and if so do: ++# 1) Check that make has not been executed in the kernel src $(srctree) ++prepare3: include/config/kernel.release ++ifdef building_out_of_srctree ++ @$(kecho) ' Using $(srctree) as source for kernel' ++ $(Q)if [ -f $(srctree)/.config -o \ ++ -d $(srctree)/include/config -o \ ++ -d $(srctree)/arch/$(SRCARCH)/include/generated ]; then \ ++ echo >&2 " $(srctree) is not clean, please run 'make ARCH=$(ARCH) mrproper'"; \ ++ echo >&2 " in the '$(srctree)' directory.";\ ++ /bin/false; \ ++ fi; ++endif ++ ++archprepare: archheaders archscripts scripts prepare3 outputmakefile \ + asm-generic $(version_h) $(autoksyms_h) include/generated/utsrelease.h + + prepare0: archprepare +@@ -1220,15 +1235,16 @@ + kselftest: + $(Q)$(MAKE) -C $(srctree)/tools/testing/selftests run_tests + +-kselftest-%: FORCE +- $(Q)$(MAKE) -C $(srctree)/tools/testing/selftests $* ++PHONY += kselftest-clean ++kselftest-clean: ++ $(Q)$(MAKE) -C $(srctree)/tools/testing/selftests clean + + PHONY += kselftest-merge + kselftest-merge: + $(if $(wildcard $(objtree)/.config),, $(error No .config exists, config your kernel first!)) + $(Q)find $(srctree)/tools/testing/selftests -name config | \ + xargs $(srctree)/scripts/kconfig/merge_config.sh -m $(objtree)/.config +- $(Q)$(MAKE) -f $(srctree)/Makefile olddefconfig ++ +$(Q)$(MAKE) -f $(srctree)/Makefile olddefconfig + + # --------------------------------------------------------------------------- + # Devicetree files +@@ -1239,11 +1255,11 @@ + + ifneq ($(dtstree),) + +-%.dtb: include/config/kernel.release scripts_dtc ++%.dtb: prepare3 scripts_dtc + $(Q)$(MAKE) $(build)=$(dtstree) $(dtstree)/$@ + + PHONY += dtbs dtbs_install dt_binding_check +-dtbs dtbs_check: include/config/kernel.release scripts_dtc ++dtbs dtbs_check: prepare3 scripts_dtc + $(Q)$(MAKE) $(build)=$(dtstree) + + dtbs_check: export CHECK_DTBS=1 +@@ -1282,16 +1298,17 @@ + + PHONY += modules + modules: $(if $(KBUILD_BUILTIN),vmlinux) modules.order modules.builtin ++ @$(kecho) ' Building modules, stage 2.'; + $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost + $(Q)$(CONFIG_SHELL) $(srctree)/scripts/modules-check.sh + +-modules.order: descend +- $(Q)$(AWK) '!x[$$0]++' $(addsuffix /$@, $(build-dirs)) > $@ ++modules.order: $(vmlinux-dirs) ++ $(Q)$(AWK) '!x[$$0]++' $(addsuffix /$@, $(vmlinux-dirs)) > $@ + +-modbuiltin-dirs := $(addprefix _modbuiltin_, $(build-dirs)) ++modbuiltin-dirs := $(addprefix _modbuiltin_, $(vmlinux-dirs)) + + modules.builtin: $(modbuiltin-dirs) +- $(Q)$(AWK) '!x[$$0]++' $(addsuffix /$@, $(build-dirs)) > $@ ++ $(Q)$(AWK) '!x[$$0]++' $(addsuffix /$@, $(vmlinux-dirs)) > $@ + + PHONY += $(modbuiltin-dirs) + # tristate.conf is not included from this Makefile. Add it as a prerequisite +@@ -1364,14 +1381,12 @@ + + # Directories & files removed with 'make mrproper' + MRPROPER_DIRS += include/config include/generated \ +- arch/$(SRCARCH)/include/generated .tmp_objdiff \ +- debian/ snap/ tar-install/ ++ arch/$(SRCARCH)/include/generated .tmp_objdiff + MRPROPER_FILES += .config .config.old .version \ + Module.symvers \ + signing_key.pem signing_key.priv signing_key.x509 \ + x509.genkey extra_certificates signing_key.x509.keyid \ +- signing_key.x509.signer vmlinux-gdb.py \ +- *.spec ++ signing_key.x509.signer vmlinux-gdb.py + + # Directories & files removed with 'make distclean' + DISTCLEAN_DIRS += +@@ -1381,8 +1396,11 @@ + # + clean: rm-dirs := $(CLEAN_DIRS) + clean: rm-files := $(CLEAN_FILES) ++clean-dirs := $(addprefix _clean_, . $(vmlinux-alldirs)) + +-PHONY += archclean vmlinuxclean ++PHONY += $(clean-dirs) clean archclean vmlinuxclean ++$(clean-dirs): ++ $(Q)$(MAKE) $(clean)=$(patsubst _clean_%,%,$@) + + vmlinuxclean: + $(Q)$(CONFIG_SHELL) $(srctree)/scripts/link-vmlinux.sh clean +@@ -1423,11 +1441,13 @@ + + # Packaging of the kernel to various formats + # --------------------------------------------------------------------------- ++package-dir := scripts/package + + %src-pkg: FORCE +- $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.package $@ ++ $(Q)$(MAKE) $(build)=$(package-dir) $@ + %pkg: include/config/kernel.release FORCE +- $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.package $@ ++ $(Q)$(MAKE) $(build)=$(package-dir) $@ ++ + + # Brief documentation of the typical targets used + # --------------------------------------------------------------------------- +@@ -1480,9 +1500,6 @@ + @echo ' headerdep - Detect inclusion cycles in headers' + @echo ' coccicheck - Check with Coccinelle' + @echo '' +- @echo 'Tools:' +- @echo ' nsdeps - Generate missing symbol namespace dependencies' +- @echo '' + @echo 'Kernel selftest:' + @echo ' kselftest - Build and run kernel selftest (run as root)' + @echo ' Build, install, and boot kernel before' +@@ -1493,10 +1510,8 @@ + @echo '' + @$(if $(dtstree), \ + echo 'Devicetree:'; \ +- echo '* dtbs - Build device tree blobs for enabled boards'; \ +- echo ' dtbs_install - Install dtbs to $(INSTALL_DTBS_PATH)'; \ +- echo ' dt_binding_check - Validate device tree binding documents'; \ +- echo ' dtbs_check - Validate device tree source files';\ ++ echo '* dtbs - Build device tree blobs for enabled boards'; \ ++ echo ' dtbs_install - Install dtbs to $(INSTALL_DTBS_PATH)'; \ + echo '') + + @echo 'Userspace tools targets:' +@@ -1504,7 +1519,7 @@ + @echo ' or "cd tools; make help"' + @echo '' + @echo 'Kernel packaging:' +- @$(MAKE) -f $(srctree)/scripts/Makefile.package help ++ @$(MAKE) $(build)=$(package-dir) help + @echo '' + @echo 'Documentation targets:' + @$(MAKE) -f $(srctree)/Documentation/Makefile dochelp +@@ -1529,7 +1544,7 @@ + @echo ' make C=1 [targets] Check re-compiled c source with $$CHECK (sparse by default)' + @echo ' make C=2 [targets] Force check of all c source with $$CHECK' + @echo ' make RECORDMCOUNT_WARN=1 [targets] Warn about ignored mcount sections' +- @echo ' make W=n [targets] Enable extra build checks, n=1,2,3 where' ++ @echo ' make W=n [targets] Enable extra gcc checks, n=1,2,3 where' + @echo ' 1: warnings which may be relevant and do not occur too often' + @echo ' 2: warnings which occur quite often but may still be relevant' + @echo ' 3: more obscure warnings, can most likely be ignored' +@@ -1558,7 +1573,7 @@ + DOC_TARGETS := xmldocs latexdocs pdfdocs htmldocs epubdocs cleandocs \ + linkcheckdocs dochelp refcheckdocs + PHONY += $(DOC_TARGETS) +-$(DOC_TARGETS): ++$(DOC_TARGETS): scripts_basic FORCE + $(Q)$(MAKE) $(build)=Documentation $@ + + # Misc +@@ -1603,9 +1618,13 @@ + echo " is missing; modules will have no dependencies and modversions."; \ + echo ) + +-build-dirs := $(KBUILD_EXTMOD) +-PHONY += modules +-modules: descend $(objtree)/Module.symvers ++module-dirs := $(addprefix _module_,$(KBUILD_EXTMOD)) ++PHONY += $(module-dirs) modules ++$(module-dirs): prepare $(objtree)/Module.symvers ++ $(Q)$(MAKE) $(build)=$(patsubst _module_%,%,$@) need-modorder=1 ++ ++modules: $(module-dirs) ++ @$(kecho) ' Building modules, stage 2.'; + $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost + + PHONY += modules_install +@@ -1621,12 +1640,13 @@ + _emodinst_post: _emodinst_ + $(call cmd,depmod) + +-clean-dirs := $(KBUILD_EXTMOD) +-clean: rm-files := $(KBUILD_EXTMOD)/Module.symvers ++clean-dirs := $(addprefix _clean_,$(KBUILD_EXTMOD)) + +-PHONY += / +-/: +- @echo >&2 '"$(MAKE) /" is no longer supported. Please use "$(MAKE) ./" instead.' ++PHONY += $(clean-dirs) clean ++$(clean-dirs): ++ $(Q)$(MAKE) $(clean)=$(patsubst _clean_%,%,$@) ++ ++clean: rm-files := $(KBUILD_EXTMOD)/Module.symvers + + PHONY += help + help: +@@ -1641,21 +1661,6 @@ + PHONY += prepare + endif # KBUILD_EXTMOD + +-# Handle descending into subdirectories listed in $(build-dirs) +-# Preset locale variables to speed up the build process. Limit locale +-# tweaks to this spot to avoid wrong language settings when running +-# make menuconfig etc. +-# Error messages still appears in the original language +-PHONY += descend $(build-dirs) +-descend: $(build-dirs) +-$(build-dirs): prepare +- $(Q)$(MAKE) $(build)=$@ single-build=$(single-build) need-builtin=1 need-modorder=1 +- +-clean-dirs := $(addprefix _clean_, $(clean-dirs)) +-PHONY += $(clean-dirs) clean +-$(clean-dirs): +- $(Q)$(MAKE) $(clean)=$(patsubst _clean_%,%,$@) +- + clean: $(clean-dirs) + $(call cmd,rmdirs) + $(call cmd,rmfiles) +@@ -1664,7 +1669,7 @@ + -o -name '*.ko.*' \ + -o -name '*.dtb' -o -name '*.dtb.S' -o -name '*.dt.yaml' \ + -o -name '*.dwo' -o -name '*.lst' \ +- -o -name '*.su' -o -name '*.mod' -o -name '*.ns_deps' \ ++ -o -name '*.su' -o -name '*.mod' \ + -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \ + -o -name '*.lex.c' -o -name '*.tab.[ch]' \ + -o -name '*.asn1.[ch]' \ +@@ -1677,20 +1682,11 @@ + # Generate tags for editors + # --------------------------------------------------------------------------- + quiet_cmd_tags = GEN $@ +- cmd_tags = $(BASH) $(srctree)/scripts/tags.sh $@ ++ cmd_tags = $(CONFIG_SHELL) $(srctree)/scripts/tags.sh $@ + + tags TAGS cscope gtags: FORCE + $(call cmd,tags) + +-# Script to generate missing namespace dependencies +-# --------------------------------------------------------------------------- +- +-PHONY += nsdeps +- +-nsdeps: modules +- $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost nsdeps +- $(Q)$(CONFIG_SHELL) $(srctree)/scripts/$@ +- + # Scripts to check various things for consistency + # --------------------------------------------------------------------------- + +@@ -1707,7 +1703,7 @@ + | xargs $(PERL) -w $(srctree)/scripts/checkversion.pl + + coccicheck: +- $(Q)$(BASH) $(srctree)/scripts/$@ ++ $(Q)$(CONFIG_SHELL) $(srctree)/scripts/$@ + + namespacecheck: + $(PERL) $(srctree)/scripts/namespace.pl +@@ -1755,47 +1751,45 @@ + + # Single targets + # --------------------------------------------------------------------------- +-# To build individual files in subdirectories, you can do like this: +-# +-# make foo/bar/baz.s +-# +-# The supported suffixes for single-target are listed in 'single-targets' +-# +-# To build only under specific subdirectories, you can do like this: +-# +-# make foo/bar/baz/ +- +-ifdef single-build +- +-single-all := $(filter $(single-targets), $(MAKECMDGOALS)) +- +-# .ko is special because modpost is needed +-single-ko := $(sort $(filter %.ko, $(single-all))) +-single-no-ko := $(sort $(patsubst %.ko,%.mod, $(single-all))) +- +-$(single-ko): single_modpost +- @: +-$(single-no-ko): descend +- @: +- ++# Single targets are compatible with: ++# - build with mixed source and output ++# - build with separate output dir 'make O=...' ++# - external modules ++# ++# target-dir => where to store outputfile ++# build-dir => directory in kernel source tree to use ++ ++build-target = $(if $(KBUILD_EXTMOD), $(KBUILD_EXTMOD)/)$@ ++build-dir = $(patsubst %/,%,$(dir $(build-target))) ++ ++%.i: prepare FORCE ++ $(Q)$(MAKE) $(build)=$(build-dir) $(build-target) ++%.ll: prepare FORCE ++ $(Q)$(MAKE) $(build)=$(build-dir) $(build-target) ++%.lst: prepare FORCE ++ $(Q)$(MAKE) $(build)=$(build-dir) $(build-target) ++%.o: prepare FORCE ++ $(Q)$(MAKE) $(build)=$(build-dir) $(build-target) ++%.s: prepare FORCE ++ $(Q)$(MAKE) $(build)=$(build-dir) $(build-target) ++%.symtypes: prepare FORCE ++ $(Q)$(MAKE) $(build)=$(build-dir) $(build-target) + ifeq ($(KBUILD_EXTMOD),) +-# For the single build of in-tree modules, use a temporary file to avoid ++# For the single build of an in-tree module, use a temporary file to avoid + # the situation of modules_install installing an invalid modules.order. +-MODORDER := .modules.tmp ++%.ko: MODORDER := .modules.tmp + endif +- +-PHONY += single_modpost +-single_modpost: $(single-no-ko) +- $(Q){ $(foreach m, $(single-ko), echo $(extmod-prefix)$m;) } > $(MODORDER) ++%.ko: prepare FORCE ++ $(Q)$(MAKE) $(build)=$(build-dir) $(build-target:.ko=.mod) ++ $(Q)echo $(build-target) > $(MODORDER) + $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost + +-KBUILD_MODULES := 1 +- +-export KBUILD_SINGLE_TARGETS := $(addprefix $(extmod-prefix), $(single-no-ko)) ++# Modules ++PHONY += / ++/: ./ + +-single-build = $(if $(filter-out $@/, $(single-no-ko)),1) +- +-endif ++%/: prepare FORCE ++ $(Q)$(MAKE) KBUILD_MODULES=1 $(build)=$(build-dir) need-modorder=1 + + # FIXME Should go into a make.lib or something + # =========================================================================== +@@ -1816,9 +1810,9 @@ + + -include $(foreach f,$(existing-targets),$(dir $(f)).$(notdir $(f)).cmd) + +-endif # config-targets +-endif # mixed-build +-endif # need-sub-make ++endif # ifeq ($(config-targets),1) ++endif # ifeq ($(mixed-targets),1) ++endif # need-sub-make + + PHONY += FORCE + FORCE: diff --git a/kernel/kernel/files/scripts/generate-module-list b/kernel/kernel/files/scripts/generate-module-list old mode 100644 new mode 100755 diff --git a/kernel/kernel/pspec.xml b/kernel/kernel/pspec.xml index 0f5aa24d..fe719656 100644 --- a/kernel/kernel/pspec.xml +++ b/kernel/kernel/pspec.xml @@ -12,7 +12,7 @@ kernel The Linux kernel (the core of the Linux operating system) for Pisi Linux kernel contains the Linux kernel, the core of any Linux operating system. The kernel handles the basic functions of the operating system: memory allocation, process allocation, device input and output, etc. - https://www.kernel.org/pub/linux/kernel/v4.x/linux-4.19.tar.gz + https://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/linux-5.4.tar.gz configs/kernel-i686-config configs/kernel-x86_64-config @@ -29,16 +29,20 @@ zlib-devel xz-devel openssl-devel + rsync - patches/linux/patch-4.19.56.xz - - - - - patches/mageia_4_19/fs-aufs-4.19.patch - patches/mageia_4_19/fs-aufs-4.19-modular.patch + patches/linux/patch-5.4.6.xz + + patches/mageia/fs-aufs-5.4.patch + patches/mageia/fs-aufs-5.4-modular.patch + patches/mageia/fs-vboxsf.patch + patches/mageia/CVE-2019-12379.patch + + + + patches/pisilinux/revert-Makefile.patch @@ -94,6 +98,17 @@ + + 2019-12-27 + 5.4.6 + Version Bump. + security + + systemRestart + + Idris Kalp + idriskalp@gmail.com + 2019-06-25 4.19.56 From 1985ece49d0030bdfda28a8a619b2b6eb22e8a89 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 18:59:55 +0300 Subject: [PATCH 153/160] cpupowertools 5.4.6 --- .../change-default-console-loglevel.patch | 11 + .../fix_CPU0_microcode_on_resume.patch | 21 + .../gentoo/1500_XATTR_USER_PREFIX.patch | 54 + ...ink-security-restrictions-by-default.patch | 22 + ...0_ThinkPad-30-brightness-control-fix.patch | 67 + .../gentoo/2900_dev-root-proc-mount-fix.patch | 30 + .../gentoo/2905_2disk-resume-image-fix.patch | 24 + .../patches/gentoo/4200_fbcondecor-3.19.patch | 2119 + .../gentoo/4567_distro-Gentoo-Kconfig.patch | 143 + ...kconfig-build-bits-for-BFQ-v7r7-3.19.patch | 104 + ...duce-the-BFQ-v7r7-I-O-sched-for-3.19.patch | 6966 +++ ...the-BFQ-v7r7-I-O-sched-for-3.19.patch1.txt | 6966 +++ ...eue-Merge-EQM-to-BFQ-v7r7-for-3.19.0.patch | 1222 + ...tional-cpu-optimizations-for-gcc-4.9.patch | 387 + .../files/patches/linux/patch-4.19.14.xz | Bin 0 -> 459580 bytes .../files/patches/linux/patch-4.19.26.xz | Bin 0 -> 757952 bytes .../files/patches/linux/patch-4.19.27.xz | Bin 0 -> 776244 bytes .../files/patches/linux/patch-5.4.6.xz | Bin 0 -> 167272 bytes .../files/patches/mageia/CVE-2019-12379.patch | 37 + ...-quirk-for-Highpoint-RocketRAID-644L.patch | 34 + ...map3_save_secure_ram-on-non-OMAP3-bu.patch | 46 + ...r-the-Highpoint-Rocketraid-644L-card.patch | 37 + .../disable-mrproper-in-devel-rpms.patch | 74 + .../files/patches/mageia/fs-aufs-4.14.patch | 63 +- .../patches/mageia/fs-aufs-5.4-modular.patch | 321 + .../patches/mageia/fs-aufs-5.4-version.patch | 12 + .../files/patches/mageia/fs-aufs-5.4.patch | 37876 ++++++++++++++++ .../files/patches/mageia/fs-vboxsf.patch | 3410 ++ ...nput-goodix-add-support-for-GDIX1002.patch | 18 + ...-goodix-disable-IRQs-while-suspended.patch | 60 + .../files/patches/mageia/net-WireGuard.patch | 357 +- ...er-add-back-stackpointer-size-checks.patch | 84 + .../patches/mageia/patch-4.14.25-rc1.patch | 4181 ++ ...Move-TSS_sp0-and-TSS_sp1-to-asm-offs.patch | 4 +- ...ame-TSS_sysenter_sp0-to-TSS_entry_st.patch | 4 +- ...d-task-stack-from-x86_tss.sp1-in-SYS.patch | 4 +- ...ntry-32-Put-ESPFIX-code-into-a-macro.patch | 4 +- ...x86-entry-32-Unshare-NMI-return-path.patch | 4 +- ...y-32-Split-off-return-to-kernel-path.patch | 4 +- ...estore-segments-before-int-registers.patch | 12 +- ...nter-the-kernel-via-trampoline-stack.patch | 37 +- ...eave-the-kernel-via-trampoline-stack.patch | 73 +- ...roduce-SAVE_ALL_NMI-and-RESTORE_ALL_.patch | 14 +- ...dle-Entry-from-Kernel-Mode-on-Entry-.patch | 198 + ...-entry-32-Simplify-debug-entry-point.patch | 69 + ...-PTI-cr3-switches-to-NMI-handler-cod.patch | 127 + ...-PTI-cr3-switch-to-non-NMI-entry-exi.patch | 187 + ...me-pti_set_user_pgd-to-pti_set_user_.patch | 81 + ...Unshare-kernel-PMDs-when-PTI-is-enab.patch | 35 + ...llocate-8k-page-tables-when-PTI-is-e.patch | 98 + ...-pgdp-kernel-user-conversion-functio.patch | 137 + ...Move-pti_set_user_pgtbl-to-pgtable.h.patch | 84 + ...-two-more-functions-from-pgtable_64..patch | 120 + ...-pae-Populate-valid-user-PGD-entries.patch | 73 + ...ate-the-user-page-table-with-user-pg.patch | 42 + ...pulate-the-user-page-table-with-user.patch | 50 + ...-an-overflow-check-to-pti_clone_pmds.patch | 33 + ...e-X86_CR3_PTI_PCID_USER_BIT-on-x86_3.patch | 41 + ...-CPU_ENTRY_AREA-on-PMD-level-on-x86_.patch | 56 + ...6-mm-dump_pagetables-Define-INIT_PGD.patch | 61 + ...Use-separate-kernel-PMDs-for-user-pa.patch | 213 + ...address-space-range-on-32-bit-for-th.patch | 75 + ...bit-0030-x86-ldt-Define-LDT_END_ADDR.patch | 64 + ...t-out-sanity-check-in-map_ldt_struct.patch | 146 + ...-ldt-Enable-LDT-user-mapping-for-PAE.patch | 107 + ...NFIG_PAGE_TABLE_ISOLATION-for-x86_32.patch | 25 + ...arning-when-booting-on-a-PCID-capabl.patch | 45 + ...0100-tone-down-PCID-on-32bit-message.patch | 32 + ...ng-can-trigger-a-kernel-hang-or-oops.patch | 126 + ...ID_OK-in-__scsi_error_from_host_byte.patch | 34 + ...r-crash-due-to-active-timer-for-ABTS.patch | 119 + .../cpupowertools/files/patches/mageia/series | 74 +- ...ng-FIXUP-for-alc289-on-Dell-machines.patch | 35 + ...ke-Fix-jack-name-format-substitution.patch | 35 + .../sound-ASoC-Intel-kbl-fix-jack-name.patch | 32 + .../pisilinux/kernel-5.4-build-fix.patch | 18 + .../patches/pisilinux/revert-Makefile.patch | 780 + kernel/tools/cpupowertools/pspec.xml | 27 +- 78 files changed, 68113 insertions(+), 272 deletions(-) create mode 100644 kernel/tools/cpupowertools/files/patches/archlinux/change-default-console-loglevel.patch create mode 100644 kernel/tools/cpupowertools/files/patches/archlinux/fix_CPU0_microcode_on_resume.patch create mode 100644 kernel/tools/cpupowertools/files/patches/gentoo/1500_XATTR_USER_PREFIX.patch create mode 100644 kernel/tools/cpupowertools/files/patches/gentoo/1510_fs-enable-link-security-restrictions-by-default.patch create mode 100644 kernel/tools/cpupowertools/files/patches/gentoo/2700_ThinkPad-30-brightness-control-fix.patch create mode 100644 kernel/tools/cpupowertools/files/patches/gentoo/2900_dev-root-proc-mount-fix.patch create mode 100644 kernel/tools/cpupowertools/files/patches/gentoo/2905_2disk-resume-image-fix.patch create mode 100644 kernel/tools/cpupowertools/files/patches/gentoo/4200_fbcondecor-3.19.patch create mode 100644 kernel/tools/cpupowertools/files/patches/gentoo/4567_distro-Gentoo-Kconfig.patch create mode 100644 kernel/tools/cpupowertools/files/patches/gentoo/5001_block-cgroups-kconfig-build-bits-for-BFQ-v7r7-3.19.patch create mode 100644 kernel/tools/cpupowertools/files/patches/gentoo/5002_block-introduce-the-BFQ-v7r7-I-O-sched-for-3.19.patch create mode 100644 kernel/tools/cpupowertools/files/patches/gentoo/5002_block-introduce-the-BFQ-v7r7-I-O-sched-for-3.19.patch1.txt create mode 100644 kernel/tools/cpupowertools/files/patches/gentoo/5003_block-bfq-add-Early-Queue-Merge-EQM-to-BFQ-v7r7-for-3.19.0.patch create mode 100644 kernel/tools/cpupowertools/files/patches/gentoo/5010_enable-additional-cpu-optimizations-for-gcc-4.9.patch create mode 100644 kernel/tools/cpupowertools/files/patches/linux/patch-4.19.14.xz create mode 100644 kernel/tools/cpupowertools/files/patches/linux/patch-4.19.26.xz create mode 100644 kernel/tools/cpupowertools/files/patches/linux/patch-4.19.27.xz create mode 100644 kernel/tools/cpupowertools/files/patches/linux/patch-5.4.6.xz create mode 100644 kernel/tools/cpupowertools/files/patches/mageia/CVE-2019-12379.patch create mode 100644 kernel/tools/cpupowertools/files/patches/mageia/PCI-Add-function-1-DMA-alias-quirk-for-Highpoint-RocketRAID-644L.patch create mode 100644 kernel/tools/cpupowertools/files/patches/mageia/arch-ARM-omap2-hide-omap3_save_secure_ram-on-non-OMAP3-bu.patch create mode 100644 kernel/tools/cpupowertools/files/patches/mageia/ata-ahci-Add-PCI-id-for-the-Highpoint-Rocketraid-644L-card.patch create mode 100644 kernel/tools/cpupowertools/files/patches/mageia/disable-mrproper-in-devel-rpms.patch create mode 100644 kernel/tools/cpupowertools/files/patches/mageia/fs-aufs-5.4-modular.patch create mode 100755 kernel/tools/cpupowertools/files/patches/mageia/fs-aufs-5.4-version.patch create mode 100644 kernel/tools/cpupowertools/files/patches/mageia/fs-aufs-5.4.patch create mode 100644 kernel/tools/cpupowertools/files/patches/mageia/fs-vboxsf.patch create mode 100644 kernel/tools/cpupowertools/files/patches/mageia/input-goodix-add-support-for-GDIX1002.patch create mode 100644 kernel/tools/cpupowertools/files/patches/mageia/input-goodix-disable-IRQs-while-suspended.patch create mode 100644 kernel/tools/cpupowertools/files/patches/mageia/net-netfilter-add-back-stackpointer-size-checks.patch create mode 100644 kernel/tools/cpupowertools/files/patches/mageia/patch-4.14.25-rc1.patch create mode 100644 kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0011-x86-entry-32-Handle-Entry-from-Kernel-Mode-on-Entry-.patch create mode 100644 kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0012-x86-entry-32-Simplify-debug-entry-point.patch create mode 100644 kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0013-x86-entry-32-Add-PTI-cr3-switches-to-NMI-handler-cod.patch create mode 100644 kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0014-x86-entry-32-Add-PTI-cr3-switch-to-non-NMI-entry-exi.patch create mode 100644 kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0015-x86-pgtable-Rename-pti_set_user_pgd-to-pti_set_user_.patch create mode 100644 kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0016-x86-pgtable-pae-Unshare-kernel-PMDs-when-PTI-is-enab.patch create mode 100644 kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0017-x86-pgtable-32-Allocate-8k-page-tables-when-PTI-is-e.patch create mode 100644 kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0018-x86-pgtable-Move-pgdp-kernel-user-conversion-functio.patch create mode 100644 kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0019-x86-pgtable-Move-pti_set_user_pgtbl-to-pgtable.h.patch create mode 100644 kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0020-x86-pgtable-Move-two-more-functions-from-pgtable_64..patch create mode 100644 kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0021-x86-mm-pae-Populate-valid-user-PGD-entries.patch create mode 100644 kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0022-x86-mm-pae-Populate-the-user-page-table-with-user-pg.patch create mode 100644 kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0023-x86-mm-legacy-Populate-the-user-page-table-with-user.patch create mode 100644 kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0024-x86-mm-pti-Add-an-overflow-check-to-pti_clone_pmds.patch create mode 100644 kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0025-x86-mm-pti-Define-X86_CR3_PTI_PCID_USER_BIT-on-x86_3.patch create mode 100644 kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0026-x86-mm-pti-Clone-CPU_ENTRY_AREA-on-PMD-level-on-x86_.patch create mode 100644 kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0027-x86-mm-dump_pagetables-Define-INIT_PGD.patch create mode 100644 kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0028-x86-pgtable-pae-Use-separate-kernel-PMDs-for-user-pa.patch create mode 100644 kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0029-x86-ldt-Reserve-address-space-range-on-32-bit-for-th.patch create mode 100644 kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0030-x86-ldt-Define-LDT_END_ADDR.patch create mode 100644 kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0031-x86-ldt-Split-out-sanity-check-in-map_ldt_struct.patch create mode 100644 kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0032-x86-ldt-Enable-LDT-user-mapping-for-PAE.patch create mode 100644 kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0033-x86-pti-Allow-CONFIG_PAGE_TABLE_ISOLATION-for-x86_32.patch create mode 100644 kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0034-x86-mm-pti-Add-Warning-when-booting-on-a-PCID-capabl.patch create mode 100644 kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0100-tone-down-PCID-on-32bit-message.patch create mode 100644 kernel/tools/cpupowertools/files/patches/mageia/scsi-core-Avoid-that-ATA-error-handling-can-trigger-a-kernel-hang-or-oops.patch create mode 100644 kernel/tools/cpupowertools/files/patches/mageia/scsi-core-return-BLK_STS_OK-for-DID_OK-in-__scsi_error_from_host_byte.patch create mode 100644 kernel/tools/cpupowertools/files/patches/mageia/scsi-qla2xxx-Fix-NULL-pointer-crash-due-to-active-timer-for-ABTS.patch create mode 100644 kernel/tools/cpupowertools/files/patches/mageia/sound-ALSA-hda-Fix-a-wrong-FIXUP-for-alc289-on-Dell-machines.patch create mode 100644 kernel/tools/cpupowertools/files/patches/mageia/sound-ASoC-Intel-Skylake-Fix-jack-name-format-substitution.patch create mode 100644 kernel/tools/cpupowertools/files/patches/mageia/sound-ASoC-Intel-kbl-fix-jack-name.patch create mode 100644 kernel/tools/cpupowertools/files/patches/pisilinux/kernel-5.4-build-fix.patch create mode 100644 kernel/tools/cpupowertools/files/patches/pisilinux/revert-Makefile.patch diff --git a/kernel/tools/cpupowertools/files/patches/archlinux/change-default-console-loglevel.patch b/kernel/tools/cpupowertools/files/patches/archlinux/change-default-console-loglevel.patch new file mode 100644 index 00000000..11da2a9d --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/archlinux/change-default-console-loglevel.patch @@ -0,0 +1,11 @@ +--- linux-3.16/include/linux/printk.h.old 2014-08-04 18:48:30.686043266 +0200 ++++ linux-3.16/include/linux/printk.h 2014-08-04 18:48:47.706218528 +0200 +@@ -37,7 +37,7 @@ + #define CONSOLE_LOGLEVEL_SILENT 0 /* Mum's the word */ + #define CONSOLE_LOGLEVEL_MIN 1 /* Minimum loglevel we let people use */ + #define CONSOLE_LOGLEVEL_QUIET 4 /* Shhh ..., when booted with "quiet" */ +-#define CONSOLE_LOGLEVEL_DEFAULT 7 /* anything MORE serious than KERN_DEBUG */ ++#define CONSOLE_LOGLEVEL_DEFAULT 4 /* anything MORE serious than KERN_DEBUG */ + #define CONSOLE_LOGLEVEL_DEBUG 10 /* issue debug messages */ + #define CONSOLE_LOGLEVEL_MOTORMOUTH 15 /* You can't shut this one up */ + diff --git a/kernel/tools/cpupowertools/files/patches/archlinux/fix_CPU0_microcode_on_resume.patch b/kernel/tools/cpupowertools/files/patches/archlinux/fix_CPU0_microcode_on_resume.patch new file mode 100644 index 00000000..56f8094f --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/archlinux/fix_CPU0_microcode_on_resume.patch @@ -0,0 +1,21 @@ +diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c +index dd9d6190b08d..181e42bd85d3 100644 +--- a/arch/x86/kernel/cpu/microcode/core.c ++++ b/arch/x86/kernel/cpu/microcode/core.c +@@ -85,6 +85,7 @@ + #include + + #include ++#include + #include + #include + #include +@@ -465,6 +466,8 @@ static void mc_bp_resume(void) + + if (uci->valid && uci->mc) + microcode_ops->apply_microcode(cpu); ++ else if (!uci->mc) ++ load_ucode_intel_ap(); + } + + static struct syscore_ops mc_syscore_ops = { diff --git a/kernel/tools/cpupowertools/files/patches/gentoo/1500_XATTR_USER_PREFIX.patch b/kernel/tools/cpupowertools/files/patches/gentoo/1500_XATTR_USER_PREFIX.patch new file mode 100644 index 00000000..cc15cd51 --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/gentoo/1500_XATTR_USER_PREFIX.patch @@ -0,0 +1,54 @@ +From: Anthony G. Basile + +This patch adds support for a restricted user-controlled namespace on +tmpfs filesystem used to house PaX flags. The namespace must be of the +form user.pax.* and its value cannot exceed a size of 8 bytes. + +This is needed even on all Gentoo systems so that XATTR_PAX flags +are preserved for users who might build packages using portage on +a tmpfs system with a non-hardened kernel and then switch to a +hardened kernel with XATTR_PAX enabled. + +The namespace is added to any user with Extended Attribute support +enabled for tmpfs. Users who do not enable xattrs will not have +the XATTR_PAX flags preserved. + +diff --git a/include/uapi/linux/xattr.h b/include/uapi/linux/xattr.h +index e4629b9..6958086 100644 +--- a/include/uapi/linux/xattr.h ++++ b/include/uapi/linux/xattr.h +@@ -63,5 +63,9 @@ + #define XATTR_POSIX_ACL_DEFAULT "posix_acl_default" + #define XATTR_NAME_POSIX_ACL_DEFAULT XATTR_SYSTEM_PREFIX XATTR_POSIX_ACL_DEFAULT + ++/* User namespace */ ++#define XATTR_PAX_PREFIX XATTR_USER_PREFIX "pax." ++#define XATTR_PAX_FLAGS_SUFFIX "flags" ++#define XATTR_NAME_PAX_FLAGS XATTR_PAX_PREFIX XATTR_PAX_FLAGS_SUFFIX + + #endif /* _UAPI_LINUX_XATTR_H */ +diff --git a/mm/shmem.c b/mm/shmem.c +index 1c44af7..f23bb1b 100644 +--- a/mm/shmem.c ++++ b/mm/shmem.c +@@ -2201,6 +2201,7 @@ static const struct xattr_handler *shmem_xattr_handlers[] = { + static int shmem_xattr_validate(const char *name) + { + struct { const char *prefix; size_t len; } arr[] = { ++ { XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN}, + { XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN }, + { XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN } + }; +@@ -2256,6 +2257,12 @@ static int shmem_setxattr(struct dentry *dentry, const char *name, + if (err) + return err; + ++ if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) { ++ if (strcmp(name, XATTR_NAME_PAX_FLAGS)) ++ return -EOPNOTSUPP; ++ if (size > 8) ++ return -EINVAL; ++ } + return simple_xattr_set(&info->xattrs, name, value, size, flags); + } + diff --git a/kernel/tools/cpupowertools/files/patches/gentoo/1510_fs-enable-link-security-restrictions-by-default.patch b/kernel/tools/cpupowertools/files/patches/gentoo/1510_fs-enable-link-security-restrictions-by-default.patch new file mode 100644 index 00000000..639fb3c3 --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/gentoo/1510_fs-enable-link-security-restrictions-by-default.patch @@ -0,0 +1,22 @@ +From: Ben Hutchings +Subject: fs: Enable link security restrictions by default +Date: Fri, 02 Nov 2012 05:32:06 +0000 +Bug-Debian: https://bugs.debian.org/609455 +Forwarded: not-needed + +This reverts commit 561ec64ae67ef25cac8d72bb9c4bfc955edfd415 +('VFS: don't do protected {sym,hard}links by default'). + +--- a/fs/namei.c ++++ b/fs/namei.c +@@ -651,8 +651,8 @@ static inline void put_link(struct namei + path_put(link); + } + +-int sysctl_protected_symlinks __read_mostly = 0; +-int sysctl_protected_hardlinks __read_mostly = 0; ++int sysctl_protected_symlinks __read_mostly = 1; ++int sysctl_protected_hardlinks __read_mostly = 1; + + /** + * may_follow_link - Check symlink following for unsafe situations diff --git a/kernel/tools/cpupowertools/files/patches/gentoo/2700_ThinkPad-30-brightness-control-fix.patch b/kernel/tools/cpupowertools/files/patches/gentoo/2700_ThinkPad-30-brightness-control-fix.patch new file mode 100644 index 00000000..b548c6dc --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/gentoo/2700_ThinkPad-30-brightness-control-fix.patch @@ -0,0 +1,67 @@ +diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c +index cb96296..6c242ed 100644 +--- a/drivers/acpi/blacklist.c ++++ b/drivers/acpi/blacklist.c +@@ -269,6 +276,61 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { + }, + + /* ++ * The following Lenovo models have a broken workaround in the ++ * acpi_video backlight implementation to meet the Windows 8 ++ * requirement of 101 backlight levels. Reverting to pre-Win8 ++ * behavior fixes the problem. ++ */ ++ { ++ .callback = dmi_disable_osi_win8, ++ .ident = "Lenovo ThinkPad L430", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), ++ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L430"), ++ }, ++ }, ++ { ++ .callback = dmi_disable_osi_win8, ++ .ident = "Lenovo ThinkPad T430s", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), ++ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T430s"), ++ }, ++ }, ++ { ++ .callback = dmi_disable_osi_win8, ++ .ident = "Lenovo ThinkPad T530", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), ++ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T530"), ++ }, ++ }, ++ { ++ .callback = dmi_disable_osi_win8, ++ .ident = "Lenovo ThinkPad W530", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), ++ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad W530"), ++ }, ++ }, ++ { ++ .callback = dmi_disable_osi_win8, ++ .ident = "Lenovo ThinkPad X1 Carbon", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), ++ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X1 Carbon"), ++ }, ++ }, ++ { ++ .callback = dmi_disable_osi_win8, ++ .ident = "Lenovo ThinkPad X230", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), ++ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X230"), ++ }, ++ }, ++ ++ /* + * BIOS invocation of _OSI(Linux) is almost always a BIOS bug. + * Linux ignores it, except for the machines enumerated below. + */ + diff --git a/kernel/tools/cpupowertools/files/patches/gentoo/2900_dev-root-proc-mount-fix.patch b/kernel/tools/cpupowertools/files/patches/gentoo/2900_dev-root-proc-mount-fix.patch new file mode 100644 index 00000000..6ea86e29 --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/gentoo/2900_dev-root-proc-mount-fix.patch @@ -0,0 +1,30 @@ +--- a/init/do_mounts.c 2014-08-26 08:03:30.000013100 -0400 ++++ b/init/do_mounts.c 2014-08-26 08:11:19.720014712 -0400 +@@ -484,7 +484,10 @@ void __init change_floppy(char *fmt, ... + va_start(args, fmt); + vsprintf(buf, fmt, args); + va_end(args); +- fd = sys_open("/dev/root", O_RDWR | O_NDELAY, 0); ++ if (saved_root_name[0]) ++ fd = sys_open(saved_root_name, O_RDWR | O_NDELAY, 0); ++ else ++ fd = sys_open("/dev/root", O_RDWR | O_NDELAY, 0); + if (fd >= 0) { + sys_ioctl(fd, FDEJECT, 0); + sys_close(fd); +@@ -527,8 +530,13 @@ void __init mount_root(void) + } + #endif + #ifdef CONFIG_BLOCK +- create_dev("/dev/root", ROOT_DEV); +- mount_block_root("/dev/root", root_mountflags); ++ if (saved_root_name[0]) { ++ create_dev(saved_root_name, ROOT_DEV); ++ mount_block_root(saved_root_name, root_mountflags); ++ } else { ++ create_dev("/dev/root", ROOT_DEV); ++ mount_block_root("/dev/root", root_mountflags); ++ } + #endif + } + diff --git a/kernel/tools/cpupowertools/files/patches/gentoo/2905_2disk-resume-image-fix.patch b/kernel/tools/cpupowertools/files/patches/gentoo/2905_2disk-resume-image-fix.patch new file mode 100644 index 00000000..7e95d298 --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/gentoo/2905_2disk-resume-image-fix.patch @@ -0,0 +1,24 @@ +diff --git a/kernel/kmod.c b/kernel/kmod.c +index fb32636..d968882 100644 +--- a/kernel/kmod.c ++++ b/kernel/kmod.c +@@ -575,7 +575,8 @@ + call_usermodehelper_freeinfo(sub_info); + return -EINVAL; + } +- helper_lock(); ++ if (!(current->flags & PF_FREEZER_SKIP)) ++ helper_lock(); + if (!khelper_wq || usermodehelper_disabled) { + retval = -EBUSY; + goto out; +@@ -611,7 +612,8 @@ wait_done: + out: + call_usermodehelper_freeinfo(sub_info); + unlock: +- helper_unlock(); ++ if (!(current->flags & PF_FREEZER_SKIP)) ++ helper_unlock(); + return retval; + } + EXPORT_SYMBOL(call_usermodehelper_exec); diff --git a/kernel/tools/cpupowertools/files/patches/gentoo/4200_fbcondecor-3.19.patch b/kernel/tools/cpupowertools/files/patches/gentoo/4200_fbcondecor-3.19.patch new file mode 100644 index 00000000..29c379fe --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/gentoo/4200_fbcondecor-3.19.patch @@ -0,0 +1,2119 @@ +diff --git a/Documentation/fb/00-INDEX b/Documentation/fb/00-INDEX +index fe85e7c..2230930 100644 +--- a/Documentation/fb/00-INDEX ++++ b/Documentation/fb/00-INDEX +@@ -23,6 +23,8 @@ ep93xx-fb.txt + - info on the driver for EP93xx LCD controller. + fbcon.txt + - intro to and usage guide for the framebuffer console (fbcon). ++fbcondecor.txt ++ - info on the Framebuffer Console Decoration + framebuffer.txt + - introduction to frame buffer devices. + gxfb.txt +diff --git a/Documentation/fb/fbcondecor.txt b/Documentation/fb/fbcondecor.txt +new file mode 100644 +index 0000000..3388c61 +--- /dev/null ++++ b/Documentation/fb/fbcondecor.txt +@@ -0,0 +1,207 @@ ++What is it? ++----------- ++ ++The framebuffer decorations are a kernel feature which allows displaying a ++background picture on selected consoles. ++ ++What do I need to get it to work? ++--------------------------------- ++ ++To get fbcondecor up-and-running you will have to: ++ 1) get a copy of splashutils [1] or a similar program ++ 2) get some fbcondecor themes ++ 3) build the kernel helper program ++ 4) build your kernel with the FB_CON_DECOR option enabled. ++ ++To get fbcondecor operational right after fbcon initialization is finished, you ++will have to include a theme and the kernel helper into your initramfs image. ++Please refer to splashutils documentation for instructions on how to do that. ++ ++[1] The splashutils package can be downloaded from: ++ http://github.com/alanhaggai/fbsplash ++ ++The userspace helper ++-------------------- ++ ++The userspace fbcondecor helper (by default: /sbin/fbcondecor_helper) is called by the ++kernel whenever an important event occurs and the kernel needs some kind of ++job to be carried out. Important events include console switches and video ++mode switches (the kernel requests background images and configuration ++parameters for the current console). The fbcondecor helper must be accessible at ++all times. If it's not, fbcondecor will be switched off automatically. ++ ++It's possible to set path to the fbcondecor helper by writing it to ++/proc/sys/kernel/fbcondecor. ++ ++***************************************************************************** ++ ++The information below is mostly technical stuff. There's probably no need to ++read it unless you plan to develop a userspace helper. ++ ++The fbcondecor protocol ++----------------------- ++ ++The fbcondecor protocol defines a communication interface between the kernel and ++the userspace fbcondecor helper. ++ ++The kernel side is responsible for: ++ ++ * rendering console text, using an image as a background (instead of a ++ standard solid color fbcon uses), ++ * accepting commands from the user via ioctls on the fbcondecor device, ++ * calling the userspace helper to set things up as soon as the fb subsystem ++ is initialized. ++ ++The userspace helper is responsible for everything else, including parsing ++configuration files, decompressing the image files whenever the kernel needs ++it, and communicating with the kernel if necessary. ++ ++The fbcondecor protocol specifies how communication is done in both ways: ++kernel->userspace and userspace->helper. ++ ++Kernel -> Userspace ++------------------- ++ ++The kernel communicates with the userspace helper by calling it and specifying ++the task to be done in a series of arguments. ++ ++The arguments follow the pattern: ++ ++ ++All commands defined in fbcondecor protocol v2 have the following parameters: ++ virtual console ++ framebuffer number ++ theme ++ ++Fbcondecor protocol v1 specified an additional 'fbcondecor mode' after the ++framebuffer number. Fbcondecor protocol v1 is deprecated and should not be used. ++ ++Fbcondecor protocol v2 specifies the following commands: ++ ++getpic ++------ ++ The kernel issues this command to request image data. It's up to the ++ userspace helper to find a background image appropriate for the specified ++ theme and the current resolution. The userspace helper should respond by ++ issuing the FBIOCONDECOR_SETPIC ioctl. ++ ++init ++---- ++ The kernel issues this command after the fbcondecor device is created and ++ the fbcondecor interface is initialized. Upon receiving 'init', the userspace ++ helper should parse the kernel command line (/proc/cmdline) or otherwise ++ decide whether fbcondecor is to be activated. ++ ++ To activate fbcondecor on the first console the helper should issue the ++ FBIOCONDECOR_SETCFG, FBIOCONDECOR_SETPIC and FBIOCONDECOR_SETSTATE commands, ++ in the above-mentioned order. ++ ++ When the userspace helper is called in an early phase of the boot process ++ (right after the initialization of fbcon), no filesystems will be mounted. ++ The helper program should mount sysfs and then create the appropriate ++ framebuffer, fbcondecor and tty0 devices (if they don't already exist) to get ++ current display settings and to be able to communicate with the kernel side. ++ It should probably also mount the procfs to be able to parse the kernel ++ command line parameters. ++ ++ Note that the console sem is not held when the kernel calls fbcondecor_helper ++ with the 'init' command. The fbcondecor helper should perform all ioctls with ++ origin set to FBCON_DECOR_IO_ORIG_USER. ++ ++modechange ++---------- ++ The kernel issues this command on a mode change. The helper's response should ++ be similar to the response to the 'init' command. Note that this time the ++ console sem is held and all ioctls must be performed with origin set to ++ FBCON_DECOR_IO_ORIG_KERNEL. ++ ++ ++Userspace -> Kernel ++------------------- ++ ++Userspace programs can communicate with fbcondecor via ioctls on the ++fbcondecor device. These ioctls are to be used by both the userspace helper ++(called only by the kernel) and userspace configuration tools (run by the users). ++ ++The fbcondecor helper should set the origin field to FBCON_DECOR_IO_ORIG_KERNEL ++when doing the appropriate ioctls. All userspace configuration tools should ++use FBCON_DECOR_IO_ORIG_USER. Failure to set the appropriate value in the origin ++field when performing ioctls from the kernel helper will most likely result ++in a console deadlock. ++ ++FBCON_DECOR_IO_ORIG_KERNEL instructs fbcondecor not to try to acquire the console ++semaphore. Not surprisingly, FBCON_DECOR_IO_ORIG_USER instructs it to acquire ++the console sem. ++ ++The framebuffer console decoration provides the following ioctls (all defined in ++linux/fb.h): ++ ++FBIOCONDECOR_SETPIC ++description: loads a background picture for a virtual console ++argument: struct fbcon_decor_iowrapper*; data: struct fb_image* ++notes: ++If called for consoles other than the current foreground one, the picture data ++will be ignored. ++ ++If the current virtual console is running in a 8-bpp mode, the cmap substruct ++of fb_image has to be filled appropriately: start should be set to 16 (first ++16 colors are reserved for fbcon), len to a value <= 240 and red, green and ++blue should point to valid cmap data. The transp field is ingored. The fields ++dx, dy, bg_color, fg_color in fb_image are ignored as well. ++ ++FBIOCONDECOR_SETCFG ++description: sets the fbcondecor config for a virtual console ++argument: struct fbcon_decor_iowrapper*; data: struct vc_decor* ++notes: The structure has to be filled with valid data. ++ ++FBIOCONDECOR_GETCFG ++description: gets the fbcondecor config for a virtual console ++argument: struct fbcon_decor_iowrapper*; data: struct vc_decor* ++ ++FBIOCONDECOR_SETSTATE ++description: sets the fbcondecor state for a virtual console ++argument: struct fbcon_decor_iowrapper*; data: unsigned int* ++ values: 0 = disabled, 1 = enabled. ++ ++FBIOCONDECOR_GETSTATE ++description: gets the fbcondecor state for a virtual console ++argument: struct fbcon_decor_iowrapper*; data: unsigned int* ++ values: as in FBIOCONDECOR_SETSTATE ++ ++Info on used structures: ++ ++Definition of struct vc_decor can be found in linux/console_decor.h. It's ++heavily commented. Note that the 'theme' field should point to a string ++no longer than FBCON_DECOR_THEME_LEN. When FBIOCONDECOR_GETCFG call is ++performed, the theme field should point to a char buffer of length ++FBCON_DECOR_THEME_LEN. ++ ++Definition of struct fbcon_decor_iowrapper can be found in linux/fb.h. ++The fields in this struct have the following meaning: ++ ++vc: ++Virtual console number. ++ ++origin: ++Specifies if the ioctl is performed as a response to a kernel request. The ++fbcondecor helper should set this field to FBCON_DECOR_IO_ORIG_KERNEL, userspace ++programs should set it to FBCON_DECOR_IO_ORIG_USER. This field is necessary to ++avoid console semaphore deadlocks. ++ ++data: ++Pointer to a data structure appropriate for the performed ioctl. Type of ++the data struct is specified in the ioctls description. ++ ++***************************************************************************** ++ ++Credit ++------ ++ ++Original 'bootsplash' project & implementation by: ++ Volker Poplawski , Stefan Reinauer , ++ Steffen Winterfeldt , Michael Schroeder , ++ Ken Wimer . ++ ++Fbcondecor, fbcondecor protocol design, current implementation & docs by: ++ Michal Januszewski ++ +diff --git a/drivers/Makefile b/drivers/Makefile +index 7183b6a..d576148 100644 +--- a/drivers/Makefile ++++ b/drivers/Makefile +@@ -17,6 +17,10 @@ obj-y += pwm/ + obj-$(CONFIG_PCI) += pci/ + obj-$(CONFIG_PARISC) += parisc/ + obj-$(CONFIG_RAPIDIO) += rapidio/ ++# tty/ comes before char/ so that the VT console is the boot-time ++# default. ++obj-y += tty/ ++obj-y += char/ + obj-y += video/ + obj-y += idle/ + +@@ -42,11 +46,6 @@ obj-$(CONFIG_REGULATOR) += regulator/ + # reset controllers early, since gpu drivers might rely on them to initialize + obj-$(CONFIG_RESET_CONTROLLER) += reset/ + +-# tty/ comes before char/ so that the VT console is the boot-time +-# default. +-obj-y += tty/ +-obj-y += char/ +- + # iommu/ comes before gpu as gpu are using iommu controllers + obj-$(CONFIG_IOMMU_SUPPORT) += iommu/ + +diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig +index fe1cd01..6d2e87a 100644 +--- a/drivers/video/console/Kconfig ++++ b/drivers/video/console/Kconfig +@@ -126,6 +126,19 @@ config FRAMEBUFFER_CONSOLE_ROTATION + such that other users of the framebuffer will remain normally + oriented. + ++config FB_CON_DECOR ++ bool "Support for the Framebuffer Console Decorations" ++ depends on FRAMEBUFFER_CONSOLE=y && !FB_TILEBLITTING ++ default n ++ ---help--- ++ This option enables support for framebuffer console decorations which ++ makes it possible to display images in the background of the system ++ consoles. Note that userspace utilities are necessary in order to take ++ advantage of these features. Refer to Documentation/fb/fbcondecor.txt ++ for more information. ++ ++ If unsure, say N. ++ + config STI_CONSOLE + bool "STI text console" + depends on PARISC +diff --git a/drivers/video/console/Makefile b/drivers/video/console/Makefile +index 43bfa48..cc104b6f 100644 +--- a/drivers/video/console/Makefile ++++ b/drivers/video/console/Makefile +@@ -16,4 +16,5 @@ obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += fbcon_rotate.o fbcon_cw.o fbcon_ud.o \ + fbcon_ccw.o + endif + ++obj-$(CONFIG_FB_CON_DECOR) += fbcondecor.o cfbcondecor.o + obj-$(CONFIG_FB_STI) += sticore.o +diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c +index 61b182b..984384b 100644 +--- a/drivers/video/console/bitblit.c ++++ b/drivers/video/console/bitblit.c +@@ -18,6 +18,7 @@ + #include + #include + #include "fbcon.h" ++#include "fbcondecor.h" + + /* + * Accelerated handlers. +@@ -55,6 +56,13 @@ static void bit_bmove(struct vc_data *vc, struct fb_info *info, int sy, + area.height = height * vc->vc_font.height; + area.width = width * vc->vc_font.width; + ++ if (fbcon_decor_active(info, vc)) { ++ area.sx += vc->vc_decor.tx; ++ area.sy += vc->vc_decor.ty; ++ area.dx += vc->vc_decor.tx; ++ area.dy += vc->vc_decor.ty; ++ } ++ + info->fbops->fb_copyarea(info, &area); + } + +@@ -380,11 +388,15 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode, + cursor.image.depth = 1; + cursor.rop = ROP_XOR; + +- if (info->fbops->fb_cursor) +- err = info->fbops->fb_cursor(info, &cursor); ++ if (fbcon_decor_active(info, vc)) { ++ fbcon_decor_cursor(info, &cursor); ++ } else { ++ if (info->fbops->fb_cursor) ++ err = info->fbops->fb_cursor(info, &cursor); + +- if (err) +- soft_cursor(info, &cursor); ++ if (err) ++ soft_cursor(info, &cursor); ++ } + + ops->cursor_reset = 0; + } +diff --git a/drivers/video/console/cfbcondecor.c b/drivers/video/console/cfbcondecor.c +new file mode 100644 +index 0000000..a2b4497 +--- /dev/null ++++ b/drivers/video/console/cfbcondecor.c +@@ -0,0 +1,471 @@ ++/* ++ * linux/drivers/video/cfbcon_decor.c -- Framebuffer decor render functions ++ * ++ * Copyright (C) 2004 Michal Januszewski ++ * ++ * Code based upon "Bootdecor" (C) 2001-2003 ++ * Volker Poplawski , ++ * Stefan Reinauer , ++ * Steffen Winterfeldt , ++ * Michael Schroeder , ++ * Ken Wimer . ++ * ++ * This file is subject to the terms and conditions of the GNU General Public ++ * License. See the file COPYING in the main directory of this archive for ++ * more details. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "fbcon.h" ++#include "fbcondecor.h" ++ ++#define parse_pixel(shift,bpp,type) \ ++ do { \ ++ if (d & (0x80 >> (shift))) \ ++ dd2[(shift)] = fgx; \ ++ else \ ++ dd2[(shift)] = transparent ? *(type *)decor_src : bgx; \ ++ decor_src += (bpp); \ ++ } while (0) \ ++ ++extern int get_color(struct vc_data *vc, struct fb_info *info, ++ u16 c, int is_fg); ++ ++void fbcon_decor_fix_pseudo_pal(struct fb_info *info, struct vc_data *vc) ++{ ++ int i, j, k; ++ int minlen = min(min(info->var.red.length, info->var.green.length), ++ info->var.blue.length); ++ u32 col; ++ ++ for (j = i = 0; i < 16; i++) { ++ k = color_table[i]; ++ ++ col = ((vc->vc_palette[j++] >> (8-minlen)) ++ << info->var.red.offset); ++ col |= ((vc->vc_palette[j++] >> (8-minlen)) ++ << info->var.green.offset); ++ col |= ((vc->vc_palette[j++] >> (8-minlen)) ++ << info->var.blue.offset); ++ ((u32 *)info->pseudo_palette)[k] = col; ++ } ++} ++ ++void fbcon_decor_renderc(struct fb_info *info, int ypos, int xpos, int height, ++ int width, u8* src, u32 fgx, u32 bgx, u8 transparent) ++{ ++ unsigned int x, y; ++ u32 dd; ++ int bytespp = ((info->var.bits_per_pixel + 7) >> 3); ++ unsigned int d = ypos * info->fix.line_length + xpos * bytespp; ++ unsigned int ds = (ypos * info->var.xres + xpos) * bytespp; ++ u16 dd2[4]; ++ ++ u8* decor_src = (u8 *)(info->bgdecor.data + ds); ++ u8* dst = (u8 *)(info->screen_base + d); ++ ++ if ((ypos + height) > info->var.yres || (xpos + width) > info->var.xres) ++ return; ++ ++ for (y = 0; y < height; y++) { ++ switch (info->var.bits_per_pixel) { ++ ++ case 32: ++ for (x = 0; x < width; x++) { ++ ++ if ((x & 7) == 0) ++ d = *src++; ++ if (d & 0x80) ++ dd = fgx; ++ else ++ dd = transparent ? ++ *(u32 *)decor_src : bgx; ++ ++ d <<= 1; ++ decor_src += 4; ++ fb_writel(dd, dst); ++ dst += 4; ++ } ++ break; ++ case 24: ++ for (x = 0; x < width; x++) { ++ ++ if ((x & 7) == 0) ++ d = *src++; ++ if (d & 0x80) ++ dd = fgx; ++ else ++ dd = transparent ? ++ (*(u32 *)decor_src & 0xffffff) : bgx; ++ ++ d <<= 1; ++ decor_src += 3; ++#ifdef __LITTLE_ENDIAN ++ fb_writew(dd & 0xffff, dst); ++ dst += 2; ++ fb_writeb((dd >> 16), dst); ++#else ++ fb_writew(dd >> 8, dst); ++ dst += 2; ++ fb_writeb(dd & 0xff, dst); ++#endif ++ dst++; ++ } ++ break; ++ case 16: ++ for (x = 0; x < width; x += 2) { ++ if ((x & 7) == 0) ++ d = *src++; ++ ++ parse_pixel(0, 2, u16); ++ parse_pixel(1, 2, u16); ++#ifdef __LITTLE_ENDIAN ++ dd = dd2[0] | (dd2[1] << 16); ++#else ++ dd = dd2[1] | (dd2[0] << 16); ++#endif ++ d <<= 2; ++ fb_writel(dd, dst); ++ dst += 4; ++ } ++ break; ++ ++ case 8: ++ for (x = 0; x < width; x += 4) { ++ if ((x & 7) == 0) ++ d = *src++; ++ ++ parse_pixel(0, 1, u8); ++ parse_pixel(1, 1, u8); ++ parse_pixel(2, 1, u8); ++ parse_pixel(3, 1, u8); ++ ++#ifdef __LITTLE_ENDIAN ++ dd = dd2[0] | (dd2[1] << 8) | (dd2[2] << 16) | (dd2[3] << 24); ++#else ++ dd = dd2[3] | (dd2[2] << 8) | (dd2[1] << 16) | (dd2[0] << 24); ++#endif ++ d <<= 4; ++ fb_writel(dd, dst); ++ dst += 4; ++ } ++ } ++ ++ dst += info->fix.line_length - width * bytespp; ++ decor_src += (info->var.xres - width) * bytespp; ++ } ++} ++ ++#define cc2cx(a) \ ++ ((info->fix.visual == FB_VISUAL_TRUECOLOR || \ ++ info->fix.visual == FB_VISUAL_DIRECTCOLOR) ? \ ++ ((u32*)info->pseudo_palette)[a] : a) ++ ++void fbcon_decor_putcs(struct vc_data *vc, struct fb_info *info, ++ const unsigned short *s, int count, int yy, int xx) ++{ ++ unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; ++ struct fbcon_ops *ops = info->fbcon_par; ++ int fg_color, bg_color, transparent; ++ u8 *src; ++ u32 bgx, fgx; ++ u16 c = scr_readw(s); ++ ++ fg_color = get_color(vc, info, c, 1); ++ bg_color = get_color(vc, info, c, 0); ++ ++ /* Don't paint the background image if console is blanked */ ++ transparent = ops->blank_state ? 0 : ++ (vc->vc_decor.bg_color == bg_color); ++ ++ xx = xx * vc->vc_font.width + vc->vc_decor.tx; ++ yy = yy * vc->vc_font.height + vc->vc_decor.ty; ++ ++ fgx = cc2cx(fg_color); ++ bgx = cc2cx(bg_color); ++ ++ while (count--) { ++ c = scr_readw(s++); ++ src = vc->vc_font.data + (c & charmask) * vc->vc_font.height * ++ ((vc->vc_font.width + 7) >> 3); ++ ++ fbcon_decor_renderc(info, yy, xx, vc->vc_font.height, ++ vc->vc_font.width, src, fgx, bgx, transparent); ++ xx += vc->vc_font.width; ++ } ++} ++ ++void fbcon_decor_cursor(struct fb_info *info, struct fb_cursor *cursor) ++{ ++ int i; ++ unsigned int dsize, s_pitch; ++ struct fbcon_ops *ops = info->fbcon_par; ++ struct vc_data* vc; ++ u8 *src; ++ ++ /* we really don't need any cursors while the console is blanked */ ++ if (info->state != FBINFO_STATE_RUNNING || ops->blank_state) ++ return; ++ ++ vc = vc_cons[ops->currcon].d; ++ ++ src = kmalloc(64 + sizeof(struct fb_image), GFP_ATOMIC); ++ if (!src) ++ return; ++ ++ s_pitch = (cursor->image.width + 7) >> 3; ++ dsize = s_pitch * cursor->image.height; ++ if (cursor->enable) { ++ switch (cursor->rop) { ++ case ROP_XOR: ++ for (i = 0; i < dsize; i++) ++ src[i] = cursor->image.data[i] ^ cursor->mask[i]; ++ break; ++ case ROP_COPY: ++ default: ++ for (i = 0; i < dsize; i++) ++ src[i] = cursor->image.data[i] & cursor->mask[i]; ++ break; ++ } ++ } else ++ memcpy(src, cursor->image.data, dsize); ++ ++ fbcon_decor_renderc(info, ++ cursor->image.dy + vc->vc_decor.ty, ++ cursor->image.dx + vc->vc_decor.tx, ++ cursor->image.height, ++ cursor->image.width, ++ (u8*)src, ++ cc2cx(cursor->image.fg_color), ++ cc2cx(cursor->image.bg_color), ++ cursor->image.bg_color == vc->vc_decor.bg_color); ++ ++ kfree(src); ++} ++ ++static void decorset(u8 *dst, int height, int width, int dstbytes, ++ u32 bgx, int bpp) ++{ ++ int i; ++ ++ if (bpp == 8) ++ bgx |= bgx << 8; ++ if (bpp == 16 || bpp == 8) ++ bgx |= bgx << 16; ++ ++ while (height-- > 0) { ++ u8 *p = dst; ++ ++ switch (bpp) { ++ ++ case 32: ++ for (i=0; i < width; i++) { ++ fb_writel(bgx, p); p += 4; ++ } ++ break; ++ case 24: ++ for (i=0; i < width; i++) { ++#ifdef __LITTLE_ENDIAN ++ fb_writew((bgx & 0xffff),(u16*)p); p += 2; ++ fb_writeb((bgx >> 16),p++); ++#else ++ fb_writew((bgx >> 8),(u16*)p); p += 2; ++ fb_writeb((bgx & 0xff),p++); ++#endif ++ } ++ case 16: ++ for (i=0; i < width/4; i++) { ++ fb_writel(bgx,p); p += 4; ++ fb_writel(bgx,p); p += 4; ++ } ++ if (width & 2) { ++ fb_writel(bgx,p); p += 4; ++ } ++ if (width & 1) ++ fb_writew(bgx,(u16*)p); ++ break; ++ case 8: ++ for (i=0; i < width/4; i++) { ++ fb_writel(bgx,p); p += 4; ++ } ++ ++ if (width & 2) { ++ fb_writew(bgx,p); p += 2; ++ } ++ if (width & 1) ++ fb_writeb(bgx,(u8*)p); ++ break; ++ ++ } ++ dst += dstbytes; ++ } ++} ++ ++void fbcon_decor_copy(u8 *dst, u8 *src, int height, int width, int linebytes, ++ int srclinebytes, int bpp) ++{ ++ int i; ++ ++ while (height-- > 0) { ++ u32 *p = (u32 *)dst; ++ u32 *q = (u32 *)src; ++ ++ switch (bpp) { ++ ++ case 32: ++ for (i=0; i < width; i++) ++ fb_writel(*q++, p++); ++ break; ++ case 24: ++ for (i=0; i < (width*3/4); i++) ++ fb_writel(*q++, p++); ++ if ((width*3) % 4) { ++ if (width & 2) { ++ fb_writeb(*(u8*)q, (u8*)p); ++ } else if (width & 1) { ++ fb_writew(*(u16*)q, (u16*)p); ++ fb_writeb(*(u8*)((u16*)q+1),(u8*)((u16*)p+2)); ++ } ++ } ++ break; ++ case 16: ++ for (i=0; i < width/4; i++) { ++ fb_writel(*q++, p++); ++ fb_writel(*q++, p++); ++ } ++ if (width & 2) ++ fb_writel(*q++, p++); ++ if (width & 1) ++ fb_writew(*(u16*)q, (u16*)p); ++ break; ++ case 8: ++ for (i=0; i < width/4; i++) ++ fb_writel(*q++, p++); ++ ++ if (width & 2) { ++ fb_writew(*(u16*)q, (u16*)p); ++ q = (u32*) ((u16*)q + 1); ++ p = (u32*) ((u16*)p + 1); ++ } ++ if (width & 1) ++ fb_writeb(*(u8*)q, (u8*)p); ++ break; ++ } ++ ++ dst += linebytes; ++ src += srclinebytes; ++ } ++} ++ ++static void decorfill(struct fb_info *info, int sy, int sx, int height, ++ int width) ++{ ++ int bytespp = ((info->var.bits_per_pixel + 7) >> 3); ++ int d = sy * info->fix.line_length + sx * bytespp; ++ int ds = (sy * info->var.xres + sx) * bytespp; ++ ++ fbcon_decor_copy((u8 *)(info->screen_base + d), (u8 *)(info->bgdecor.data + ds), ++ height, width, info->fix.line_length, info->var.xres * bytespp, ++ info->var.bits_per_pixel); ++} ++ ++void fbcon_decor_clear(struct vc_data *vc, struct fb_info *info, int sy, int sx, ++ int height, int width) ++{ ++ int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; ++ struct fbcon_ops *ops = info->fbcon_par; ++ u8 *dst; ++ int transparent, bg_color = attr_bgcol_ec(bgshift, vc, info); ++ ++ transparent = (vc->vc_decor.bg_color == bg_color); ++ sy = sy * vc->vc_font.height + vc->vc_decor.ty; ++ sx = sx * vc->vc_font.width + vc->vc_decor.tx; ++ height *= vc->vc_font.height; ++ width *= vc->vc_font.width; ++ ++ /* Don't paint the background image if console is blanked */ ++ if (transparent && !ops->blank_state) { ++ decorfill(info, sy, sx, height, width); ++ } else { ++ dst = (u8 *)(info->screen_base + sy * info->fix.line_length + ++ sx * ((info->var.bits_per_pixel + 7) >> 3)); ++ decorset(dst, height, width, info->fix.line_length, cc2cx(bg_color), ++ info->var.bits_per_pixel); ++ } ++} ++ ++void fbcon_decor_clear_margins(struct vc_data *vc, struct fb_info *info, ++ int bottom_only) ++{ ++ unsigned int tw = vc->vc_cols*vc->vc_font.width; ++ unsigned int th = vc->vc_rows*vc->vc_font.height; ++ ++ if (!bottom_only) { ++ /* top margin */ ++ decorfill(info, 0, 0, vc->vc_decor.ty, info->var.xres); ++ /* left margin */ ++ decorfill(info, vc->vc_decor.ty, 0, th, vc->vc_decor.tx); ++ /* right margin */ ++ decorfill(info, vc->vc_decor.ty, vc->vc_decor.tx + tw, th, ++ info->var.xres - vc->vc_decor.tx - tw); ++ } ++ decorfill(info, vc->vc_decor.ty + th, 0, ++ info->var.yres - vc->vc_decor.ty - th, info->var.xres); ++} ++ ++void fbcon_decor_bmove_redraw(struct vc_data *vc, struct fb_info *info, int y, ++ int sx, int dx, int width) ++{ ++ u16 *d = (u16 *) (vc->vc_origin + vc->vc_size_row * y + dx * 2); ++ u16 *s = d + (dx - sx); ++ u16 *start = d; ++ u16 *ls = d; ++ u16 *le = d + width; ++ u16 c; ++ int x = dx; ++ u16 attr = 1; ++ ++ do { ++ c = scr_readw(d); ++ if (attr != (c & 0xff00)) { ++ attr = c & 0xff00; ++ if (d > start) { ++ fbcon_decor_putcs(vc, info, start, d - start, y, x); ++ x += d - start; ++ start = d; ++ } ++ } ++ if (s >= ls && s < le && c == scr_readw(s)) { ++ if (d > start) { ++ fbcon_decor_putcs(vc, info, start, d - start, y, x); ++ x += d - start + 1; ++ start = d + 1; ++ } else { ++ x++; ++ start++; ++ } ++ } ++ s++; ++ d++; ++ } while (d < le); ++ if (d > start) ++ fbcon_decor_putcs(vc, info, start, d - start, y, x); ++} ++ ++void fbcon_decor_blank(struct vc_data *vc, struct fb_info *info, int blank) ++{ ++ if (blank) { ++ decorset((u8 *)info->screen_base, info->var.yres, info->var.xres, ++ info->fix.line_length, 0, info->var.bits_per_pixel); ++ } else { ++ update_screen(vc); ++ fbcon_decor_clear_margins(vc, info, 0); ++ } ++} ++ +diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c +index f447734..da50d61 100644 +--- a/drivers/video/console/fbcon.c ++++ b/drivers/video/console/fbcon.c +@@ -79,6 +79,7 @@ + #include + + #include "fbcon.h" ++#include "../console/fbcondecor.h" + + #ifdef FBCONDEBUG + # define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__ , ## args) +@@ -94,7 +95,7 @@ enum { + + static struct display fb_display[MAX_NR_CONSOLES]; + +-static signed char con2fb_map[MAX_NR_CONSOLES]; ++signed char con2fb_map[MAX_NR_CONSOLES]; + static signed char con2fb_map_boot[MAX_NR_CONSOLES]; + + static int logo_lines; +@@ -286,7 +287,7 @@ static inline int fbcon_is_inactive(struct vc_data *vc, struct fb_info *info) + !vt_force_oops_output(vc); + } + +-static int get_color(struct vc_data *vc, struct fb_info *info, ++int get_color(struct vc_data *vc, struct fb_info *info, + u16 c, int is_fg) + { + int depth = fb_get_color_depth(&info->var, &info->fix); +@@ -551,6 +552,9 @@ static int do_fbcon_takeover(int show_logo) + info_idx = -1; + } else { + fbcon_has_console_bind = 1; ++#ifdef CONFIG_FB_CON_DECOR ++ fbcon_decor_init(); ++#endif + } + + return err; +@@ -1007,6 +1011,12 @@ static const char *fbcon_startup(void) + rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); + cols /= vc->vc_font.width; + rows /= vc->vc_font.height; ++ ++ if (fbcon_decor_active(info, vc)) { ++ cols = vc->vc_decor.twidth / vc->vc_font.width; ++ rows = vc->vc_decor.theight / vc->vc_font.height; ++ } ++ + vc_resize(vc, cols, rows); + + DPRINTK("mode: %s\n", info->fix.id); +@@ -1036,7 +1046,7 @@ static void fbcon_init(struct vc_data *vc, int init) + cap = info->flags; + + if (vc != svc || logo_shown == FBCON_LOGO_DONTSHOW || +- (info->fix.type == FB_TYPE_TEXT)) ++ (info->fix.type == FB_TYPE_TEXT) || fbcon_decor_active(info, vc)) + logo = 0; + + if (var_to_display(p, &info->var, info)) +@@ -1260,6 +1270,11 @@ static void fbcon_clear(struct vc_data *vc, int sy, int sx, int height, + fbcon_clear_margins(vc, 0); + } + ++ if (fbcon_decor_active(info, vc)) { ++ fbcon_decor_clear(vc, info, sy, sx, height, width); ++ return; ++ } ++ + /* Split blits that cross physical y_wrap boundary */ + + y_break = p->vrows - p->yscroll; +@@ -1279,10 +1294,15 @@ static void fbcon_putcs(struct vc_data *vc, const unsigned short *s, + struct display *p = &fb_display[vc->vc_num]; + struct fbcon_ops *ops = info->fbcon_par; + +- if (!fbcon_is_inactive(vc, info)) +- ops->putcs(vc, info, s, count, real_y(p, ypos), xpos, +- get_color(vc, info, scr_readw(s), 1), +- get_color(vc, info, scr_readw(s), 0)); ++ if (!fbcon_is_inactive(vc, info)) { ++ ++ if (fbcon_decor_active(info, vc)) ++ fbcon_decor_putcs(vc, info, s, count, ypos, xpos); ++ else ++ ops->putcs(vc, info, s, count, real_y(p, ypos), xpos, ++ get_color(vc, info, scr_readw(s), 1), ++ get_color(vc, info, scr_readw(s), 0)); ++ } + } + + static void fbcon_putc(struct vc_data *vc, int c, int ypos, int xpos) +@@ -1298,8 +1318,13 @@ static void fbcon_clear_margins(struct vc_data *vc, int bottom_only) + struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; + struct fbcon_ops *ops = info->fbcon_par; + +- if (!fbcon_is_inactive(vc, info)) +- ops->clear_margins(vc, info, bottom_only); ++ if (!fbcon_is_inactive(vc, info)) { ++ if (fbcon_decor_active(info, vc)) { ++ fbcon_decor_clear_margins(vc, info, bottom_only); ++ } else { ++ ops->clear_margins(vc, info, bottom_only); ++ } ++ } + } + + static void fbcon_cursor(struct vc_data *vc, int mode) +@@ -1819,7 +1844,7 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir, + count = vc->vc_rows; + if (softback_top) + fbcon_softback_note(vc, t, count); +- if (logo_shown >= 0) ++ if (logo_shown >= 0 || fbcon_decor_active(info, vc)) + goto redraw_up; + switch (p->scrollmode) { + case SCROLL_MOVE: +@@ -1912,6 +1937,8 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir, + count = vc->vc_rows; + if (logo_shown >= 0) + goto redraw_down; ++ if (fbcon_decor_active(info, vc)) ++ goto redraw_down; + switch (p->scrollmode) { + case SCROLL_MOVE: + fbcon_redraw_blit(vc, info, p, b - 1, b - t - count, +@@ -2060,6 +2087,13 @@ static void fbcon_bmove_rec(struct vc_data *vc, struct display *p, int sy, int s + } + return; + } ++ ++ if (fbcon_decor_active(info, vc) && sy == dy && height == 1) { ++ /* must use slower redraw bmove to keep background pic intact */ ++ fbcon_decor_bmove_redraw(vc, info, sy, sx, dx, width); ++ return; ++ } ++ + ops->bmove(vc, info, real_y(p, sy), sx, real_y(p, dy), dx, + height, width); + } +@@ -2130,8 +2164,8 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width, + var.yres = virt_h * virt_fh; + x_diff = info->var.xres - var.xres; + y_diff = info->var.yres - var.yres; +- if (x_diff < 0 || x_diff > virt_fw || +- y_diff < 0 || y_diff > virt_fh) { ++ if ((x_diff < 0 || x_diff > virt_fw || ++ y_diff < 0 || y_diff > virt_fh) && !vc->vc_decor.state) { + const struct fb_videomode *mode; + + DPRINTK("attempting resize %ix%i\n", var.xres, var.yres); +@@ -2167,6 +2201,21 @@ static int fbcon_switch(struct vc_data *vc) + + info = registered_fb[con2fb_map[vc->vc_num]]; + ops = info->fbcon_par; ++ prev_console = ops->currcon; ++ if (prev_console != -1) ++ old_info = registered_fb[con2fb_map[prev_console]]; ++ ++#ifdef CONFIG_FB_CON_DECOR ++ if (!fbcon_decor_active_vc(vc) && info->fix.visual == FB_VISUAL_DIRECTCOLOR) { ++ struct vc_data *vc_curr = vc_cons[prev_console].d; ++ if (vc_curr && fbcon_decor_active_vc(vc_curr)) { ++ /* Clear the screen to avoid displaying funky colors during ++ * palette updates. */ ++ memset((u8*)info->screen_base + info->fix.line_length * info->var.yoffset, ++ 0, info->var.yres * info->fix.line_length); ++ } ++ } ++#endif + + if (softback_top) { + if (softback_lines) +@@ -2185,9 +2234,6 @@ static int fbcon_switch(struct vc_data *vc) + logo_shown = FBCON_LOGO_CANSHOW; + } + +- prev_console = ops->currcon; +- if (prev_console != -1) +- old_info = registered_fb[con2fb_map[prev_console]]; + /* + * FIXME: If we have multiple fbdev's loaded, we need to + * update all info->currcon. Perhaps, we can place this +@@ -2231,6 +2277,18 @@ static int fbcon_switch(struct vc_data *vc) + fbcon_del_cursor_timer(old_info); + } + ++ if (fbcon_decor_active_vc(vc)) { ++ struct vc_data *vc_curr = vc_cons[prev_console].d; ++ ++ if (!vc_curr->vc_decor.theme || ++ strcmp(vc->vc_decor.theme, vc_curr->vc_decor.theme) || ++ (fbcon_decor_active_nores(info, vc_curr) && ++ !fbcon_decor_active(info, vc_curr))) { ++ fbcon_decor_disable(vc, 0); ++ fbcon_decor_call_helper("modechange", vc->vc_num); ++ } ++ } ++ + if (fbcon_is_inactive(vc, info) || + ops->blank_state != FB_BLANK_UNBLANK) + fbcon_del_cursor_timer(info); +@@ -2339,15 +2397,20 @@ static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch) + } + } + +- if (!fbcon_is_inactive(vc, info)) { ++ if (!fbcon_is_inactive(vc, info)) { + if (ops->blank_state != blank) { + ops->blank_state = blank; + fbcon_cursor(vc, blank ? CM_ERASE : CM_DRAW); + ops->cursor_flash = (!blank); + +- if (!(info->flags & FBINFO_MISC_USEREVENT)) +- if (fb_blank(info, blank)) +- fbcon_generic_blank(vc, info, blank); ++ if (!(info->flags & FBINFO_MISC_USEREVENT)) { ++ if (fb_blank(info, blank)) { ++ if (fbcon_decor_active(info, vc)) ++ fbcon_decor_blank(vc, info, blank); ++ else ++ fbcon_generic_blank(vc, info, blank); ++ } ++ } + } + + if (!blank) +@@ -2522,13 +2585,22 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h, + } + + if (resize) { ++ /* reset wrap/pan */ + int cols, rows; + + cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres); + rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); ++ ++ if (fbcon_decor_active(info, vc)) { ++ info->var.xoffset = info->var.yoffset = p->yscroll = 0; ++ cols = vc->vc_decor.twidth; ++ rows = vc->vc_decor.theight; ++ } + cols /= w; + rows /= h; ++ + vc_resize(vc, cols, rows); ++ + if (CON_IS_VISIBLE(vc) && softback_buf) + fbcon_update_softback(vc); + } else if (CON_IS_VISIBLE(vc) +@@ -2657,7 +2729,11 @@ static int fbcon_set_palette(struct vc_data *vc, unsigned char *table) + int i, j, k, depth; + u8 val; + +- if (fbcon_is_inactive(vc, info)) ++ if (fbcon_is_inactive(vc, info) ++#ifdef CONFIG_FB_CON_DECOR ++ || vc->vc_num != fg_console ++#endif ++ ) + return -EINVAL; + + if (!CON_IS_VISIBLE(vc)) +@@ -2683,14 +2759,56 @@ static int fbcon_set_palette(struct vc_data *vc, unsigned char *table) + } else + fb_copy_cmap(fb_default_cmap(1 << depth), &palette_cmap); + +- return fb_set_cmap(&palette_cmap, info); ++ if (fbcon_decor_active(info, vc_cons[fg_console].d) && ++ info->fix.visual == FB_VISUAL_DIRECTCOLOR) { ++ ++ u16 *red, *green, *blue; ++ int minlen = min(min(info->var.red.length, info->var.green.length), ++ info->var.blue.length); ++ int h; ++ ++ struct fb_cmap cmap = { ++ .start = 0, ++ .len = (1 << minlen), ++ .red = NULL, ++ .green = NULL, ++ .blue = NULL, ++ .transp = NULL ++ }; ++ ++ red = kmalloc(256 * sizeof(u16) * 3, GFP_KERNEL); ++ ++ if (!red) ++ goto out; ++ ++ green = red + 256; ++ blue = green + 256; ++ cmap.red = red; ++ cmap.green = green; ++ cmap.blue = blue; ++ ++ for (i = 0; i < cmap.len; i++) { ++ red[i] = green[i] = blue[i] = (0xffff * i)/(cmap.len-1); ++ } ++ ++ h = fb_set_cmap(&cmap, info); ++ fbcon_decor_fix_pseudo_pal(info, vc_cons[fg_console].d); ++ kfree(red); ++ ++ return h; ++ ++ } else if (fbcon_decor_active(info, vc_cons[fg_console].d) && ++ info->var.bits_per_pixel == 8 && info->bgdecor.cmap.red != NULL) ++ fb_set_cmap(&info->bgdecor.cmap, info); ++ ++out: return fb_set_cmap(&palette_cmap, info); + } + + static u16 *fbcon_screen_pos(struct vc_data *vc, int offset) + { + unsigned long p; + int line; +- ++ + if (vc->vc_num != fg_console || !softback_lines) + return (u16 *) (vc->vc_origin + offset); + line = offset / vc->vc_size_row; +@@ -2909,7 +3027,14 @@ static void fbcon_modechanged(struct fb_info *info) + rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); + cols /= vc->vc_font.width; + rows /= vc->vc_font.height; +- vc_resize(vc, cols, rows); ++ ++ if (!fbcon_decor_active_nores(info, vc)) { ++ vc_resize(vc, cols, rows); ++ } else { ++ fbcon_decor_disable(vc, 0); ++ fbcon_decor_call_helper("modechange", vc->vc_num); ++ } ++ + updatescrollmode(p, info, vc); + scrollback_max = 0; + scrollback_current = 0; +@@ -2954,7 +3079,9 @@ static void fbcon_set_all_vcs(struct fb_info *info) + rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); + cols /= vc->vc_font.width; + rows /= vc->vc_font.height; +- vc_resize(vc, cols, rows); ++ if (!fbcon_decor_active_nores(info, vc)) { ++ vc_resize(vc, cols, rows); ++ } + } + + if (fg != -1) +@@ -3596,6 +3723,7 @@ static void fbcon_exit(void) + } + } + ++ fbcon_decor_exit(); + fbcon_has_exited = 1; + } + +diff --git a/drivers/video/console/fbcondecor.c b/drivers/video/console/fbcondecor.c +new file mode 100644 +index 0000000..babc8c5 +--- /dev/null ++++ b/drivers/video/console/fbcondecor.c +@@ -0,0 +1,555 @@ ++/* ++ * linux/drivers/video/console/fbcondecor.c -- Framebuffer console decorations ++ * ++ * Copyright (C) 2004-2009 Michal Januszewski ++ * ++ * Code based upon "Bootsplash" (C) 2001-2003 ++ * Volker Poplawski , ++ * Stefan Reinauer , ++ * Steffen Winterfeldt , ++ * Michael Schroeder , ++ * Ken Wimer . ++ * ++ * Compat ioctl support by Thorsten Klein . ++ * ++ * This file is subject to the terms and conditions of the GNU General Public ++ * License. See the file COPYING in the main directory of this archive for ++ * more details. ++ * ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "fbcon.h" ++#include "fbcondecor.h" ++ ++extern signed char con2fb_map[]; ++static int fbcon_decor_enable(struct vc_data *vc); ++char fbcon_decor_path[KMOD_PATH_LEN] = "/sbin/fbcondecor_helper"; ++static int initialized = 0; ++ ++int fbcon_decor_call_helper(char* cmd, unsigned short vc) ++{ ++ char *envp[] = { ++ "HOME=/", ++ "PATH=/sbin:/bin", ++ NULL ++ }; ++ ++ char tfb[5]; ++ char tcons[5]; ++ unsigned char fb = (int) con2fb_map[vc]; ++ ++ char *argv[] = { ++ fbcon_decor_path, ++ "2", ++ cmd, ++ tcons, ++ tfb, ++ vc_cons[vc].d->vc_decor.theme, ++ NULL ++ }; ++ ++ snprintf(tfb,5,"%d",fb); ++ snprintf(tcons,5,"%d",vc); ++ ++ return call_usermodehelper(fbcon_decor_path, argv, envp, UMH_WAIT_EXEC); ++} ++ ++/* Disables fbcondecor on a virtual console; called with console sem held. */ ++int fbcon_decor_disable(struct vc_data *vc, unsigned char redraw) ++{ ++ struct fb_info* info; ++ ++ if (!vc->vc_decor.state) ++ return -EINVAL; ++ ++ info = registered_fb[(int) con2fb_map[vc->vc_num]]; ++ ++ if (info == NULL) ++ return -EINVAL; ++ ++ vc->vc_decor.state = 0; ++ vc_resize(vc, info->var.xres / vc->vc_font.width, ++ info->var.yres / vc->vc_font.height); ++ ++ if (fg_console == vc->vc_num && redraw) { ++ redraw_screen(vc, 0); ++ update_region(vc, vc->vc_origin + ++ vc->vc_size_row * vc->vc_top, ++ vc->vc_size_row * (vc->vc_bottom - vc->vc_top) / 2); ++ } ++ ++ printk(KERN_INFO "fbcondecor: switched decor state to 'off' on console %d\n", ++ vc->vc_num); ++ ++ return 0; ++} ++ ++/* Enables fbcondecor on a virtual console; called with console sem held. */ ++static int fbcon_decor_enable(struct vc_data *vc) ++{ ++ struct fb_info* info; ++ ++ info = registered_fb[(int) con2fb_map[vc->vc_num]]; ++ ++ if (vc->vc_decor.twidth == 0 || vc->vc_decor.theight == 0 || ++ info == NULL || vc->vc_decor.state || (!info->bgdecor.data && ++ vc->vc_num == fg_console)) ++ return -EINVAL; ++ ++ vc->vc_decor.state = 1; ++ vc_resize(vc, vc->vc_decor.twidth / vc->vc_font.width, ++ vc->vc_decor.theight / vc->vc_font.height); ++ ++ if (fg_console == vc->vc_num) { ++ redraw_screen(vc, 0); ++ update_region(vc, vc->vc_origin + ++ vc->vc_size_row * vc->vc_top, ++ vc->vc_size_row * (vc->vc_bottom - vc->vc_top) / 2); ++ fbcon_decor_clear_margins(vc, info, 0); ++ } ++ ++ printk(KERN_INFO "fbcondecor: switched decor state to 'on' on console %d\n", ++ vc->vc_num); ++ ++ return 0; ++} ++ ++static inline int fbcon_decor_ioctl_dosetstate(struct vc_data *vc, unsigned int state, unsigned char origin) ++{ ++ int ret; ++ ++// if (origin == FBCON_DECOR_IO_ORIG_USER) ++ console_lock(); ++ if (!state) ++ ret = fbcon_decor_disable(vc, 1); ++ else ++ ret = fbcon_decor_enable(vc); ++// if (origin == FBCON_DECOR_IO_ORIG_USER) ++ console_unlock(); ++ ++ return ret; ++} ++ ++static inline void fbcon_decor_ioctl_dogetstate(struct vc_data *vc, unsigned int *state) ++{ ++ *state = vc->vc_decor.state; ++} ++ ++static int fbcon_decor_ioctl_dosetcfg(struct vc_data *vc, struct vc_decor *cfg, unsigned char origin) ++{ ++ struct fb_info *info; ++ int len; ++ char *tmp; ++ ++ info = registered_fb[(int) con2fb_map[vc->vc_num]]; ++ ++ if (info == NULL || !cfg->twidth || !cfg->theight || ++ cfg->tx + cfg->twidth > info->var.xres || ++ cfg->ty + cfg->theight > info->var.yres) ++ return -EINVAL; ++ ++ len = strlen_user(cfg->theme); ++ if (!len || len > FBCON_DECOR_THEME_LEN) ++ return -EINVAL; ++ tmp = kmalloc(len, GFP_KERNEL); ++ if (!tmp) ++ return -ENOMEM; ++ if (copy_from_user(tmp, (void __user *)cfg->theme, len)) ++ return -EFAULT; ++ cfg->theme = tmp; ++ cfg->state = 0; ++ ++ /* If this ioctl is a response to a request from kernel, the console sem ++ * is already held; we also don't need to disable decor because either the ++ * new config and background picture will be successfully loaded, and the ++ * decor will stay on, or in case of a failure it'll be turned off in fbcon. */ ++// if (origin == FBCON_DECOR_IO_ORIG_USER) { ++ console_lock(); ++ if (vc->vc_decor.state) ++ fbcon_decor_disable(vc, 1); ++// } ++ ++ if (vc->vc_decor.theme) ++ kfree(vc->vc_decor.theme); ++ ++ vc->vc_decor = *cfg; ++ ++// if (origin == FBCON_DECOR_IO_ORIG_USER) ++ console_unlock(); ++ ++ printk(KERN_INFO "fbcondecor: console %d using theme '%s'\n", ++ vc->vc_num, vc->vc_decor.theme); ++ return 0; ++} ++ ++static int fbcon_decor_ioctl_dogetcfg(struct vc_data *vc, struct vc_decor *decor) ++{ ++ char __user *tmp; ++ ++ tmp = decor->theme; ++ *decor = vc->vc_decor; ++ decor->theme = tmp; ++ ++ if (vc->vc_decor.theme) { ++ if (copy_to_user(tmp, vc->vc_decor.theme, strlen(vc->vc_decor.theme) + 1)) ++ return -EFAULT; ++ } else ++ if (put_user(0, tmp)) ++ return -EFAULT; ++ ++ return 0; ++} ++ ++static int fbcon_decor_ioctl_dosetpic(struct vc_data *vc, struct fb_image *img, unsigned char origin) ++{ ++ struct fb_info *info; ++ int len; ++ u8 *tmp; ++ ++ if (vc->vc_num != fg_console) ++ return -EINVAL; ++ ++ info = registered_fb[(int) con2fb_map[vc->vc_num]]; ++ ++ if (info == NULL) ++ return -EINVAL; ++ ++ if (img->width != info->var.xres || img->height != info->var.yres) { ++ printk(KERN_ERR "fbcondecor: picture dimensions mismatch\n"); ++ printk(KERN_ERR "%dx%d vs %dx%d\n", img->width, img->height, info->var.xres, info->var.yres); ++ return -EINVAL; ++ } ++ ++ if (img->depth != info->var.bits_per_pixel) { ++ printk(KERN_ERR "fbcondecor: picture depth mismatch\n"); ++ return -EINVAL; ++ } ++ ++ if (img->depth == 8) { ++ if (!img->cmap.len || !img->cmap.red || !img->cmap.green || ++ !img->cmap.blue) ++ return -EINVAL; ++ ++ tmp = vmalloc(img->cmap.len * 3 * 2); ++ if (!tmp) ++ return -ENOMEM; ++ ++ if (copy_from_user(tmp, ++ (void __user*)img->cmap.red, (img->cmap.len << 1)) || ++ copy_from_user(tmp + (img->cmap.len << 1), ++ (void __user*)img->cmap.green, (img->cmap.len << 1)) || ++ copy_from_user(tmp + (img->cmap.len << 2), ++ (void __user*)img->cmap.blue, (img->cmap.len << 1))) { ++ vfree(tmp); ++ return -EFAULT; ++ } ++ ++ img->cmap.transp = NULL; ++ img->cmap.red = (u16*)tmp; ++ img->cmap.green = img->cmap.red + img->cmap.len; ++ img->cmap.blue = img->cmap.green + img->cmap.len; ++ } else { ++ img->cmap.red = NULL; ++ } ++ ++ len = ((img->depth + 7) >> 3) * img->width * img->height; ++ ++ /* ++ * Allocate an additional byte so that we never go outside of the ++ * buffer boundaries in the rendering functions in a 24 bpp mode. ++ */ ++ tmp = vmalloc(len + 1); ++ ++ if (!tmp) ++ goto out; ++ ++ if (copy_from_user(tmp, (void __user*)img->data, len)) ++ goto out; ++ ++ img->data = tmp; ++ ++ /* If this ioctl is a response to a request from kernel, the console sem ++ * is already held. */ ++// if (origin == FBCON_DECOR_IO_ORIG_USER) ++ console_lock(); ++ ++ if (info->bgdecor.data) ++ vfree((u8*)info->bgdecor.data); ++ if (info->bgdecor.cmap.red) ++ vfree(info->bgdecor.cmap.red); ++ ++ info->bgdecor = *img; ++ ++ if (fbcon_decor_active_vc(vc) && fg_console == vc->vc_num) { ++ redraw_screen(vc, 0); ++ update_region(vc, vc->vc_origin + ++ vc->vc_size_row * vc->vc_top, ++ vc->vc_size_row * (vc->vc_bottom - vc->vc_top) / 2); ++ fbcon_decor_clear_margins(vc, info, 0); ++ } ++ ++// if (origin == FBCON_DECOR_IO_ORIG_USER) ++ console_unlock(); ++ ++ return 0; ++ ++out: if (img->cmap.red) ++ vfree(img->cmap.red); ++ ++ if (tmp) ++ vfree(tmp); ++ return -ENOMEM; ++} ++ ++static long fbcon_decor_ioctl(struct file *filp, u_int cmd, u_long arg) ++{ ++ struct fbcon_decor_iowrapper __user *wrapper = (void __user*) arg; ++ struct vc_data *vc = NULL; ++ unsigned short vc_num = 0; ++ unsigned char origin = 0; ++ void __user *data = NULL; ++ ++ if (!access_ok(VERIFY_READ, wrapper, ++ sizeof(struct fbcon_decor_iowrapper))) ++ return -EFAULT; ++ ++ __get_user(vc_num, &wrapper->vc); ++ __get_user(origin, &wrapper->origin); ++ __get_user(data, &wrapper->data); ++ ++ if (!vc_cons_allocated(vc_num)) ++ return -EINVAL; ++ ++ vc = vc_cons[vc_num].d; ++ ++ switch (cmd) { ++ case FBIOCONDECOR_SETPIC: ++ { ++ struct fb_image img; ++ if (copy_from_user(&img, (struct fb_image __user *)data, sizeof(struct fb_image))) ++ return -EFAULT; ++ ++ return fbcon_decor_ioctl_dosetpic(vc, &img, origin); ++ } ++ case FBIOCONDECOR_SETCFG: ++ { ++ struct vc_decor cfg; ++ if (copy_from_user(&cfg, (struct vc_decor __user *)data, sizeof(struct vc_decor))) ++ return -EFAULT; ++ ++ return fbcon_decor_ioctl_dosetcfg(vc, &cfg, origin); ++ } ++ case FBIOCONDECOR_GETCFG: ++ { ++ int rval; ++ struct vc_decor cfg; ++ ++ if (copy_from_user(&cfg, (struct vc_decor __user *)data, sizeof(struct vc_decor))) ++ return -EFAULT; ++ ++ rval = fbcon_decor_ioctl_dogetcfg(vc, &cfg); ++ ++ if (copy_to_user(data, &cfg, sizeof(struct vc_decor))) ++ return -EFAULT; ++ return rval; ++ } ++ case FBIOCONDECOR_SETSTATE: ++ { ++ unsigned int state = 0; ++ if (get_user(state, (unsigned int __user *)data)) ++ return -EFAULT; ++ return fbcon_decor_ioctl_dosetstate(vc, state, origin); ++ } ++ case FBIOCONDECOR_GETSTATE: ++ { ++ unsigned int state = 0; ++ fbcon_decor_ioctl_dogetstate(vc, &state); ++ return put_user(state, (unsigned int __user *)data); ++ } ++ ++ default: ++ return -ENOIOCTLCMD; ++ } ++} ++ ++#ifdef CONFIG_COMPAT ++ ++static long fbcon_decor_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { ++ ++ struct fbcon_decor_iowrapper32 __user *wrapper = (void __user *)arg; ++ struct vc_data *vc = NULL; ++ unsigned short vc_num = 0; ++ unsigned char origin = 0; ++ compat_uptr_t data_compat = 0; ++ void __user *data = NULL; ++ ++ if (!access_ok(VERIFY_READ, wrapper, ++ sizeof(struct fbcon_decor_iowrapper32))) ++ return -EFAULT; ++ ++ __get_user(vc_num, &wrapper->vc); ++ __get_user(origin, &wrapper->origin); ++ __get_user(data_compat, &wrapper->data); ++ data = compat_ptr(data_compat); ++ ++ if (!vc_cons_allocated(vc_num)) ++ return -EINVAL; ++ ++ vc = vc_cons[vc_num].d; ++ ++ switch (cmd) { ++ case FBIOCONDECOR_SETPIC32: ++ { ++ struct fb_image32 img_compat; ++ struct fb_image img; ++ ++ if (copy_from_user(&img_compat, (struct fb_image32 __user *)data, sizeof(struct fb_image32))) ++ return -EFAULT; ++ ++ fb_image_from_compat(img, img_compat); ++ ++ return fbcon_decor_ioctl_dosetpic(vc, &img, origin); ++ } ++ ++ case FBIOCONDECOR_SETCFG32: ++ { ++ struct vc_decor32 cfg_compat; ++ struct vc_decor cfg; ++ ++ if (copy_from_user(&cfg_compat, (struct vc_decor32 __user *)data, sizeof(struct vc_decor32))) ++ return -EFAULT; ++ ++ vc_decor_from_compat(cfg, cfg_compat); ++ ++ return fbcon_decor_ioctl_dosetcfg(vc, &cfg, origin); ++ } ++ ++ case FBIOCONDECOR_GETCFG32: ++ { ++ int rval; ++ struct vc_decor32 cfg_compat; ++ struct vc_decor cfg; ++ ++ if (copy_from_user(&cfg_compat, (struct vc_decor32 __user *)data, sizeof(struct vc_decor32))) ++ return -EFAULT; ++ cfg.theme = compat_ptr(cfg_compat.theme); ++ ++ rval = fbcon_decor_ioctl_dogetcfg(vc, &cfg); ++ ++ vc_decor_to_compat(cfg_compat, cfg); ++ ++ if (copy_to_user((struct vc_decor32 __user *)data, &cfg_compat, sizeof(struct vc_decor32))) ++ return -EFAULT; ++ return rval; ++ } ++ ++ case FBIOCONDECOR_SETSTATE32: ++ { ++ compat_uint_t state_compat = 0; ++ unsigned int state = 0; ++ ++ if (get_user(state_compat, (compat_uint_t __user *)data)) ++ return -EFAULT; ++ ++ state = (unsigned int)state_compat; ++ ++ return fbcon_decor_ioctl_dosetstate(vc, state, origin); ++ } ++ ++ case FBIOCONDECOR_GETSTATE32: ++ { ++ compat_uint_t state_compat = 0; ++ unsigned int state = 0; ++ ++ fbcon_decor_ioctl_dogetstate(vc, &state); ++ state_compat = (compat_uint_t)state; ++ ++ return put_user(state_compat, (compat_uint_t __user *)data); ++ } ++ ++ default: ++ return -ENOIOCTLCMD; ++ } ++} ++#else ++ #define fbcon_decor_compat_ioctl NULL ++#endif ++ ++static struct file_operations fbcon_decor_ops = { ++ .owner = THIS_MODULE, ++ .unlocked_ioctl = fbcon_decor_ioctl, ++ .compat_ioctl = fbcon_decor_compat_ioctl ++}; ++ ++static struct miscdevice fbcon_decor_dev = { ++ .minor = MISC_DYNAMIC_MINOR, ++ .name = "fbcondecor", ++ .fops = &fbcon_decor_ops ++}; ++ ++void fbcon_decor_reset(void) ++{ ++ int i; ++ ++ for (i = 0; i < num_registered_fb; i++) { ++ registered_fb[i]->bgdecor.data = NULL; ++ registered_fb[i]->bgdecor.cmap.red = NULL; ++ } ++ ++ for (i = 0; i < MAX_NR_CONSOLES && vc_cons[i].d; i++) { ++ vc_cons[i].d->vc_decor.state = vc_cons[i].d->vc_decor.twidth = ++ vc_cons[i].d->vc_decor.theight = 0; ++ vc_cons[i].d->vc_decor.theme = NULL; ++ } ++ ++ return; ++} ++ ++int fbcon_decor_init(void) ++{ ++ int i; ++ ++ fbcon_decor_reset(); ++ ++ if (initialized) ++ return 0; ++ ++ i = misc_register(&fbcon_decor_dev); ++ if (i) { ++ printk(KERN_ERR "fbcondecor: failed to register device\n"); ++ return i; ++ } ++ ++ fbcon_decor_call_helper("init", 0); ++ initialized = 1; ++ return 0; ++} ++ ++int fbcon_decor_exit(void) ++{ ++ fbcon_decor_reset(); ++ return 0; ++} ++ ++EXPORT_SYMBOL(fbcon_decor_path); +diff --git a/drivers/video/console/fbcondecor.h b/drivers/video/console/fbcondecor.h +new file mode 100644 +index 0000000..3b3724b +--- /dev/null ++++ b/drivers/video/console/fbcondecor.h +@@ -0,0 +1,78 @@ ++/* ++ * linux/drivers/video/console/fbcondecor.h -- Framebuffer Console Decoration headers ++ * ++ * Copyright (C) 2004 Michal Januszewski ++ * ++ */ ++ ++#ifndef __FBCON_DECOR_H ++#define __FBCON_DECOR_H ++ ++#ifndef _LINUX_FB_H ++#include ++#endif ++ ++/* This is needed for vc_cons in fbcmap.c */ ++#include ++ ++struct fb_cursor; ++struct fb_info; ++struct vc_data; ++ ++#ifdef CONFIG_FB_CON_DECOR ++/* fbcondecor.c */ ++int fbcon_decor_init(void); ++int fbcon_decor_exit(void); ++int fbcon_decor_call_helper(char* cmd, unsigned short cons); ++int fbcon_decor_disable(struct vc_data *vc, unsigned char redraw); ++ ++/* cfbcondecor.c */ ++void fbcon_decor_putcs(struct vc_data *vc, struct fb_info *info, const unsigned short *s, int count, int yy, int xx); ++void fbcon_decor_cursor(struct fb_info *info, struct fb_cursor *cursor); ++void fbcon_decor_clear(struct vc_data *vc, struct fb_info *info, int sy, int sx, int height, int width); ++void fbcon_decor_clear_margins(struct vc_data *vc, struct fb_info *info, int bottom_only); ++void fbcon_decor_blank(struct vc_data *vc, struct fb_info *info, int blank); ++void fbcon_decor_bmove_redraw(struct vc_data *vc, struct fb_info *info, int y, int sx, int dx, int width); ++void fbcon_decor_copy(u8 *dst, u8 *src, int height, int width, int linebytes, int srclinesbytes, int bpp); ++void fbcon_decor_fix_pseudo_pal(struct fb_info *info, struct vc_data *vc); ++ ++/* vt.c */ ++void acquire_console_sem(void); ++void release_console_sem(void); ++void do_unblank_screen(int entering_gfx); ++ ++/* struct vc_data *y */ ++#define fbcon_decor_active_vc(y) (y->vc_decor.state && y->vc_decor.theme) ++ ++/* struct fb_info *x, struct vc_data *y */ ++#define fbcon_decor_active_nores(x,y) (x->bgdecor.data && fbcon_decor_active_vc(y)) ++ ++/* struct fb_info *x, struct vc_data *y */ ++#define fbcon_decor_active(x,y) (fbcon_decor_active_nores(x,y) && \ ++ x->bgdecor.width == x->var.xres && \ ++ x->bgdecor.height == x->var.yres && \ ++ x->bgdecor.depth == x->var.bits_per_pixel) ++ ++ ++#else /* CONFIG_FB_CON_DECOR */ ++ ++static inline void fbcon_decor_putcs(struct vc_data *vc, struct fb_info *info, const unsigned short *s, int count, int yy, int xx) {} ++static inline void fbcon_decor_putc(struct vc_data *vc, struct fb_info *info, int c, int ypos, int xpos) {} ++static inline void fbcon_decor_cursor(struct fb_info *info, struct fb_cursor *cursor) {} ++static inline void fbcon_decor_clear(struct vc_data *vc, struct fb_info *info, int sy, int sx, int height, int width) {} ++static inline void fbcon_decor_clear_margins(struct vc_data *vc, struct fb_info *info, int bottom_only) {} ++static inline void fbcon_decor_blank(struct vc_data *vc, struct fb_info *info, int blank) {} ++static inline void fbcon_decor_bmove_redraw(struct vc_data *vc, struct fb_info *info, int y, int sx, int dx, int width) {} ++static inline void fbcon_decor_fix_pseudo_pal(struct fb_info *info, struct vc_data *vc) {} ++static inline int fbcon_decor_call_helper(char* cmd, unsigned short cons) { return 0; } ++static inline int fbcon_decor_init(void) { return 0; } ++static inline int fbcon_decor_exit(void) { return 0; } ++static inline int fbcon_decor_disable(struct vc_data *vc, unsigned char redraw) { return 0; } ++ ++#define fbcon_decor_active_vc(y) (0) ++#define fbcon_decor_active_nores(x,y) (0) ++#define fbcon_decor_active(x,y) (0) ++ ++#endif /* CONFIG_FB_CON_DECOR */ ++ ++#endif /* __FBCON_DECOR_H */ +diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig +index e1f4727..2952e33 100644 +--- a/drivers/video/fbdev/Kconfig ++++ b/drivers/video/fbdev/Kconfig +@@ -1204,7 +1204,6 @@ config FB_MATROX + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT +- select FB_TILEBLITTING + select FB_MACMODES if PPC_PMAC + ---help--- + Say Y here if you have a Matrox Millennium, Matrox Millennium II, +diff --git a/drivers/video/fbdev/core/fbcmap.c b/drivers/video/fbdev/core/fbcmap.c +index f89245b..05e036c 100644 +--- a/drivers/video/fbdev/core/fbcmap.c ++++ b/drivers/video/fbdev/core/fbcmap.c +@@ -17,6 +17,8 @@ + #include + #include + ++#include "../../console/fbcondecor.h" ++ + static u16 red2[] __read_mostly = { + 0x0000, 0xaaaa + }; +@@ -249,14 +251,17 @@ int fb_set_cmap(struct fb_cmap *cmap, struct fb_info *info) + if (transp) + htransp = *transp++; + if (info->fbops->fb_setcolreg(start++, +- hred, hgreen, hblue, ++ hred, hgreen, hblue, + htransp, info)) + break; + } + } +- if (rc == 0) ++ if (rc == 0) { + fb_copy_cmap(cmap, &info->cmap); +- ++ if (fbcon_decor_active(info, vc_cons[fg_console].d) && ++ info->fix.visual == FB_VISUAL_DIRECTCOLOR) ++ fbcon_decor_fix_pseudo_pal(info, vc_cons[fg_console].d); ++ } + return rc; + } + +diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c +index b6d5008..d6703f2 100644 +--- a/drivers/video/fbdev/core/fbmem.c ++++ b/drivers/video/fbdev/core/fbmem.c +@@ -1250,15 +1250,6 @@ struct fb_fix_screeninfo32 { + u16 reserved[3]; + }; + +-struct fb_cmap32 { +- u32 start; +- u32 len; +- compat_caddr_t red; +- compat_caddr_t green; +- compat_caddr_t blue; +- compat_caddr_t transp; +-}; +- + static int fb_getput_cmap(struct fb_info *info, unsigned int cmd, + unsigned long arg) + { +diff --git a/include/linux/console_decor.h b/include/linux/console_decor.h +new file mode 100644 +index 0000000..04b8d80 +--- /dev/null ++++ b/include/linux/console_decor.h +@@ -0,0 +1,46 @@ ++#ifndef _LINUX_CONSOLE_DECOR_H_ ++#define _LINUX_CONSOLE_DECOR_H_ 1 ++ ++/* A structure used by the framebuffer console decorations (drivers/video/console/fbcondecor.c) */ ++struct vc_decor { ++ __u8 bg_color; /* The color that is to be treated as transparent */ ++ __u8 state; /* Current decor state: 0 = off, 1 = on */ ++ __u16 tx, ty; /* Top left corner coordinates of the text field */ ++ __u16 twidth, theight; /* Width and height of the text field */ ++ char* theme; ++}; ++ ++#ifdef __KERNEL__ ++#ifdef CONFIG_COMPAT ++#include ++ ++struct vc_decor32 { ++ __u8 bg_color; /* The color that is to be treated as transparent */ ++ __u8 state; /* Current decor state: 0 = off, 1 = on */ ++ __u16 tx, ty; /* Top left corner coordinates of the text field */ ++ __u16 twidth, theight; /* Width and height of the text field */ ++ compat_uptr_t theme; ++}; ++ ++#define vc_decor_from_compat(to, from) \ ++ (to).bg_color = (from).bg_color; \ ++ (to).state = (from).state; \ ++ (to).tx = (from).tx; \ ++ (to).ty = (from).ty; \ ++ (to).twidth = (from).twidth; \ ++ (to).theight = (from).theight; \ ++ (to).theme = compat_ptr((from).theme) ++ ++#define vc_decor_to_compat(to, from) \ ++ (to).bg_color = (from).bg_color; \ ++ (to).state = (from).state; \ ++ (to).tx = (from).tx; \ ++ (to).ty = (from).ty; \ ++ (to).twidth = (from).twidth; \ ++ (to).theight = (from).theight; \ ++ (to).theme = ptr_to_compat((from).theme) ++ ++#endif /* CONFIG_COMPAT */ ++#endif /* __KERNEL__ */ ++ ++#endif +diff --git a/include/linux/console_struct.h b/include/linux/console_struct.h +index 7f0c329..98f5d60 100644 +--- a/include/linux/console_struct.h ++++ b/include/linux/console_struct.h +@@ -19,6 +19,7 @@ + struct vt_struct; + + #define NPAR 16 ++#include + + struct vc_data { + struct tty_port port; /* Upper level data */ +@@ -107,6 +108,8 @@ struct vc_data { + unsigned long vc_uni_pagedir; + unsigned long *vc_uni_pagedir_loc; /* [!] Location of uni_pagedir variable for this console */ + bool vc_panic_force_write; /* when oops/panic this VC can accept forced output/blanking */ ++ ++ struct vc_decor vc_decor; + /* additional information is in vt_kern.h */ + }; + +diff --git a/include/linux/fb.h b/include/linux/fb.h +index fe6ac95..1e36b03 100644 +--- a/include/linux/fb.h ++++ b/include/linux/fb.h +@@ -219,6 +219,34 @@ struct fb_deferred_io { + }; + #endif + ++#ifdef __KERNEL__ ++#ifdef CONFIG_COMPAT ++struct fb_image32 { ++ __u32 dx; /* Where to place image */ ++ __u32 dy; ++ __u32 width; /* Size of image */ ++ __u32 height; ++ __u32 fg_color; /* Only used when a mono bitmap */ ++ __u32 bg_color; ++ __u8 depth; /* Depth of the image */ ++ const compat_uptr_t data; /* Pointer to image data */ ++ struct fb_cmap32 cmap; /* color map info */ ++}; ++ ++#define fb_image_from_compat(to, from) \ ++ (to).dx = (from).dx; \ ++ (to).dy = (from).dy; \ ++ (to).width = (from).width; \ ++ (to).height = (from).height; \ ++ (to).fg_color = (from).fg_color; \ ++ (to).bg_color = (from).bg_color; \ ++ (to).depth = (from).depth; \ ++ (to).data = compat_ptr((from).data); \ ++ fb_cmap_from_compat((to).cmap, (from).cmap) ++ ++#endif /* CONFIG_COMPAT */ ++#endif /* __KERNEL__ */ ++ + /* + * Frame buffer operations + * +@@ -489,6 +517,9 @@ struct fb_info { + #define FBINFO_STATE_SUSPENDED 1 + u32 state; /* Hardware state i.e suspend */ + void *fbcon_par; /* fbcon use-only private area */ ++ ++ struct fb_image bgdecor; ++ + /* From here on everything is device dependent */ + void *par; + /* we need the PCI or similar aperture base/size not +diff --git a/include/uapi/linux/fb.h b/include/uapi/linux/fb.h +index fb795c3..dc77a03 100644 +--- a/include/uapi/linux/fb.h ++++ b/include/uapi/linux/fb.h +@@ -8,6 +8,25 @@ + + #define FB_MAX 32 /* sufficient for now */ + ++struct fbcon_decor_iowrapper ++{ ++ unsigned short vc; /* Virtual console */ ++ unsigned char origin; /* Point of origin of the request */ ++ void *data; ++}; ++ ++#ifdef __KERNEL__ ++#ifdef CONFIG_COMPAT ++#include ++struct fbcon_decor_iowrapper32 ++{ ++ unsigned short vc; /* Virtual console */ ++ unsigned char origin; /* Point of origin of the request */ ++ compat_uptr_t data; ++}; ++#endif /* CONFIG_COMPAT */ ++#endif /* __KERNEL__ */ ++ + /* ioctls + 0x46 is 'F' */ + #define FBIOGET_VSCREENINFO 0x4600 +@@ -35,6 +54,25 @@ + #define FBIOGET_DISPINFO 0x4618 + #define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32) + ++#define FBIOCONDECOR_SETCFG _IOWR('F', 0x19, struct fbcon_decor_iowrapper) ++#define FBIOCONDECOR_GETCFG _IOR('F', 0x1A, struct fbcon_decor_iowrapper) ++#define FBIOCONDECOR_SETSTATE _IOWR('F', 0x1B, struct fbcon_decor_iowrapper) ++#define FBIOCONDECOR_GETSTATE _IOR('F', 0x1C, struct fbcon_decor_iowrapper) ++#define FBIOCONDECOR_SETPIC _IOWR('F', 0x1D, struct fbcon_decor_iowrapper) ++#ifdef __KERNEL__ ++#ifdef CONFIG_COMPAT ++#define FBIOCONDECOR_SETCFG32 _IOWR('F', 0x19, struct fbcon_decor_iowrapper32) ++#define FBIOCONDECOR_GETCFG32 _IOR('F', 0x1A, struct fbcon_decor_iowrapper32) ++#define FBIOCONDECOR_SETSTATE32 _IOWR('F', 0x1B, struct fbcon_decor_iowrapper32) ++#define FBIOCONDECOR_GETSTATE32 _IOR('F', 0x1C, struct fbcon_decor_iowrapper32) ++#define FBIOCONDECOR_SETPIC32 _IOWR('F', 0x1D, struct fbcon_decor_iowrapper32) ++#endif /* CONFIG_COMPAT */ ++#endif /* __KERNEL__ */ ++ ++#define FBCON_DECOR_THEME_LEN 128 /* Maximum lenght of a theme name */ ++#define FBCON_DECOR_IO_ORIG_KERNEL 0 /* Kernel ioctl origin */ ++#define FBCON_DECOR_IO_ORIG_USER 1 /* User ioctl origin */ ++ + #define FB_TYPE_PACKED_PIXELS 0 /* Packed Pixels */ + #define FB_TYPE_PLANES 1 /* Non interleaved planes */ + #define FB_TYPE_INTERLEAVED_PLANES 2 /* Interleaved planes */ +@@ -277,6 +315,29 @@ struct fb_var_screeninfo { + __u32 reserved[4]; /* Reserved for future compatibility */ + }; + ++#ifdef __KERNEL__ ++#ifdef CONFIG_COMPAT ++struct fb_cmap32 { ++ __u32 start; ++ __u32 len; /* Number of entries */ ++ compat_uptr_t red; /* Red values */ ++ compat_uptr_t green; ++ compat_uptr_t blue; ++ compat_uptr_t transp; /* transparency, can be NULL */ ++}; ++ ++#define fb_cmap_from_compat(to, from) \ ++ (to).start = (from).start; \ ++ (to).len = (from).len; \ ++ (to).red = compat_ptr((from).red); \ ++ (to).green = compat_ptr((from).green); \ ++ (to).blue = compat_ptr((from).blue); \ ++ (to).transp = compat_ptr((from).transp) ++ ++#endif /* CONFIG_COMPAT */ ++#endif /* __KERNEL__ */ ++ ++ + struct fb_cmap { + __u32 start; /* First entry */ + __u32 len; /* Number of entries */ +diff --git a/kernel/sysctl.c b/kernel/sysctl.c +index 74f5b58..6386ab0 100644 +--- a/kernel/sysctl.c ++++ b/kernel/sysctl.c +@@ -146,6 +146,10 @@ static const int cap_last_cap = CAP_LAST_CAP; + static unsigned long hung_task_timeout_max = (LONG_MAX/HZ); + #endif + ++#ifdef CONFIG_FB_CON_DECOR ++extern char fbcon_decor_path[]; ++#endif ++ + #ifdef CONFIG_INOTIFY_USER + #include + #endif +@@ -255,6 +259,15 @@ static struct ctl_table sysctl_base_table[] = { + .mode = 0555, + .child = dev_table, + }, ++#ifdef CONFIG_FB_CON_DECOR ++ { ++ .procname = "fbcondecor", ++ .data = &fbcon_decor_path, ++ .maxlen = KMOD_PATH_LEN, ++ .mode = 0644, ++ .proc_handler = &proc_dostring, ++ }, ++#endif + { } + }; + diff --git a/kernel/tools/cpupowertools/files/patches/gentoo/4567_distro-Gentoo-Kconfig.patch b/kernel/tools/cpupowertools/files/patches/gentoo/4567_distro-Gentoo-Kconfig.patch new file mode 100644 index 00000000..c7af596c --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/gentoo/4567_distro-Gentoo-Kconfig.patch @@ -0,0 +1,143 @@ +--- a/Kconfig ++++ b/Kconfig +@@ -8,4 +8,6 @@ config SRCARCH + string + option env="SRCARCH" + ++source "distro/Kconfig" ++ + source "arch/$SRCARCH/Kconfig" +--- /dev/null ++++ b/distro/Kconfig +@@ -0,0 +1,131 @@ ++menu "Gentoo Linux" ++ ++config GENTOO_LINUX ++ bool "Gentoo Linux support" ++ ++ default y ++ ++ help ++ In order to boot Gentoo Linux a minimal set of config settings needs to ++ be enabled in the kernel; to avoid the users from having to enable them ++ manually as part of a Gentoo Linux installation or a new clean config, ++ we enable these config settings by default for convenience. ++ ++ See the settings that become available for more details and fine-tuning. ++ ++config GENTOO_LINUX_UDEV ++ bool "Linux dynamic and persistent device naming (userspace devfs) support" ++ ++ depends on GENTOO_LINUX ++ default y if GENTOO_LINUX ++ ++ select DEVTMPFS ++ select TMPFS ++ ++ select MMU ++ select SHMEM ++ ++ help ++ In order to boot Gentoo Linux a minimal set of config settings needs to ++ be enabled in the kernel; to avoid the users from having to enable them ++ manually as part of a Gentoo Linux installation or a new clean config, ++ we enable these config settings by default for convenience. ++ ++ Currently this only selects TMPFS, DEVTMPFS and their dependencies. ++ TMPFS is enabled to maintain a tmpfs file system at /dev/shm, /run and ++ /sys/fs/cgroup; DEVTMPFS to maintain a devtmpfs file system at /dev. ++ ++ Some of these are critical files that need to be available early in the ++ boot process; if not available, it causes sysfs and udev to malfunction. ++ ++ To ensure Gentoo Linux boots, it is best to leave this setting enabled; ++ if you run a custom setup, you could consider whether to disable this. ++ ++config GENTOO_LINUX_PORTAGE ++ bool "Select options required by Portage features" ++ ++ depends on GENTOO_LINUX ++ default y if GENTOO_LINUX ++ ++ select CGROUPS ++ select NAMESPACES ++ select IPC_NS ++ select NET_NS ++ ++ help ++ This enables options required by various Portage FEATURES. ++ Currently this selects: ++ ++ CGROUPS (required for FEATURES=cgroup) ++ IPC_NS (required for FEATURES=ipc-sandbox) ++ NET_NS (required for FEATURES=network-sandbox) ++ ++ It is highly recommended that you leave this enabled as these FEATURES ++ are, or will soon be, enabled by default. ++ ++menu "Support for init systems, system and service managers" ++ visible if GENTOO_LINUX ++ ++config GENTOO_LINUX_INIT_SCRIPT ++ bool "OpenRC, runit and other script based systems and managers" ++ ++ default y if GENTOO_LINUX ++ ++ depends on GENTOO_LINUX ++ ++ select BINFMT_SCRIPT ++ ++ help ++ The init system is the first thing that loads after the kernel booted. ++ ++ These config settings allow you to select which init systems to support; ++ instead of having to select all the individual settings all over the ++ place, these settings allows you to select all the settings at once. ++ ++ This particular setting enables all the known requirements for OpenRC, ++ runit and similar script based systems and managers. ++ ++ If you are unsure about this, it is best to leave this setting enabled. ++ ++config GENTOO_LINUX_INIT_SYSTEMD ++ bool "systemd" ++ ++ default n ++ ++ depends on GENTOO_LINUX && GENTOO_LINUX_UDEV ++ ++ select AUTOFS4_FS ++ select BLK_DEV_BSG ++ select CGROUPS ++ select DEVPTS_MULTIPLE_INSTANCES ++ select EPOLL ++ select FANOTIFY ++ select FHANDLE ++ select INOTIFY_USER ++ select NET ++ select NET_NS ++ select PROC_FS ++ select SIGNALFD ++ select SYSFS ++ select TIMERFD ++ ++ select ANON_INODES ++ select BLOCK ++ select EVENTFD ++ select FSNOTIFY ++ select INET ++ select NLATTR ++ ++ help ++ The init system is the first thing that loads after the kernel booted. ++ ++ These config settings allow you to select which init systems to support; ++ instead of having to select all the individual settings all over the ++ place, these settings allows you to select all the settings at once. ++ ++ This particular setting enables all the known requirements for systemd; ++ it also enables suggested optional settings, as the package suggests to. ++ ++endmenu ++ ++endmenu diff --git a/kernel/tools/cpupowertools/files/patches/gentoo/5001_block-cgroups-kconfig-build-bits-for-BFQ-v7r7-3.19.patch b/kernel/tools/cpupowertools/files/patches/gentoo/5001_block-cgroups-kconfig-build-bits-for-BFQ-v7r7-3.19.patch new file mode 100644 index 00000000..b36d572c --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/gentoo/5001_block-cgroups-kconfig-build-bits-for-BFQ-v7r7-3.19.patch @@ -0,0 +1,104 @@ +From a828d56aebc0735676be23734cccf31e279c0d1b Mon Sep 17 00:00:00 2001 +From: Paolo Valente +Date: Mon, 8 Dec 2014 16:04:25 +0100 +Subject: [PATCH 1/3] block: cgroups, kconfig, build bits for BFQ-v7r7-3.19 + +Update Kconfig.iosched and do the related Makefile changes to include +kernel configuration options for BFQ. Also add the bfqio controller +to the cgroups subsystem. + +Signed-off-by: Paolo Valente +Signed-off-by: Arianna Avanzini +--- + block/Kconfig.iosched | 32 ++++++++++++++++++++++++++++++++ + block/Makefile | 1 + + include/linux/cgroup_subsys.h | 4 ++++ + 3 files changed, 37 insertions(+) + +diff --git a/block/Kconfig.iosched b/block/Kconfig.iosched +index 421bef9..0ee5f0f 100644 +--- a/block/Kconfig.iosched ++++ b/block/Kconfig.iosched +@@ -39,6 +39,27 @@ config CFQ_GROUP_IOSCHED + ---help--- + Enable group IO scheduling in CFQ. + ++config IOSCHED_BFQ ++ tristate "BFQ I/O scheduler" ++ default n ++ ---help--- ++ The BFQ I/O scheduler tries to distribute bandwidth among ++ all processes according to their weights. ++ It aims at distributing the bandwidth as desired, independently of ++ the disk parameters and with any workload. It also tries to ++ guarantee low latency to interactive and soft real-time ++ applications. If compiled built-in (saying Y here), BFQ can ++ be configured to support hierarchical scheduling. ++ ++config CGROUP_BFQIO ++ bool "BFQ hierarchical scheduling support" ++ depends on CGROUPS && IOSCHED_BFQ=y ++ default n ++ ---help--- ++ Enable hierarchical scheduling in BFQ, using the cgroups ++ filesystem interface. The name of the subsystem will be ++ bfqio. ++ + choice + prompt "Default I/O scheduler" + default DEFAULT_CFQ +@@ -52,6 +73,16 @@ choice + config DEFAULT_CFQ + bool "CFQ" if IOSCHED_CFQ=y + ++ config DEFAULT_BFQ ++ bool "BFQ" if IOSCHED_BFQ=y ++ help ++ Selects BFQ as the default I/O scheduler which will be ++ used by default for all block devices. ++ The BFQ I/O scheduler aims at distributing the bandwidth ++ as desired, independently of the disk parameters and with ++ any workload. It also tries to guarantee low latency to ++ interactive and soft real-time applications. ++ + config DEFAULT_NOOP + bool "No-op" + +@@ -61,6 +92,7 @@ config DEFAULT_IOSCHED + string + default "deadline" if DEFAULT_DEADLINE + default "cfq" if DEFAULT_CFQ ++ default "bfq" if DEFAULT_BFQ + default "noop" if DEFAULT_NOOP + + endmenu +diff --git a/block/Makefile b/block/Makefile +index 00ecc97..1ed86d5 100644 +--- a/block/Makefile ++++ b/block/Makefile +@@ -18,6 +18,7 @@ obj-$(CONFIG_BLK_DEV_THROTTLING) += blk-throttle.o + obj-$(CONFIG_IOSCHED_NOOP) += noop-iosched.o + obj-$(CONFIG_IOSCHED_DEADLINE) += deadline-iosched.o + obj-$(CONFIG_IOSCHED_CFQ) += cfq-iosched.o ++obj-$(CONFIG_IOSCHED_BFQ) += bfq-iosched.o + + obj-$(CONFIG_BLOCK_COMPAT) += compat_ioctl.o + obj-$(CONFIG_BLK_CMDLINE_PARSER) += cmdline-parser.o +diff --git a/include/linux/cgroup_subsys.h b/include/linux/cgroup_subsys.h +index 98c4f9b..13b010d 100644 +--- a/include/linux/cgroup_subsys.h ++++ b/include/linux/cgroup_subsys.h +@@ -35,6 +35,10 @@ SUBSYS(net_cls) + SUBSYS(blkio) + #endif + ++#if IS_ENABLED(CONFIG_CGROUP_BFQIO) ++SUBSYS(bfqio) ++#endif ++ + #if IS_ENABLED(CONFIG_CGROUP_PERF) + SUBSYS(perf_event) + #endif +-- +2.3.0 + diff --git a/kernel/tools/cpupowertools/files/patches/gentoo/5002_block-introduce-the-BFQ-v7r7-I-O-sched-for-3.19.patch b/kernel/tools/cpupowertools/files/patches/gentoo/5002_block-introduce-the-BFQ-v7r7-I-O-sched-for-3.19.patch new file mode 100644 index 00000000..fb96ff28 --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/gentoo/5002_block-introduce-the-BFQ-v7r7-I-O-sched-for-3.19.patch @@ -0,0 +1,6966 @@ +From 5bfaaa91a51940efaccb66bc5cd562ba3b9d4053 Mon Sep 17 00:00:00 2001 +From: Paolo Valente +Date: Thu, 9 May 2013 19:10:02 +0200 +Subject: [PATCH 2/3] block: introduce the BFQ-v7r7 I/O sched for 3.19 + +Add the BFQ-v7r7 I/O scheduler to 3.19. +The general structure is borrowed from CFQ, as much of the code for +handling I/O contexts. Over time, several useful features have been +ported from CFQ as well (details in the changelog in README.BFQ). A +(bfq_)queue is associated to each task doing I/O on a device, and each +time a scheduling decision has to be made a queue is selected and served +until it expires. + + - Slices are given in the service domain: tasks are assigned + budgets, measured in number of sectors. Once got the disk, a task + must however consume its assigned budget within a configurable + maximum time (by default, the maximum possible value of the + budgets is automatically computed to comply with this timeout). + This allows the desired latency vs "throughput boosting" tradeoff + to be set. + + - Budgets are scheduled according to a variant of WF2Q+, implemented + using an augmented rb-tree to take eligibility into account while + preserving an O(log N) overall complexity. + + - A low-latency tunable is provided; if enabled, both interactive + and soft real-time applications are guaranteed a very low latency. + + - Latency guarantees are preserved also in the presence of NCQ. + + - Also with flash-based devices, a high throughput is achieved + while still preserving latency guarantees. + + - BFQ features Early Queue Merge (EQM), a sort of fusion of the + cooperating-queue-merging and the preemption mechanisms present + in CFQ. EQM is in fact a unified mechanism that tries to get a + sequential read pattern, and hence a high throughput, with any + set of processes performing interleaved I/O over a contiguous + sequence of sectors. + + - BFQ supports full hierarchical scheduling, exporting a cgroups + interface. Since each node has a full scheduler, each group can + be assigned its own weight. + + - If the cgroups interface is not used, only I/O priorities can be + assigned to processes, with ioprio values mapped to weights + with the relation weight = IOPRIO_BE_NR - ioprio. + + - ioprio classes are served in strict priority order, i.e., lower + priority queues are not served as long as there are higher + priority queues. Among queues in the same class the bandwidth is + distributed in proportion to the weight of each queue. A very + thin extra bandwidth is however guaranteed to the Idle class, to + prevent it from starving. + +Signed-off-by: Paolo Valente +Signed-off-by: Arianna Avanzini +--- + block/bfq-cgroup.c | 936 ++++++++++++ + block/bfq-ioc.c | 36 + + block/bfq-iosched.c | 3902 +++++++++++++++++++++++++++++++++++++++++++++++++++ + block/bfq-sched.c | 1214 ++++++++++++++++ + block/bfq.h | 775 ++++++++++ + 5 files changed, 6863 insertions(+) + create mode 100644 block/bfq-cgroup.c + create mode 100644 block/bfq-ioc.c + create mode 100644 block/bfq-iosched.c + create mode 100644 block/bfq-sched.c + create mode 100644 block/bfq.h + +diff --git a/block/bfq-cgroup.c b/block/bfq-cgroup.c +new file mode 100644 +index 0000000..11e2f1d +--- /dev/null ++++ b/block/bfq-cgroup.c +@@ -0,0 +1,936 @@ ++/* ++ * BFQ: CGROUPS support. ++ * ++ * Based on ideas and code from CFQ: ++ * Copyright (C) 2003 Jens Axboe ++ * ++ * Copyright (C) 2008 Fabio Checconi ++ * Paolo Valente ++ * ++ * Copyright (C) 2010 Paolo Valente ++ * ++ * Licensed under the GPL-2 as detailed in the accompanying COPYING.BFQ ++ * file. ++ */ ++ ++#ifdef CONFIG_CGROUP_BFQIO ++ ++static DEFINE_MUTEX(bfqio_mutex); ++ ++static bool bfqio_is_removed(struct bfqio_cgroup *bgrp) ++{ ++ return bgrp ? !bgrp->online : false; ++} ++ ++static struct bfqio_cgroup bfqio_root_cgroup = { ++ .weight = BFQ_DEFAULT_GRP_WEIGHT, ++ .ioprio = BFQ_DEFAULT_GRP_IOPRIO, ++ .ioprio_class = BFQ_DEFAULT_GRP_CLASS, ++}; ++ ++static inline void bfq_init_entity(struct bfq_entity *entity, ++ struct bfq_group *bfqg) ++{ ++ entity->weight = entity->new_weight; ++ entity->orig_weight = entity->new_weight; ++ entity->ioprio = entity->new_ioprio; ++ entity->ioprio_class = entity->new_ioprio_class; ++ entity->parent = bfqg->my_entity; ++ entity->sched_data = &bfqg->sched_data; ++} ++ ++static struct bfqio_cgroup *css_to_bfqio(struct cgroup_subsys_state *css) ++{ ++ return css ? container_of(css, struct bfqio_cgroup, css) : NULL; ++} ++ ++/* ++ * Search the bfq_group for bfqd into the hash table (by now only a list) ++ * of bgrp. Must be called under rcu_read_lock(). ++ */ ++static struct bfq_group *bfqio_lookup_group(struct bfqio_cgroup *bgrp, ++ struct bfq_data *bfqd) ++{ ++ struct bfq_group *bfqg; ++ void *key; ++ ++ hlist_for_each_entry_rcu(bfqg, &bgrp->group_data, group_node) { ++ key = rcu_dereference(bfqg->bfqd); ++ if (key == bfqd) ++ return bfqg; ++ } ++ ++ return NULL; ++} ++ ++static inline void bfq_group_init_entity(struct bfqio_cgroup *bgrp, ++ struct bfq_group *bfqg) ++{ ++ struct bfq_entity *entity = &bfqg->entity; ++ ++ /* ++ * If the weight of the entity has never been set via the sysfs ++ * interface, then bgrp->weight == 0. In this case we initialize ++ * the weight from the current ioprio value. Otherwise, the group ++ * weight, if set, has priority over the ioprio value. ++ */ ++ if (bgrp->weight == 0) { ++ entity->new_weight = bfq_ioprio_to_weight(bgrp->ioprio); ++ entity->new_ioprio = bgrp->ioprio; ++ } else { ++ if (bgrp->weight < BFQ_MIN_WEIGHT || ++ bgrp->weight > BFQ_MAX_WEIGHT) { ++ printk(KERN_CRIT "bfq_group_init_entity: " ++ "bgrp->weight %d\n", bgrp->weight); ++ BUG(); ++ } ++ entity->new_weight = bgrp->weight; ++ entity->new_ioprio = bfq_weight_to_ioprio(bgrp->weight); ++ } ++ entity->orig_weight = entity->weight = entity->new_weight; ++ entity->ioprio = entity->new_ioprio; ++ entity->ioprio_class = entity->new_ioprio_class = bgrp->ioprio_class; ++ entity->my_sched_data = &bfqg->sched_data; ++ bfqg->active_entities = 0; ++} ++ ++static inline void bfq_group_set_parent(struct bfq_group *bfqg, ++ struct bfq_group *parent) ++{ ++ struct bfq_entity *entity; ++ ++ BUG_ON(parent == NULL); ++ BUG_ON(bfqg == NULL); ++ ++ entity = &bfqg->entity; ++ entity->parent = parent->my_entity; ++ entity->sched_data = &parent->sched_data; ++} ++ ++/** ++ * bfq_group_chain_alloc - allocate a chain of groups. ++ * @bfqd: queue descriptor. ++ * @css: the leaf cgroup_subsys_state this chain starts from. ++ * ++ * Allocate a chain of groups starting from the one belonging to ++ * @cgroup up to the root cgroup. Stop if a cgroup on the chain ++ * to the root has already an allocated group on @bfqd. ++ */ ++static struct bfq_group *bfq_group_chain_alloc(struct bfq_data *bfqd, ++ struct cgroup_subsys_state *css) ++{ ++ struct bfqio_cgroup *bgrp; ++ struct bfq_group *bfqg, *prev = NULL, *leaf = NULL; ++ ++ for (; css != NULL; css = css->parent) { ++ bgrp = css_to_bfqio(css); ++ ++ bfqg = bfqio_lookup_group(bgrp, bfqd); ++ if (bfqg != NULL) { ++ /* ++ * All the cgroups in the path from there to the ++ * root must have a bfq_group for bfqd, so we don't ++ * need any more allocations. ++ */ ++ break; ++ } ++ ++ bfqg = kzalloc(sizeof(*bfqg), GFP_ATOMIC); ++ if (bfqg == NULL) ++ goto cleanup; ++ ++ bfq_group_init_entity(bgrp, bfqg); ++ bfqg->my_entity = &bfqg->entity; ++ ++ if (leaf == NULL) { ++ leaf = bfqg; ++ prev = leaf; ++ } else { ++ bfq_group_set_parent(prev, bfqg); ++ /* ++ * Build a list of allocated nodes using the bfqd ++ * filed, that is still unused and will be ++ * initialized only after the node will be ++ * connected. ++ */ ++ prev->bfqd = bfqg; ++ prev = bfqg; ++ } ++ } ++ ++ return leaf; ++ ++cleanup: ++ while (leaf != NULL) { ++ prev = leaf; ++ leaf = leaf->bfqd; ++ kfree(prev); ++ } ++ ++ return NULL; ++} ++ ++/** ++ * bfq_group_chain_link - link an allocated group chain to a cgroup ++ * hierarchy. ++ * @bfqd: the queue descriptor. ++ * @css: the leaf cgroup_subsys_state to start from. ++ * @leaf: the leaf group (to be associated to @cgroup). ++ * ++ * Try to link a chain of groups to a cgroup hierarchy, connecting the ++ * nodes bottom-up, so we can be sure that when we find a cgroup in the ++ * hierarchy that already as a group associated to @bfqd all the nodes ++ * in the path to the root cgroup have one too. ++ * ++ * On locking: the queue lock protects the hierarchy (there is a hierarchy ++ * per device) while the bfqio_cgroup lock protects the list of groups ++ * belonging to the same cgroup. ++ */ ++static void bfq_group_chain_link(struct bfq_data *bfqd, ++ struct cgroup_subsys_state *css, ++ struct bfq_group *leaf) ++{ ++ struct bfqio_cgroup *bgrp; ++ struct bfq_group *bfqg, *next, *prev = NULL; ++ unsigned long flags; ++ ++ assert_spin_locked(bfqd->queue->queue_lock); ++ ++ for (; css != NULL && leaf != NULL; css = css->parent) { ++ bgrp = css_to_bfqio(css); ++ next = leaf->bfqd; ++ ++ bfqg = bfqio_lookup_group(bgrp, bfqd); ++ BUG_ON(bfqg != NULL); ++ ++ spin_lock_irqsave(&bgrp->lock, flags); ++ ++ rcu_assign_pointer(leaf->bfqd, bfqd); ++ hlist_add_head_rcu(&leaf->group_node, &bgrp->group_data); ++ hlist_add_head(&leaf->bfqd_node, &bfqd->group_list); ++ ++ spin_unlock_irqrestore(&bgrp->lock, flags); ++ ++ prev = leaf; ++ leaf = next; ++ } ++ ++ BUG_ON(css == NULL && leaf != NULL); ++ if (css != NULL && prev != NULL) { ++ bgrp = css_to_bfqio(css); ++ bfqg = bfqio_lookup_group(bgrp, bfqd); ++ bfq_group_set_parent(prev, bfqg); ++ } ++} ++ ++/** ++ * bfq_find_alloc_group - return the group associated to @bfqd in @cgroup. ++ * @bfqd: queue descriptor. ++ * @cgroup: cgroup being searched for. ++ * ++ * Return a group associated to @bfqd in @cgroup, allocating one if ++ * necessary. When a group is returned all the cgroups in the path ++ * to the root have a group associated to @bfqd. ++ * ++ * If the allocation fails, return the root group: this breaks guarantees ++ * but is a safe fallback. If this loss becomes a problem it can be ++ * mitigated using the equivalent weight (given by the product of the ++ * weights of the groups in the path from @group to the root) in the ++ * root scheduler. ++ * ++ * We allocate all the missing nodes in the path from the leaf cgroup ++ * to the root and we connect the nodes only after all the allocations ++ * have been successful. ++ */ ++static struct bfq_group *bfq_find_alloc_group(struct bfq_data *bfqd, ++ struct cgroup_subsys_state *css) ++{ ++ struct bfqio_cgroup *bgrp = css_to_bfqio(css); ++ struct bfq_group *bfqg; ++ ++ bfqg = bfqio_lookup_group(bgrp, bfqd); ++ if (bfqg != NULL) ++ return bfqg; ++ ++ bfqg = bfq_group_chain_alloc(bfqd, css); ++ if (bfqg != NULL) ++ bfq_group_chain_link(bfqd, css, bfqg); ++ else ++ bfqg = bfqd->root_group; ++ ++ return bfqg; ++} ++ ++/** ++ * bfq_bfqq_move - migrate @bfqq to @bfqg. ++ * @bfqd: queue descriptor. ++ * @bfqq: the queue to move. ++ * @entity: @bfqq's entity. ++ * @bfqg: the group to move to. ++ * ++ * Move @bfqq to @bfqg, deactivating it from its old group and reactivating ++ * it on the new one. Avoid putting the entity on the old group idle tree. ++ * ++ * Must be called under the queue lock; the cgroup owning @bfqg must ++ * not disappear (by now this just means that we are called under ++ * rcu_read_lock()). ++ */ ++static void bfq_bfqq_move(struct bfq_data *bfqd, struct bfq_queue *bfqq, ++ struct bfq_entity *entity, struct bfq_group *bfqg) ++{ ++ int busy, resume; ++ ++ busy = bfq_bfqq_busy(bfqq); ++ resume = !RB_EMPTY_ROOT(&bfqq->sort_list); ++ ++ BUG_ON(resume && !entity->on_st); ++ BUG_ON(busy && !resume && entity->on_st && ++ bfqq != bfqd->in_service_queue); ++ ++ if (busy) { ++ BUG_ON(atomic_read(&bfqq->ref) < 2); ++ ++ if (!resume) ++ bfq_del_bfqq_busy(bfqd, bfqq, 0); ++ else ++ bfq_deactivate_bfqq(bfqd, bfqq, 0); ++ } else if (entity->on_st) ++ bfq_put_idle_entity(bfq_entity_service_tree(entity), entity); ++ ++ /* ++ * Here we use a reference to bfqg. We don't need a refcounter ++ * as the cgroup reference will not be dropped, so that its ++ * destroy() callback will not be invoked. ++ */ ++ entity->parent = bfqg->my_entity; ++ entity->sched_data = &bfqg->sched_data; ++ ++ if (busy && resume) ++ bfq_activate_bfqq(bfqd, bfqq); ++ ++ if (bfqd->in_service_queue == NULL && !bfqd->rq_in_driver) ++ bfq_schedule_dispatch(bfqd); ++} ++ ++/** ++ * __bfq_bic_change_cgroup - move @bic to @cgroup. ++ * @bfqd: the queue descriptor. ++ * @bic: the bic to move. ++ * @cgroup: the cgroup to move to. ++ * ++ * Move bic to cgroup, assuming that bfqd->queue is locked; the caller ++ * has to make sure that the reference to cgroup is valid across the call. ++ * ++ * NOTE: an alternative approach might have been to store the current ++ * cgroup in bfqq and getting a reference to it, reducing the lookup ++ * time here, at the price of slightly more complex code. ++ */ ++static struct bfq_group *__bfq_bic_change_cgroup(struct bfq_data *bfqd, ++ struct bfq_io_cq *bic, ++ struct cgroup_subsys_state *css) ++{ ++ struct bfq_queue *async_bfqq = bic_to_bfqq(bic, 0); ++ struct bfq_queue *sync_bfqq = bic_to_bfqq(bic, 1); ++ struct bfq_entity *entity; ++ struct bfq_group *bfqg; ++ struct bfqio_cgroup *bgrp; ++ ++ bgrp = css_to_bfqio(css); ++ ++ bfqg = bfq_find_alloc_group(bfqd, css); ++ if (async_bfqq != NULL) { ++ entity = &async_bfqq->entity; ++ ++ if (entity->sched_data != &bfqg->sched_data) { ++ bic_set_bfqq(bic, NULL, 0); ++ bfq_log_bfqq(bfqd, async_bfqq, ++ "bic_change_group: %p %d", ++ async_bfqq, atomic_read(&async_bfqq->ref)); ++ bfq_put_queue(async_bfqq); ++ } ++ } ++ ++ if (sync_bfqq != NULL) { ++ entity = &sync_bfqq->entity; ++ if (entity->sched_data != &bfqg->sched_data) ++ bfq_bfqq_move(bfqd, sync_bfqq, entity, bfqg); ++ } ++ ++ return bfqg; ++} ++ ++/** ++ * bfq_bic_change_cgroup - move @bic to @cgroup. ++ * @bic: the bic being migrated. ++ * @cgroup: the destination cgroup. ++ * ++ * When the task owning @bic is moved to @cgroup, @bic is immediately ++ * moved into its new parent group. ++ */ ++static void bfq_bic_change_cgroup(struct bfq_io_cq *bic, ++ struct cgroup_subsys_state *css) ++{ ++ struct bfq_data *bfqd; ++ unsigned long uninitialized_var(flags); ++ ++ bfqd = bfq_get_bfqd_locked(&(bic->icq.q->elevator->elevator_data), ++ &flags); ++ if (bfqd != NULL) { ++ __bfq_bic_change_cgroup(bfqd, bic, css); ++ bfq_put_bfqd_unlock(bfqd, &flags); ++ } ++} ++ ++/** ++ * bfq_bic_update_cgroup - update the cgroup of @bic. ++ * @bic: the @bic to update. ++ * ++ * Make sure that @bic is enqueued in the cgroup of the current task. ++ * We need this in addition to moving bics during the cgroup attach ++ * phase because the task owning @bic could be at its first disk ++ * access or we may end up in the root cgroup as the result of a ++ * memory allocation failure and here we try to move to the right ++ * group. ++ * ++ * Must be called under the queue lock. It is safe to use the returned ++ * value even after the rcu_read_unlock() as the migration/destruction ++ * paths act under the queue lock too. IOW it is impossible to race with ++ * group migration/destruction and end up with an invalid group as: ++ * a) here cgroup has not yet been destroyed, nor its destroy callback ++ * has started execution, as current holds a reference to it, ++ * b) if it is destroyed after rcu_read_unlock() [after current is ++ * migrated to a different cgroup] its attach() callback will have ++ * taken care of remove all the references to the old cgroup data. ++ */ ++static struct bfq_group *bfq_bic_update_cgroup(struct bfq_io_cq *bic) ++{ ++ struct bfq_data *bfqd = bic_to_bfqd(bic); ++ struct bfq_group *bfqg; ++ struct cgroup_subsys_state *css; ++ ++ BUG_ON(bfqd == NULL); ++ ++ rcu_read_lock(); ++ css = task_css(current, bfqio_cgrp_id); ++ bfqg = __bfq_bic_change_cgroup(bfqd, bic, css); ++ rcu_read_unlock(); ++ ++ return bfqg; ++} ++ ++/** ++ * bfq_flush_idle_tree - deactivate any entity on the idle tree of @st. ++ * @st: the service tree being flushed. ++ */ ++static inline void bfq_flush_idle_tree(struct bfq_service_tree *st) ++{ ++ struct bfq_entity *entity = st->first_idle; ++ ++ for (; entity != NULL; entity = st->first_idle) ++ __bfq_deactivate_entity(entity, 0); ++} ++ ++/** ++ * bfq_reparent_leaf_entity - move leaf entity to the root_group. ++ * @bfqd: the device data structure with the root group. ++ * @entity: the entity to move. ++ */ ++static inline void bfq_reparent_leaf_entity(struct bfq_data *bfqd, ++ struct bfq_entity *entity) ++{ ++ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); ++ ++ BUG_ON(bfqq == NULL); ++ bfq_bfqq_move(bfqd, bfqq, entity, bfqd->root_group); ++ return; ++} ++ ++/** ++ * bfq_reparent_active_entities - move to the root group all active ++ * entities. ++ * @bfqd: the device data structure with the root group. ++ * @bfqg: the group to move from. ++ * @st: the service tree with the entities. ++ * ++ * Needs queue_lock to be taken and reference to be valid over the call. ++ */ ++static inline void bfq_reparent_active_entities(struct bfq_data *bfqd, ++ struct bfq_group *bfqg, ++ struct bfq_service_tree *st) ++{ ++ struct rb_root *active = &st->active; ++ struct bfq_entity *entity = NULL; ++ ++ if (!RB_EMPTY_ROOT(&st->active)) ++ entity = bfq_entity_of(rb_first(active)); ++ ++ for (; entity != NULL; entity = bfq_entity_of(rb_first(active))) ++ bfq_reparent_leaf_entity(bfqd, entity); ++ ++ if (bfqg->sched_data.in_service_entity != NULL) ++ bfq_reparent_leaf_entity(bfqd, ++ bfqg->sched_data.in_service_entity); ++ ++ return; ++} ++ ++/** ++ * bfq_destroy_group - destroy @bfqg. ++ * @bgrp: the bfqio_cgroup containing @bfqg. ++ * @bfqg: the group being destroyed. ++ * ++ * Destroy @bfqg, making sure that it is not referenced from its parent. ++ */ ++static void bfq_destroy_group(struct bfqio_cgroup *bgrp, struct bfq_group *bfqg) ++{ ++ struct bfq_data *bfqd; ++ struct bfq_service_tree *st; ++ struct bfq_entity *entity = bfqg->my_entity; ++ unsigned long uninitialized_var(flags); ++ int i; ++ ++ hlist_del(&bfqg->group_node); ++ ++ /* ++ * Empty all service_trees belonging to this group before ++ * deactivating the group itself. ++ */ ++ for (i = 0; i < BFQ_IOPRIO_CLASSES; i++) { ++ st = bfqg->sched_data.service_tree + i; ++ ++ /* ++ * The idle tree may still contain bfq_queues belonging ++ * to exited task because they never migrated to a different ++ * cgroup from the one being destroyed now. No one else ++ * can access them so it's safe to act without any lock. ++ */ ++ bfq_flush_idle_tree(st); ++ ++ /* ++ * It may happen that some queues are still active ++ * (busy) upon group destruction (if the corresponding ++ * processes have been forced to terminate). We move ++ * all the leaf entities corresponding to these queues ++ * to the root_group. ++ * Also, it may happen that the group has an entity ++ * in service, which is disconnected from the active ++ * tree: it must be moved, too. ++ * There is no need to put the sync queues, as the ++ * scheduler has taken no reference. ++ */ ++ bfqd = bfq_get_bfqd_locked(&bfqg->bfqd, &flags); ++ if (bfqd != NULL) { ++ bfq_reparent_active_entities(bfqd, bfqg, st); ++ bfq_put_bfqd_unlock(bfqd, &flags); ++ } ++ BUG_ON(!RB_EMPTY_ROOT(&st->active)); ++ BUG_ON(!RB_EMPTY_ROOT(&st->idle)); ++ } ++ BUG_ON(bfqg->sched_data.next_in_service != NULL); ++ BUG_ON(bfqg->sched_data.in_service_entity != NULL); ++ ++ /* ++ * We may race with device destruction, take extra care when ++ * dereferencing bfqg->bfqd. ++ */ ++ bfqd = bfq_get_bfqd_locked(&bfqg->bfqd, &flags); ++ if (bfqd != NULL) { ++ hlist_del(&bfqg->bfqd_node); ++ __bfq_deactivate_entity(entity, 0); ++ bfq_put_async_queues(bfqd, bfqg); ++ bfq_put_bfqd_unlock(bfqd, &flags); ++ } ++ BUG_ON(entity->tree != NULL); ++ ++ /* ++ * No need to defer the kfree() to the end of the RCU grace ++ * period: we are called from the destroy() callback of our ++ * cgroup, so we can be sure that no one is a) still using ++ * this cgroup or b) doing lookups in it. ++ */ ++ kfree(bfqg); ++} ++ ++static void bfq_end_wr_async(struct bfq_data *bfqd) ++{ ++ struct hlist_node *tmp; ++ struct bfq_group *bfqg; ++ ++ hlist_for_each_entry_safe(bfqg, tmp, &bfqd->group_list, bfqd_node) ++ bfq_end_wr_async_queues(bfqd, bfqg); ++ bfq_end_wr_async_queues(bfqd, bfqd->root_group); ++} ++ ++/** ++ * bfq_disconnect_groups - disconnect @bfqd from all its groups. ++ * @bfqd: the device descriptor being exited. ++ * ++ * When the device exits we just make sure that no lookup can return ++ * the now unused group structures. They will be deallocated on cgroup ++ * destruction. ++ */ ++static void bfq_disconnect_groups(struct bfq_data *bfqd) ++{ ++ struct hlist_node *tmp; ++ struct bfq_group *bfqg; ++ ++ bfq_log(bfqd, "disconnect_groups beginning"); ++ hlist_for_each_entry_safe(bfqg, tmp, &bfqd->group_list, bfqd_node) { ++ hlist_del(&bfqg->bfqd_node); ++ ++ __bfq_deactivate_entity(bfqg->my_entity, 0); ++ ++ /* ++ * Don't remove from the group hash, just set an ++ * invalid key. No lookups can race with the ++ * assignment as bfqd is being destroyed; this ++ * implies also that new elements cannot be added ++ * to the list. ++ */ ++ rcu_assign_pointer(bfqg->bfqd, NULL); ++ ++ bfq_log(bfqd, "disconnect_groups: put async for group %p", ++ bfqg); ++ bfq_put_async_queues(bfqd, bfqg); ++ } ++} ++ ++static inline void bfq_free_root_group(struct bfq_data *bfqd) ++{ ++ struct bfqio_cgroup *bgrp = &bfqio_root_cgroup; ++ struct bfq_group *bfqg = bfqd->root_group; ++ ++ bfq_put_async_queues(bfqd, bfqg); ++ ++ spin_lock_irq(&bgrp->lock); ++ hlist_del_rcu(&bfqg->group_node); ++ spin_unlock_irq(&bgrp->lock); ++ ++ /* ++ * No need to synchronize_rcu() here: since the device is gone ++ * there cannot be any read-side access to its root_group. ++ */ ++ kfree(bfqg); ++} ++ ++static struct bfq_group *bfq_alloc_root_group(struct bfq_data *bfqd, int node) ++{ ++ struct bfq_group *bfqg; ++ struct bfqio_cgroup *bgrp; ++ int i; ++ ++ bfqg = kzalloc_node(sizeof(*bfqg), GFP_KERNEL, node); ++ if (bfqg == NULL) ++ return NULL; ++ ++ bfqg->entity.parent = NULL; ++ for (i = 0; i < BFQ_IOPRIO_CLASSES; i++) ++ bfqg->sched_data.service_tree[i] = BFQ_SERVICE_TREE_INIT; ++ ++ bgrp = &bfqio_root_cgroup; ++ spin_lock_irq(&bgrp->lock); ++ rcu_assign_pointer(bfqg->bfqd, bfqd); ++ hlist_add_head_rcu(&bfqg->group_node, &bgrp->group_data); ++ spin_unlock_irq(&bgrp->lock); ++ ++ return bfqg; ++} ++ ++#define SHOW_FUNCTION(__VAR) \ ++static u64 bfqio_cgroup_##__VAR##_read(struct cgroup_subsys_state *css, \ ++ struct cftype *cftype) \ ++{ \ ++ struct bfqio_cgroup *bgrp = css_to_bfqio(css); \ ++ u64 ret = -ENODEV; \ ++ \ ++ mutex_lock(&bfqio_mutex); \ ++ if (bfqio_is_removed(bgrp)) \ ++ goto out_unlock; \ ++ \ ++ spin_lock_irq(&bgrp->lock); \ ++ ret = bgrp->__VAR; \ ++ spin_unlock_irq(&bgrp->lock); \ ++ \ ++out_unlock: \ ++ mutex_unlock(&bfqio_mutex); \ ++ return ret; \ ++} ++ ++SHOW_FUNCTION(weight); ++SHOW_FUNCTION(ioprio); ++SHOW_FUNCTION(ioprio_class); ++#undef SHOW_FUNCTION ++ ++#define STORE_FUNCTION(__VAR, __MIN, __MAX) \ ++static int bfqio_cgroup_##__VAR##_write(struct cgroup_subsys_state *css,\ ++ struct cftype *cftype, \ ++ u64 val) \ ++{ \ ++ struct bfqio_cgroup *bgrp = css_to_bfqio(css); \ ++ struct bfq_group *bfqg; \ ++ int ret = -EINVAL; \ ++ \ ++ if (val < (__MIN) || val > (__MAX)) \ ++ return ret; \ ++ \ ++ ret = -ENODEV; \ ++ mutex_lock(&bfqio_mutex); \ ++ if (bfqio_is_removed(bgrp)) \ ++ goto out_unlock; \ ++ ret = 0; \ ++ \ ++ spin_lock_irq(&bgrp->lock); \ ++ bgrp->__VAR = (unsigned short)val; \ ++ hlist_for_each_entry(bfqg, &bgrp->group_data, group_node) { \ ++ /* \ ++ * Setting the ioprio_changed flag of the entity \ ++ * to 1 with new_##__VAR == ##__VAR would re-set \ ++ * the value of the weight to its ioprio mapping. \ ++ * Set the flag only if necessary. \ ++ */ \ ++ if ((unsigned short)val != bfqg->entity.new_##__VAR) { \ ++ bfqg->entity.new_##__VAR = (unsigned short)val; \ ++ /* \ ++ * Make sure that the above new value has been \ ++ * stored in bfqg->entity.new_##__VAR before \ ++ * setting the ioprio_changed flag. In fact, \ ++ * this flag may be read asynchronously (in \ ++ * critical sections protected by a different \ ++ * lock than that held here), and finding this \ ++ * flag set may cause the execution of the code \ ++ * for updating parameters whose value may \ ++ * depend also on bfqg->entity.new_##__VAR (in \ ++ * __bfq_entity_update_weight_prio). \ ++ * This barrier makes sure that the new value \ ++ * of bfqg->entity.new_##__VAR is correctly \ ++ * seen in that code. \ ++ */ \ ++ smp_wmb(); \ ++ bfqg->entity.ioprio_changed = 1; \ ++ } \ ++ } \ ++ spin_unlock_irq(&bgrp->lock); \ ++ \ ++out_unlock: \ ++ mutex_unlock(&bfqio_mutex); \ ++ return ret; \ ++} ++ ++STORE_FUNCTION(weight, BFQ_MIN_WEIGHT, BFQ_MAX_WEIGHT); ++STORE_FUNCTION(ioprio, 0, IOPRIO_BE_NR - 1); ++STORE_FUNCTION(ioprio_class, IOPRIO_CLASS_RT, IOPRIO_CLASS_IDLE); ++#undef STORE_FUNCTION ++ ++static struct cftype bfqio_files[] = { ++ { ++ .name = "weight", ++ .read_u64 = bfqio_cgroup_weight_read, ++ .write_u64 = bfqio_cgroup_weight_write, ++ }, ++ { ++ .name = "ioprio", ++ .read_u64 = bfqio_cgroup_ioprio_read, ++ .write_u64 = bfqio_cgroup_ioprio_write, ++ }, ++ { ++ .name = "ioprio_class", ++ .read_u64 = bfqio_cgroup_ioprio_class_read, ++ .write_u64 = bfqio_cgroup_ioprio_class_write, ++ }, ++ { }, /* terminate */ ++}; ++ ++static struct cgroup_subsys_state *bfqio_create(struct cgroup_subsys_state ++ *parent_css) ++{ ++ struct bfqio_cgroup *bgrp; ++ ++ if (parent_css != NULL) { ++ bgrp = kzalloc(sizeof(*bgrp), GFP_KERNEL); ++ if (bgrp == NULL) ++ return ERR_PTR(-ENOMEM); ++ } else ++ bgrp = &bfqio_root_cgroup; ++ ++ spin_lock_init(&bgrp->lock); ++ INIT_HLIST_HEAD(&bgrp->group_data); ++ bgrp->ioprio = BFQ_DEFAULT_GRP_IOPRIO; ++ bgrp->ioprio_class = BFQ_DEFAULT_GRP_CLASS; ++ ++ return &bgrp->css; ++} ++ ++/* ++ * We cannot support shared io contexts, as we have no means to support ++ * two tasks with the same ioc in two different groups without major rework ++ * of the main bic/bfqq data structures. By now we allow a task to change ++ * its cgroup only if it's the only owner of its ioc; the drawback of this ++ * behavior is that a group containing a task that forked using CLONE_IO ++ * will not be destroyed until the tasks sharing the ioc die. ++ */ ++static int bfqio_can_attach(struct cgroup_subsys_state *css, ++ struct cgroup_taskset *tset) ++{ ++ struct task_struct *task; ++ struct io_context *ioc; ++ int ret = 0; ++ ++ cgroup_taskset_for_each(task, tset) { ++ /* ++ * task_lock() is needed to avoid races with ++ * exit_io_context() ++ */ ++ task_lock(task); ++ ioc = task->io_context; ++ if (ioc != NULL && atomic_read(&ioc->nr_tasks) > 1) ++ /* ++ * ioc == NULL means that the task is either too ++ * young or exiting: if it has still no ioc the ++ * ioc can't be shared, if the task is exiting the ++ * attach will fail anyway, no matter what we ++ * return here. ++ */ ++ ret = -EINVAL; ++ task_unlock(task); ++ if (ret) ++ break; ++ } ++ ++ return ret; ++} ++ ++static void bfqio_attach(struct cgroup_subsys_state *css, ++ struct cgroup_taskset *tset) ++{ ++ struct task_struct *task; ++ struct io_context *ioc; ++ struct io_cq *icq; ++ ++ /* ++ * IMPORTANT NOTE: The move of more than one process at a time to a ++ * new group has not yet been tested. ++ */ ++ cgroup_taskset_for_each(task, tset) { ++ ioc = get_task_io_context(task, GFP_ATOMIC, NUMA_NO_NODE); ++ if (ioc) { ++ /* ++ * Handle cgroup change here. ++ */ ++ rcu_read_lock(); ++ hlist_for_each_entry_rcu(icq, &ioc->icq_list, ioc_node) ++ if (!strncmp( ++ icq->q->elevator->type->elevator_name, ++ "bfq", ELV_NAME_MAX)) ++ bfq_bic_change_cgroup(icq_to_bic(icq), ++ css); ++ rcu_read_unlock(); ++ put_io_context(ioc); ++ } ++ } ++} ++ ++static void bfqio_destroy(struct cgroup_subsys_state *css) ++{ ++ struct bfqio_cgroup *bgrp = css_to_bfqio(css); ++ struct hlist_node *tmp; ++ struct bfq_group *bfqg; ++ ++ /* ++ * Since we are destroying the cgroup, there are no more tasks ++ * referencing it, and all the RCU grace periods that may have ++ * referenced it are ended (as the destruction of the parent ++ * cgroup is RCU-safe); bgrp->group_data will not be accessed by ++ * anything else and we don't need any synchronization. ++ */ ++ hlist_for_each_entry_safe(bfqg, tmp, &bgrp->group_data, group_node) ++ bfq_destroy_group(bgrp, bfqg); ++ ++ BUG_ON(!hlist_empty(&bgrp->group_data)); ++ ++ kfree(bgrp); ++} ++ ++static int bfqio_css_online(struct cgroup_subsys_state *css) ++{ ++ struct bfqio_cgroup *bgrp = css_to_bfqio(css); ++ ++ mutex_lock(&bfqio_mutex); ++ bgrp->online = true; ++ mutex_unlock(&bfqio_mutex); ++ ++ return 0; ++} ++ ++static void bfqio_css_offline(struct cgroup_subsys_state *css) ++{ ++ struct bfqio_cgroup *bgrp = css_to_bfqio(css); ++ ++ mutex_lock(&bfqio_mutex); ++ bgrp->online = false; ++ mutex_unlock(&bfqio_mutex); ++} ++ ++struct cgroup_subsys bfqio_cgrp_subsys = { ++ .css_alloc = bfqio_create, ++ .css_online = bfqio_css_online, ++ .css_offline = bfqio_css_offline, ++ .can_attach = bfqio_can_attach, ++ .attach = bfqio_attach, ++ .css_free = bfqio_destroy, ++ .legacy_cftypes = bfqio_files, ++}; ++#else ++static inline void bfq_init_entity(struct bfq_entity *entity, ++ struct bfq_group *bfqg) ++{ ++ entity->weight = entity->new_weight; ++ entity->orig_weight = entity->new_weight; ++ entity->ioprio = entity->new_ioprio; ++ entity->ioprio_class = entity->new_ioprio_class; ++ entity->sched_data = &bfqg->sched_data; ++} ++ ++static inline struct bfq_group * ++bfq_bic_update_cgroup(struct bfq_io_cq *bic) ++{ ++ struct bfq_data *bfqd = bic_to_bfqd(bic); ++ return bfqd->root_group; ++} ++ ++static inline void bfq_bfqq_move(struct bfq_data *bfqd, ++ struct bfq_queue *bfqq, ++ struct bfq_entity *entity, ++ struct bfq_group *bfqg) ++{ ++} ++ ++static void bfq_end_wr_async(struct bfq_data *bfqd) ++{ ++ bfq_end_wr_async_queues(bfqd, bfqd->root_group); ++} ++ ++static inline void bfq_disconnect_groups(struct bfq_data *bfqd) ++{ ++ bfq_put_async_queues(bfqd, bfqd->root_group); ++} ++ ++static inline void bfq_free_root_group(struct bfq_data *bfqd) ++{ ++ kfree(bfqd->root_group); ++} ++ ++static struct bfq_group *bfq_alloc_root_group(struct bfq_data *bfqd, int node) ++{ ++ struct bfq_group *bfqg; ++ int i; ++ ++ bfqg = kmalloc_node(sizeof(*bfqg), GFP_KERNEL | __GFP_ZERO, node); ++ if (bfqg == NULL) ++ return NULL; ++ ++ for (i = 0; i < BFQ_IOPRIO_CLASSES; i++) ++ bfqg->sched_data.service_tree[i] = BFQ_SERVICE_TREE_INIT; ++ ++ return bfqg; ++} ++#endif +diff --git a/block/bfq-ioc.c b/block/bfq-ioc.c +new file mode 100644 +index 0000000..7f6b000 +--- /dev/null ++++ b/block/bfq-ioc.c +@@ -0,0 +1,36 @@ ++/* ++ * BFQ: I/O context handling. ++ * ++ * Based on ideas and code from CFQ: ++ * Copyright (C) 2003 Jens Axboe ++ * ++ * Copyright (C) 2008 Fabio Checconi ++ * Paolo Valente ++ * ++ * Copyright (C) 2010 Paolo Valente ++ */ ++ ++/** ++ * icq_to_bic - convert iocontext queue structure to bfq_io_cq. ++ * @icq: the iocontext queue. ++ */ ++static inline struct bfq_io_cq *icq_to_bic(struct io_cq *icq) ++{ ++ /* bic->icq is the first member, %NULL will convert to %NULL */ ++ return container_of(icq, struct bfq_io_cq, icq); ++} ++ ++/** ++ * bfq_bic_lookup - search into @ioc a bic associated to @bfqd. ++ * @bfqd: the lookup key. ++ * @ioc: the io_context of the process doing I/O. ++ * ++ * Queue lock must be held. ++ */ ++static inline struct bfq_io_cq *bfq_bic_lookup(struct bfq_data *bfqd, ++ struct io_context *ioc) ++{ ++ if (ioc) ++ return icq_to_bic(ioc_lookup_icq(ioc, bfqd->queue)); ++ return NULL; ++} +diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c +new file mode 100644 +index 0000000..97ee934 +--- /dev/null ++++ b/block/bfq-iosched.c +@@ -0,0 +1,3902 @@ ++/* ++ * Budget Fair Queueing (BFQ) disk scheduler. ++ * ++ * Based on ideas and code from CFQ: ++ * Copyright (C) 2003 Jens Axboe ++ * ++ * Copyright (C) 2008 Fabio Checconi ++ * Paolo Valente ++ * ++ * Copyright (C) 2010 Paolo Valente ++ * ++ * Licensed under the GPL-2 as detailed in the accompanying COPYING.BFQ ++ * file. ++ * ++ * BFQ is a proportional-share storage-I/O scheduling algorithm based on ++ * the slice-by-slice service scheme of CFQ. But BFQ assigns budgets, ++ * measured in number of sectors, to processes instead of time slices. The ++ * device is not granted to the in-service process for a given time slice, ++ * but until it has exhausted its assigned budget. This change from the time ++ * to the service domain allows BFQ to distribute the device throughput ++ * among processes as desired, without any distortion due to ZBR, workload ++ * fluctuations or other factors. BFQ uses an ad hoc internal scheduler, ++ * called B-WF2Q+, to schedule processes according to their budgets. More ++ * precisely, BFQ schedules queues associated to processes. Thanks to the ++ * accurate policy of B-WF2Q+, BFQ can afford to assign high budgets to ++ * I/O-bound processes issuing sequential requests (to boost the ++ * throughput), and yet guarantee a low latency to interactive and soft ++ * real-time applications. ++ * ++ * BFQ is described in [1], where also a reference to the initial, more ++ * theoretical paper on BFQ can be found. The interested reader can find ++ * in the latter paper full details on the main algorithm, as well as ++ * formulas of the guarantees and formal proofs of all the properties. ++ * With respect to the version of BFQ presented in these papers, this ++ * implementation adds a few more heuristics, such as the one that ++ * guarantees a low latency to soft real-time applications, and a ++ * hierarchical extension based on H-WF2Q+. ++ * ++ * B-WF2Q+ is based on WF2Q+, that is described in [2], together with ++ * H-WF2Q+, while the augmented tree used to implement B-WF2Q+ with O(log N) ++ * complexity derives from the one introduced with EEVDF in [3]. ++ * ++ * [1] P. Valente and M. Andreolini, ``Improving Application Responsiveness ++ * with the BFQ Disk I/O Scheduler'', ++ * Proceedings of the 5th Annual International Systems and Storage ++ * Conference (SYSTOR '12), June 2012. ++ * ++ * http://algogroup.unimo.it/people/paolo/disk_sched/bf1-v1-suite-results.pdf ++ * ++ * [2] Jon C.R. Bennett and H. Zhang, ``Hierarchical Packet Fair Queueing ++ * Algorithms,'' IEEE/ACM Transactions on Networking, 5(5):675-689, ++ * Oct 1997. ++ * ++ * http://www.cs.cmu.edu/~hzhang/papers/TON-97-Oct.ps.gz ++ * ++ * [3] I. Stoica and H. Abdel-Wahab, ``Earliest Eligible Virtual Deadline ++ * First: A Flexible and Accurate Mechanism for Proportional Share ++ * Resource Allocation,'' technical report. ++ * ++ * http://www.cs.berkeley.edu/~istoica/papers/eevdf-tr-95.pdf ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "bfq.h" ++#include "blk.h" ++ ++/* Max number of dispatches in one round of service. */ ++static const int bfq_quantum = 4; ++ ++/* Expiration time of sync (0) and async (1) requests, in jiffies. */ ++static const int bfq_fifo_expire[2] = { HZ / 4, HZ / 8 }; ++ ++/* Maximum backwards seek, in KiB. */ ++static const int bfq_back_max = 16 * 1024; ++ ++/* Penalty of a backwards seek, in number of sectors. */ ++static const int bfq_back_penalty = 2; ++ ++/* Idling period duration, in jiffies. */ ++static int bfq_slice_idle = HZ / 125; ++ ++/* Default maximum budget values, in sectors and number of requests. */ ++static const int bfq_default_max_budget = 16 * 1024; ++static const int bfq_max_budget_async_rq = 4; ++ ++/* ++ * Async to sync throughput distribution is controlled as follows: ++ * when an async request is served, the entity is charged the number ++ * of sectors of the request, multiplied by the factor below ++ */ ++static const int bfq_async_charge_factor = 10; ++ ++/* Default timeout values, in jiffies, approximating CFQ defaults. */ ++static const int bfq_timeout_sync = HZ / 8; ++static int bfq_timeout_async = HZ / 25; ++ ++struct kmem_cache *bfq_pool; ++ ++/* Below this threshold (in ms), we consider thinktime immediate. */ ++#define BFQ_MIN_TT 2 ++ ++/* hw_tag detection: parallel requests threshold and min samples needed. */ ++#define BFQ_HW_QUEUE_THRESHOLD 4 ++#define BFQ_HW_QUEUE_SAMPLES 32 ++ ++#define BFQQ_SEEK_THR (sector_t)(8 * 1024) ++#define BFQQ_SEEKY(bfqq) ((bfqq)->seek_mean > BFQQ_SEEK_THR) ++ ++/* Min samples used for peak rate estimation (for autotuning). */ ++#define BFQ_PEAK_RATE_SAMPLES 32 ++ ++/* Shift used for peak rate fixed precision calculations. */ ++#define BFQ_RATE_SHIFT 16 ++ ++/* ++ * By default, BFQ computes the duration of the weight raising for ++ * interactive applications automatically, using the following formula: ++ * duration = (R / r) * T, where r is the peak rate of the device, and ++ * R and T are two reference parameters. ++ * In particular, R is the peak rate of the reference device (see below), ++ * and T is a reference time: given the systems that are likely to be ++ * installed on the reference device according to its speed class, T is ++ * about the maximum time needed, under BFQ and while reading two files in ++ * parallel, to load typical large applications on these systems. ++ * In practice, the slower/faster the device at hand is, the more/less it ++ * takes to load applications with respect to the reference device. ++ * Accordingly, the longer/shorter BFQ grants weight raising to interactive ++ * applications. ++ * ++ * BFQ uses four different reference pairs (R, T), depending on: ++ * . whether the device is rotational or non-rotational; ++ * . whether the device is slow, such as old or portable HDDs, as well as ++ * SD cards, or fast, such as newer HDDs and SSDs. ++ * ++ * The device's speed class is dynamically (re)detected in ++ * bfq_update_peak_rate() every time the estimated peak rate is updated. ++ * ++ * In the following definitions, R_slow[0]/R_fast[0] and T_slow[0]/T_fast[0] ++ * are the reference values for a slow/fast rotational device, whereas ++ * R_slow[1]/R_fast[1] and T_slow[1]/T_fast[1] are the reference values for ++ * a slow/fast non-rotational device. Finally, device_speed_thresh are the ++ * thresholds used to switch between speed classes. ++ * Both the reference peak rates and the thresholds are measured in ++ * sectors/usec, left-shifted by BFQ_RATE_SHIFT. ++ */ ++static int R_slow[2] = {1536, 10752}; ++static int R_fast[2] = {17415, 34791}; ++/* ++ * To improve readability, a conversion function is used to initialize the ++ * following arrays, which entails that they can be initialized only in a ++ * function. ++ */ ++static int T_slow[2]; ++static int T_fast[2]; ++static int device_speed_thresh[2]; ++ ++#define BFQ_SERVICE_TREE_INIT ((struct bfq_service_tree) \ ++ { RB_ROOT, RB_ROOT, NULL, NULL, 0, 0 }) ++ ++#define RQ_BIC(rq) ((struct bfq_io_cq *) (rq)->elv.priv[0]) ++#define RQ_BFQQ(rq) ((rq)->elv.priv[1]) ++ ++static inline void bfq_schedule_dispatch(struct bfq_data *bfqd); ++ ++#include "bfq-ioc.c" ++#include "bfq-sched.c" ++#include "bfq-cgroup.c" ++ ++#define bfq_class_idle(bfqq) ((bfqq)->entity.ioprio_class ==\ ++ IOPRIO_CLASS_IDLE) ++#define bfq_class_rt(bfqq) ((bfqq)->entity.ioprio_class ==\ ++ IOPRIO_CLASS_RT) ++ ++#define bfq_sample_valid(samples) ((samples) > 80) ++ ++/* ++ * We regard a request as SYNC, if either it's a read or has the SYNC bit ++ * set (in which case it could also be a direct WRITE). ++ */ ++static inline int bfq_bio_sync(struct bio *bio) ++{ ++ if (bio_data_dir(bio) == READ || (bio->bi_rw & REQ_SYNC)) ++ return 1; ++ ++ return 0; ++} ++ ++/* ++ * Scheduler run of queue, if there are requests pending and no one in the ++ * driver that will restart queueing. ++ */ ++static inline void bfq_schedule_dispatch(struct bfq_data *bfqd) ++{ ++ if (bfqd->queued != 0) { ++ bfq_log(bfqd, "schedule dispatch"); ++ kblockd_schedule_work(&bfqd->unplug_work); ++ } ++} ++ ++/* ++ * Lifted from AS - choose which of rq1 and rq2 that is best served now. ++ * We choose the request that is closesr to the head right now. Distance ++ * behind the head is penalized and only allowed to a certain extent. ++ */ ++static struct request *bfq_choose_req(struct bfq_data *bfqd, ++ struct request *rq1, ++ struct request *rq2, ++ sector_t last) ++{ ++ sector_t s1, s2, d1 = 0, d2 = 0; ++ unsigned long back_max; ++#define BFQ_RQ1_WRAP 0x01 /* request 1 wraps */ ++#define BFQ_RQ2_WRAP 0x02 /* request 2 wraps */ ++ unsigned wrap = 0; /* bit mask: requests behind the disk head? */ ++ ++ if (rq1 == NULL || rq1 == rq2) ++ return rq2; ++ if (rq2 == NULL) ++ return rq1; ++ ++ if (rq_is_sync(rq1) && !rq_is_sync(rq2)) ++ return rq1; ++ else if (rq_is_sync(rq2) && !rq_is_sync(rq1)) ++ return rq2; ++ if ((rq1->cmd_flags & REQ_META) && !(rq2->cmd_flags & REQ_META)) ++ return rq1; ++ else if ((rq2->cmd_flags & REQ_META) && !(rq1->cmd_flags & REQ_META)) ++ return rq2; ++ ++ s1 = blk_rq_pos(rq1); ++ s2 = blk_rq_pos(rq2); ++ ++ /* ++ * By definition, 1KiB is 2 sectors. ++ */ ++ back_max = bfqd->bfq_back_max * 2; ++ ++ /* ++ * Strict one way elevator _except_ in the case where we allow ++ * short backward seeks which are biased as twice the cost of a ++ * similar forward seek. ++ */ ++ if (s1 >= last) ++ d1 = s1 - last; ++ else if (s1 + back_max >= last) ++ d1 = (last - s1) * bfqd->bfq_back_penalty; ++ else ++ wrap |= BFQ_RQ1_WRAP; ++ ++ if (s2 >= last) ++ d2 = s2 - last; ++ else if (s2 + back_max >= last) ++ d2 = (last - s2) * bfqd->bfq_back_penalty; ++ else ++ wrap |= BFQ_RQ2_WRAP; ++ ++ /* Found required data */ ++ ++ /* ++ * By doing switch() on the bit mask "wrap" we avoid having to ++ * check two variables for all permutations: --> faster! ++ */ ++ switch (wrap) { ++ case 0: /* common case for CFQ: rq1 and rq2 not wrapped */ ++ if (d1 < d2) ++ return rq1; ++ else if (d2 < d1) ++ return rq2; ++ else { ++ if (s1 >= s2) ++ return rq1; ++ else ++ return rq2; ++ } ++ ++ case BFQ_RQ2_WRAP: ++ return rq1; ++ case BFQ_RQ1_WRAP: ++ return rq2; ++ case (BFQ_RQ1_WRAP|BFQ_RQ2_WRAP): /* both rqs wrapped */ ++ default: ++ /* ++ * Since both rqs are wrapped, ++ * start with the one that's further behind head ++ * (--> only *one* back seek required), ++ * since back seek takes more time than forward. ++ */ ++ if (s1 <= s2) ++ return rq1; ++ else ++ return rq2; ++ } ++} ++ ++static struct bfq_queue * ++bfq_rq_pos_tree_lookup(struct bfq_data *bfqd, struct rb_root *root, ++ sector_t sector, struct rb_node **ret_parent, ++ struct rb_node ***rb_link) ++{ ++ struct rb_node **p, *parent; ++ struct bfq_queue *bfqq = NULL; ++ ++ parent = NULL; ++ p = &root->rb_node; ++ while (*p) { ++ struct rb_node **n; ++ ++ parent = *p; ++ bfqq = rb_entry(parent, struct bfq_queue, pos_node); ++ ++ /* ++ * Sort strictly based on sector. Smallest to the left, ++ * largest to the right. ++ */ ++ if (sector > blk_rq_pos(bfqq->next_rq)) ++ n = &(*p)->rb_right; ++ else if (sector < blk_rq_pos(bfqq->next_rq)) ++ n = &(*p)->rb_left; ++ else ++ break; ++ p = n; ++ bfqq = NULL; ++ } ++ ++ *ret_parent = parent; ++ if (rb_link) ++ *rb_link = p; ++ ++ bfq_log(bfqd, "rq_pos_tree_lookup %llu: returning %d", ++ (long long unsigned)sector, ++ bfqq != NULL ? bfqq->pid : 0); ++ ++ return bfqq; ++} ++ ++static void bfq_rq_pos_tree_add(struct bfq_data *bfqd, struct bfq_queue *bfqq) ++{ ++ struct rb_node **p, *parent; ++ struct bfq_queue *__bfqq; ++ ++ if (bfqq->pos_root != NULL) { ++ rb_erase(&bfqq->pos_node, bfqq->pos_root); ++ bfqq->pos_root = NULL; ++ } ++ ++ if (bfq_class_idle(bfqq)) ++ return; ++ if (!bfqq->next_rq) ++ return; ++ ++ bfqq->pos_root = &bfqd->rq_pos_tree; ++ __bfqq = bfq_rq_pos_tree_lookup(bfqd, bfqq->pos_root, ++ blk_rq_pos(bfqq->next_rq), &parent, &p); ++ if (__bfqq == NULL) { ++ rb_link_node(&bfqq->pos_node, parent, p); ++ rb_insert_color(&bfqq->pos_node, bfqq->pos_root); ++ } else ++ bfqq->pos_root = NULL; ++} ++ ++/* ++ * Tell whether there are active queues or groups with differentiated weights. ++ */ ++static inline bool bfq_differentiated_weights(struct bfq_data *bfqd) ++{ ++ BUG_ON(!bfqd->hw_tag); ++ /* ++ * For weights to differ, at least one of the trees must contain ++ * at least two nodes. ++ */ ++ return (!RB_EMPTY_ROOT(&bfqd->queue_weights_tree) && ++ (bfqd->queue_weights_tree.rb_node->rb_left || ++ bfqd->queue_weights_tree.rb_node->rb_right) ++#ifdef CONFIG_CGROUP_BFQIO ++ ) || ++ (!RB_EMPTY_ROOT(&bfqd->group_weights_tree) && ++ (bfqd->group_weights_tree.rb_node->rb_left || ++ bfqd->group_weights_tree.rb_node->rb_right) ++#endif ++ ); ++} ++ ++/* ++ * If the weight-counter tree passed as input contains no counter for ++ * the weight of the input entity, then add that counter; otherwise just ++ * increment the existing counter. ++ * ++ * Note that weight-counter trees contain few nodes in mostly symmetric ++ * scenarios. For example, if all queues have the same weight, then the ++ * weight-counter tree for the queues may contain at most one node. ++ * This holds even if low_latency is on, because weight-raised queues ++ * are not inserted in the tree. ++ * In most scenarios, the rate at which nodes are created/destroyed ++ * should be low too. ++ */ ++static void bfq_weights_tree_add(struct bfq_data *bfqd, ++ struct bfq_entity *entity, ++ struct rb_root *root) ++{ ++ struct rb_node **new = &(root->rb_node), *parent = NULL; ++ ++ /* ++ * Do not insert if: ++ * - the device does not support queueing; ++ * - the entity is already associated with a counter, which happens if: ++ * 1) the entity is associated with a queue, 2) a request arrival ++ * has caused the queue to become both non-weight-raised, and hence ++ * change its weight, and backlogged; in this respect, each ++ * of the two events causes an invocation of this function, ++ * 3) this is the invocation of this function caused by the second ++ * event. This second invocation is actually useless, and we handle ++ * this fact by exiting immediately. More efficient or clearer ++ * solutions might possibly be adopted. ++ */ ++ if (!bfqd->hw_tag || entity->weight_counter) ++ return; ++ ++ while (*new) { ++ struct bfq_weight_counter *__counter = container_of(*new, ++ struct bfq_weight_counter, ++ weights_node); ++ parent = *new; ++ ++ if (entity->weight == __counter->weight) { ++ entity->weight_counter = __counter; ++ goto inc_counter; ++ } ++ if (entity->weight < __counter->weight) ++ new = &((*new)->rb_left); ++ else ++ new = &((*new)->rb_right); ++ } ++ ++ entity->weight_counter = kzalloc(sizeof(struct bfq_weight_counter), ++ GFP_ATOMIC); ++ entity->weight_counter->weight = entity->weight; ++ rb_link_node(&entity->weight_counter->weights_node, parent, new); ++ rb_insert_color(&entity->weight_counter->weights_node, root); ++ ++inc_counter: ++ entity->weight_counter->num_active++; ++} ++ ++/* ++ * Decrement the weight counter associated with the entity, and, if the ++ * counter reaches 0, remove the counter from the tree. ++ * See the comments to the function bfq_weights_tree_add() for considerations ++ * about overhead. ++ */ ++static void bfq_weights_tree_remove(struct bfq_data *bfqd, ++ struct bfq_entity *entity, ++ struct rb_root *root) ++{ ++ /* ++ * Check whether the entity is actually associated with a counter. ++ * In fact, the device may not be considered NCQ-capable for a while, ++ * which implies that no insertion in the weight trees is performed, ++ * after which the device may start to be deemed NCQ-capable, and hence ++ * this function may start to be invoked. This may cause the function ++ * to be invoked for entities that are not associated with any counter. ++ */ ++ if (!entity->weight_counter) ++ return; ++ ++ BUG_ON(RB_EMPTY_ROOT(root)); ++ BUG_ON(entity->weight_counter->weight != entity->weight); ++ ++ BUG_ON(!entity->weight_counter->num_active); ++ entity->weight_counter->num_active--; ++ if (entity->weight_counter->num_active > 0) ++ goto reset_entity_pointer; ++ ++ rb_erase(&entity->weight_counter->weights_node, root); ++ kfree(entity->weight_counter); ++ ++reset_entity_pointer: ++ entity->weight_counter = NULL; ++} ++ ++static struct request *bfq_find_next_rq(struct bfq_data *bfqd, ++ struct bfq_queue *bfqq, ++ struct request *last) ++{ ++ struct rb_node *rbnext = rb_next(&last->rb_node); ++ struct rb_node *rbprev = rb_prev(&last->rb_node); ++ struct request *next = NULL, *prev = NULL; ++ ++ BUG_ON(RB_EMPTY_NODE(&last->rb_node)); ++ ++ if (rbprev != NULL) ++ prev = rb_entry_rq(rbprev); ++ ++ if (rbnext != NULL) ++ next = rb_entry_rq(rbnext); ++ else { ++ rbnext = rb_first(&bfqq->sort_list); ++ if (rbnext && rbnext != &last->rb_node) ++ next = rb_entry_rq(rbnext); ++ } ++ ++ return bfq_choose_req(bfqd, next, prev, blk_rq_pos(last)); ++} ++ ++/* see the definition of bfq_async_charge_factor for details */ ++static inline unsigned long bfq_serv_to_charge(struct request *rq, ++ struct bfq_queue *bfqq) ++{ ++ return blk_rq_sectors(rq) * ++ (1 + ((!bfq_bfqq_sync(bfqq)) * (bfqq->wr_coeff == 1) * ++ bfq_async_charge_factor)); ++} ++ ++/** ++ * bfq_updated_next_req - update the queue after a new next_rq selection. ++ * @bfqd: the device data the queue belongs to. ++ * @bfqq: the queue to update. ++ * ++ * If the first request of a queue changes we make sure that the queue ++ * has enough budget to serve at least its first request (if the ++ * request has grown). We do this because if the queue has not enough ++ * budget for its first request, it has to go through two dispatch ++ * rounds to actually get it dispatched. ++ */ ++static void bfq_updated_next_req(struct bfq_data *bfqd, ++ struct bfq_queue *bfqq) ++{ ++ struct bfq_entity *entity = &bfqq->entity; ++ struct bfq_service_tree *st = bfq_entity_service_tree(entity); ++ struct request *next_rq = bfqq->next_rq; ++ unsigned long new_budget; ++ ++ if (next_rq == NULL) ++ return; ++ ++ if (bfqq == bfqd->in_service_queue) ++ /* ++ * In order not to break guarantees, budgets cannot be ++ * changed after an entity has been selected. ++ */ ++ return; ++ ++ BUG_ON(entity->tree != &st->active); ++ BUG_ON(entity == entity->sched_data->in_service_entity); ++ ++ new_budget = max_t(unsigned long, bfqq->max_budget, ++ bfq_serv_to_charge(next_rq, bfqq)); ++ if (entity->budget != new_budget) { ++ entity->budget = new_budget; ++ bfq_log_bfqq(bfqd, bfqq, "updated next rq: new budget %lu", ++ new_budget); ++ bfq_activate_bfqq(bfqd, bfqq); ++ } ++} ++ ++static inline unsigned int bfq_wr_duration(struct bfq_data *bfqd) ++{ ++ u64 dur; ++ ++ if (bfqd->bfq_wr_max_time > 0) ++ return bfqd->bfq_wr_max_time; ++ ++ dur = bfqd->RT_prod; ++ do_div(dur, bfqd->peak_rate); ++ ++ return dur; ++} ++ ++/* Empty burst list and add just bfqq (see comments to bfq_handle_burst) */ ++static inline void bfq_reset_burst_list(struct bfq_data *bfqd, ++ struct bfq_queue *bfqq) ++{ ++ struct bfq_queue *item; ++ struct hlist_node *n; ++ ++ hlist_for_each_entry_safe(item, n, &bfqd->burst_list, burst_list_node) ++ hlist_del_init(&item->burst_list_node); ++ hlist_add_head(&bfqq->burst_list_node, &bfqd->burst_list); ++ bfqd->burst_size = 1; ++} ++ ++/* Add bfqq to the list of queues in current burst (see bfq_handle_burst) */ ++static void bfq_add_to_burst(struct bfq_data *bfqd, struct bfq_queue *bfqq) ++{ ++ /* Increment burst size to take into account also bfqq */ ++ bfqd->burst_size++; ++ ++ if (bfqd->burst_size == bfqd->bfq_large_burst_thresh) { ++ struct bfq_queue *pos, *bfqq_item; ++ struct hlist_node *n; ++ ++ /* ++ * Enough queues have been activated shortly after each ++ * other to consider this burst as large. ++ */ ++ bfqd->large_burst = true; ++ ++ /* ++ * We can now mark all queues in the burst list as ++ * belonging to a large burst. ++ */ ++ hlist_for_each_entry(bfqq_item, &bfqd->burst_list, ++ burst_list_node) ++ bfq_mark_bfqq_in_large_burst(bfqq_item); ++ bfq_mark_bfqq_in_large_burst(bfqq); ++ ++ /* ++ * From now on, and until the current burst finishes, any ++ * new queue being activated shortly after the last queue ++ * was inserted in the burst can be immediately marked as ++ * belonging to a large burst. So the burst list is not ++ * needed any more. Remove it. ++ */ ++ hlist_for_each_entry_safe(pos, n, &bfqd->burst_list, ++ burst_list_node) ++ hlist_del_init(&pos->burst_list_node); ++ } else /* burst not yet large: add bfqq to the burst list */ ++ hlist_add_head(&bfqq->burst_list_node, &bfqd->burst_list); ++} ++ ++/* ++ * If many queues happen to become active shortly after each other, then, ++ * to help the processes associated to these queues get their job done as ++ * soon as possible, it is usually better to not grant either weight-raising ++ * or device idling to these queues. In this comment we describe, firstly, ++ * the reasons why this fact holds, and, secondly, the next function, which ++ * implements the main steps needed to properly mark these queues so that ++ * they can then be treated in a different way. ++ * ++ * As for the terminology, we say that a queue becomes active, i.e., ++ * switches from idle to backlogged, either when it is created (as a ++ * consequence of the arrival of an I/O request), or, if already existing, ++ * when a new request for the queue arrives while the queue is idle. ++ * Bursts of activations, i.e., activations of different queues occurring ++ * shortly after each other, are typically caused by services or applications ++ * that spawn or reactivate many parallel threads/processes. Examples are ++ * systemd during boot or git grep. ++ * ++ * These services or applications benefit mostly from a high throughput: ++ * the quicker the requests of the activated queues are cumulatively served, ++ * the sooner the target job of these queues gets completed. As a consequence, ++ * weight-raising any of these queues, which also implies idling the device ++ * for it, is almost always counterproductive: in most cases it just lowers ++ * throughput. ++ * ++ * On the other hand, a burst of activations may be also caused by the start ++ * of an application that does not consist in a lot of parallel I/O-bound ++ * threads. In fact, with a complex application, the burst may be just a ++ * consequence of the fact that several processes need to be executed to ++ * start-up the application. To start an application as quickly as possible, ++ * the best thing to do is to privilege the I/O related to the application ++ * with respect to all other I/O. Therefore, the best strategy to start as ++ * quickly as possible an application that causes a burst of activations is ++ * to weight-raise all the queues activated during the burst. This is the ++ * exact opposite of the best strategy for the other type of bursts. ++ * ++ * In the end, to take the best action for each of the two cases, the two ++ * types of bursts need to be distinguished. Fortunately, this seems ++ * relatively easy to do, by looking at the sizes of the bursts. In ++ * particular, we found a threshold such that bursts with a larger size ++ * than that threshold are apparently caused only by services or commands ++ * such as systemd or git grep. For brevity, hereafter we call just 'large' ++ * these bursts. BFQ *does not* weight-raise queues whose activations occur ++ * in a large burst. In addition, for each of these queues BFQ performs or ++ * does not perform idling depending on which choice boosts the throughput ++ * most. The exact choice depends on the device and request pattern at ++ * hand. ++ * ++ * Turning back to the next function, it implements all the steps needed ++ * to detect the occurrence of a large burst and to properly mark all the ++ * queues belonging to it (so that they can then be treated in a different ++ * way). This goal is achieved by maintaining a special "burst list" that ++ * holds, temporarily, the queues that belong to the burst in progress. The ++ * list is then used to mark these queues as belonging to a large burst if ++ * the burst does become large. The main steps are the following. ++ * ++ * . when the very first queue is activated, the queue is inserted into the ++ * list (as it could be the first queue in a possible burst) ++ * ++ * . if the current burst has not yet become large, and a queue Q that does ++ * not yet belong to the burst is activated shortly after the last time ++ * at which a new queue entered the burst list, then the function appends ++ * Q to the burst list ++ * ++ * . if, as a consequence of the previous step, the burst size reaches ++ * the large-burst threshold, then ++ * ++ * . all the queues in the burst list are marked as belonging to a ++ * large burst ++ * ++ * . the burst list is deleted; in fact, the burst list already served ++ * its purpose (keeping temporarily track of the queues in a burst, ++ * so as to be able to mark them as belonging to a large burst in the ++ * previous sub-step), and now is not needed any more ++ * ++ * . the device enters a large-burst mode ++ * ++ * . if a queue Q that does not belong to the burst is activated while ++ * the device is in large-burst mode and shortly after the last time ++ * at which a queue either entered the burst list or was marked as ++ * belonging to the current large burst, then Q is immediately marked ++ * as belonging to a large burst. ++ * ++ * . if a queue Q that does not belong to the burst is activated a while ++ * later, i.e., not shortly after, than the last time at which a queue ++ * either entered the burst list or was marked as belonging to the ++ * current large burst, then the current burst is deemed as finished and: ++ * ++ * . the large-burst mode is reset if set ++ * ++ * . the burst list is emptied ++ * ++ * . Q is inserted in the burst list, as Q may be the first queue ++ * in a possible new burst (then the burst list contains just Q ++ * after this step). ++ */ ++static void bfq_handle_burst(struct bfq_data *bfqd, struct bfq_queue *bfqq, ++ bool idle_for_long_time) ++{ ++ /* ++ * If bfqq happened to be activated in a burst, but has been idle ++ * for at least as long as an interactive queue, then we assume ++ * that, in the overall I/O initiated in the burst, the I/O ++ * associated to bfqq is finished. So bfqq does not need to be ++ * treated as a queue belonging to a burst anymore. Accordingly, ++ * we reset bfqq's in_large_burst flag if set, and remove bfqq ++ * from the burst list if it's there. We do not decrement instead ++ * burst_size, because the fact that bfqq does not need to belong ++ * to the burst list any more does not invalidate the fact that ++ * bfqq may have been activated during the current burst. ++ */ ++ if (idle_for_long_time) { ++ hlist_del_init(&bfqq->burst_list_node); ++ bfq_clear_bfqq_in_large_burst(bfqq); ++ } ++ ++ /* ++ * If bfqq is already in the burst list or is part of a large ++ * burst, then there is nothing else to do. ++ */ ++ if (!hlist_unhashed(&bfqq->burst_list_node) || ++ bfq_bfqq_in_large_burst(bfqq)) ++ return; ++ ++ /* ++ * If bfqq's activation happens late enough, then the current ++ * burst is finished, and related data structures must be reset. ++ * ++ * In this respect, consider the special case where bfqq is the very ++ * first queue being activated. In this case, last_ins_in_burst is ++ * not yet significant when we get here. But it is easy to verify ++ * that, whether or not the following condition is true, bfqq will ++ * end up being inserted into the burst list. In particular the ++ * list will happen to contain only bfqq. And this is exactly what ++ * has to happen, as bfqq may be the first queue in a possible ++ * burst. ++ */ ++ if (time_is_before_jiffies(bfqd->last_ins_in_burst + ++ bfqd->bfq_burst_interval)) { ++ bfqd->large_burst = false; ++ bfq_reset_burst_list(bfqd, bfqq); ++ return; ++ } ++ ++ /* ++ * If we get here, then bfqq is being activated shortly after the ++ * last queue. So, if the current burst is also large, we can mark ++ * bfqq as belonging to this large burst immediately. ++ */ ++ if (bfqd->large_burst) { ++ bfq_mark_bfqq_in_large_burst(bfqq); ++ return; ++ } ++ ++ /* ++ * If we get here, then a large-burst state has not yet been ++ * reached, but bfqq is being activated shortly after the last ++ * queue. Then we add bfqq to the burst. ++ */ ++ bfq_add_to_burst(bfqd, bfqq); ++} ++ ++static void bfq_add_request(struct request *rq) ++{ ++ struct bfq_queue *bfqq = RQ_BFQQ(rq); ++ struct bfq_entity *entity = &bfqq->entity; ++ struct bfq_data *bfqd = bfqq->bfqd; ++ struct request *next_rq, *prev; ++ unsigned long old_wr_coeff = bfqq->wr_coeff; ++ bool interactive = false; ++ ++ bfq_log_bfqq(bfqd, bfqq, "add_request %d", rq_is_sync(rq)); ++ bfqq->queued[rq_is_sync(rq)]++; ++ bfqd->queued++; ++ ++ elv_rb_add(&bfqq->sort_list, rq); ++ ++ /* ++ * Check if this request is a better next-serve candidate. ++ */ ++ prev = bfqq->next_rq; ++ next_rq = bfq_choose_req(bfqd, bfqq->next_rq, rq, bfqd->last_position); ++ BUG_ON(next_rq == NULL); ++ bfqq->next_rq = next_rq; ++ ++ /* ++ * Adjust priority tree position, if next_rq changes. ++ */ ++ if (prev != bfqq->next_rq) ++ bfq_rq_pos_tree_add(bfqd, bfqq); ++ ++ if (!bfq_bfqq_busy(bfqq)) { ++ bool soft_rt, ++ idle_for_long_time = time_is_before_jiffies( ++ bfqq->budget_timeout + ++ bfqd->bfq_wr_min_idle_time); ++ ++ if (bfq_bfqq_sync(bfqq)) { ++ bool already_in_burst = ++ !hlist_unhashed(&bfqq->burst_list_node) || ++ bfq_bfqq_in_large_burst(bfqq); ++ bfq_handle_burst(bfqd, bfqq, idle_for_long_time); ++ /* ++ * If bfqq was not already in the current burst, ++ * then, at this point, bfqq either has been ++ * added to the current burst or has caused the ++ * current burst to terminate. In particular, in ++ * the second case, bfqq has become the first ++ * queue in a possible new burst. ++ * In both cases last_ins_in_burst needs to be ++ * moved forward. ++ */ ++ if (!already_in_burst) ++ bfqd->last_ins_in_burst = jiffies; ++ } ++ ++ soft_rt = bfqd->bfq_wr_max_softrt_rate > 0 && ++ !bfq_bfqq_in_large_burst(bfqq) && ++ time_is_before_jiffies(bfqq->soft_rt_next_start); ++ interactive = !bfq_bfqq_in_large_burst(bfqq) && ++ idle_for_long_time; ++ entity->budget = max_t(unsigned long, bfqq->max_budget, ++ bfq_serv_to_charge(next_rq, bfqq)); ++ ++ if (!bfq_bfqq_IO_bound(bfqq)) { ++ if (time_before(jiffies, ++ RQ_BIC(rq)->ttime.last_end_request + ++ bfqd->bfq_slice_idle)) { ++ bfqq->requests_within_timer++; ++ if (bfqq->requests_within_timer >= ++ bfqd->bfq_requests_within_timer) ++ bfq_mark_bfqq_IO_bound(bfqq); ++ } else ++ bfqq->requests_within_timer = 0; ++ } ++ ++ if (!bfqd->low_latency) ++ goto add_bfqq_busy; ++ ++ /* ++ * If the queue is not being boosted and has been idle ++ * for enough time, start a weight-raising period ++ */ ++ if (old_wr_coeff == 1 && (interactive || soft_rt)) { ++ bfqq->wr_coeff = bfqd->bfq_wr_coeff; ++ if (interactive) ++ bfqq->wr_cur_max_time = bfq_wr_duration(bfqd); ++ else ++ bfqq->wr_cur_max_time = ++ bfqd->bfq_wr_rt_max_time; ++ bfq_log_bfqq(bfqd, bfqq, ++ "wrais starting at %lu, rais_max_time %u", ++ jiffies, ++ jiffies_to_msecs(bfqq->wr_cur_max_time)); ++ } else if (old_wr_coeff > 1) { ++ if (interactive) ++ bfqq->wr_cur_max_time = bfq_wr_duration(bfqd); ++ else if (bfq_bfqq_in_large_burst(bfqq) || ++ (bfqq->wr_cur_max_time == ++ bfqd->bfq_wr_rt_max_time && ++ !soft_rt)) { ++ bfqq->wr_coeff = 1; ++ bfq_log_bfqq(bfqd, bfqq, ++ "wrais ending at %lu, rais_max_time %u", ++ jiffies, ++ jiffies_to_msecs(bfqq-> ++ wr_cur_max_time)); ++ } else if (time_before( ++ bfqq->last_wr_start_finish + ++ bfqq->wr_cur_max_time, ++ jiffies + ++ bfqd->bfq_wr_rt_max_time) && ++ soft_rt) { ++ /* ++ * ++ * The remaining weight-raising time is lower ++ * than bfqd->bfq_wr_rt_max_time, which ++ * means that the application is enjoying ++ * weight raising either because deemed soft- ++ * rt in the near past, or because deemed ++ * interactive a long ago. In both cases, ++ * resetting now the current remaining weight- ++ * raising time for the application to the ++ * weight-raising duration for soft rt ++ * applications would not cause any latency ++ * increase for the application (as the new ++ * duration would be higher than the remaining ++ * time). ++ * ++ * In addition, the application is now meeting ++ * the requirements for being deemed soft rt. ++ * In the end we can correctly and safely ++ * (re)charge the weight-raising duration for ++ * the application with the weight-raising ++ * duration for soft rt applications. ++ * ++ * In particular, doing this recharge now, i.e., ++ * before the weight-raising period for the ++ * application finishes, reduces the probability ++ * of the following negative scenario: ++ * 1) the weight of a soft rt application is ++ * raised at startup (as for any newly ++ * created application), ++ * 2) since the application is not interactive, ++ * at a certain time weight-raising is ++ * stopped for the application, ++ * 3) at that time the application happens to ++ * still have pending requests, and hence ++ * is destined to not have a chance to be ++ * deemed soft rt before these requests are ++ * completed (see the comments to the ++ * function bfq_bfqq_softrt_next_start() ++ * for details on soft rt detection), ++ * 4) these pending requests experience a high ++ * latency because the application is not ++ * weight-raised while they are pending. ++ */ ++ bfqq->last_wr_start_finish = jiffies; ++ bfqq->wr_cur_max_time = ++ bfqd->bfq_wr_rt_max_time; ++ } ++ } ++ if (old_wr_coeff != bfqq->wr_coeff) ++ entity->ioprio_changed = 1; ++add_bfqq_busy: ++ bfqq->last_idle_bklogged = jiffies; ++ bfqq->service_from_backlogged = 0; ++ bfq_clear_bfqq_softrt_update(bfqq); ++ bfq_add_bfqq_busy(bfqd, bfqq); ++ } else { ++ if (bfqd->low_latency && old_wr_coeff == 1 && !rq_is_sync(rq) && ++ time_is_before_jiffies( ++ bfqq->last_wr_start_finish + ++ bfqd->bfq_wr_min_inter_arr_async)) { ++ bfqq->wr_coeff = bfqd->bfq_wr_coeff; ++ bfqq->wr_cur_max_time = bfq_wr_duration(bfqd); ++ ++ bfqd->wr_busy_queues++; ++ entity->ioprio_changed = 1; ++ bfq_log_bfqq(bfqd, bfqq, ++ "non-idle wrais starting at %lu, rais_max_time %u", ++ jiffies, ++ jiffies_to_msecs(bfqq->wr_cur_max_time)); ++ } ++ if (prev != bfqq->next_rq) ++ bfq_updated_next_req(bfqd, bfqq); ++ } ++ ++ if (bfqd->low_latency && ++ (old_wr_coeff == 1 || bfqq->wr_coeff == 1 || interactive)) ++ bfqq->last_wr_start_finish = jiffies; ++} ++ ++static struct request *bfq_find_rq_fmerge(struct bfq_data *bfqd, ++ struct bio *bio) ++{ ++ struct task_struct *tsk = current; ++ struct bfq_io_cq *bic; ++ struct bfq_queue *bfqq; ++ ++ bic = bfq_bic_lookup(bfqd, tsk->io_context); ++ if (bic == NULL) ++ return NULL; ++ ++ bfqq = bic_to_bfqq(bic, bfq_bio_sync(bio)); ++ if (bfqq != NULL) ++ return elv_rb_find(&bfqq->sort_list, bio_end_sector(bio)); ++ ++ return NULL; ++} ++ ++static void bfq_activate_request(struct request_queue *q, struct request *rq) ++{ ++ struct bfq_data *bfqd = q->elevator->elevator_data; ++ ++ bfqd->rq_in_driver++; ++ bfqd->last_position = blk_rq_pos(rq) + blk_rq_sectors(rq); ++ bfq_log(bfqd, "activate_request: new bfqd->last_position %llu", ++ (long long unsigned)bfqd->last_position); ++} ++ ++static inline void bfq_deactivate_request(struct request_queue *q, ++ struct request *rq) ++{ ++ struct bfq_data *bfqd = q->elevator->elevator_data; ++ ++ BUG_ON(bfqd->rq_in_driver == 0); ++ bfqd->rq_in_driver--; ++} ++ ++static void bfq_remove_request(struct request *rq) ++{ ++ struct bfq_queue *bfqq = RQ_BFQQ(rq); ++ struct bfq_data *bfqd = bfqq->bfqd; ++ const int sync = rq_is_sync(rq); ++ ++ if (bfqq->next_rq == rq) { ++ bfqq->next_rq = bfq_find_next_rq(bfqd, bfqq, rq); ++ bfq_updated_next_req(bfqd, bfqq); ++ } ++ ++ list_del_init(&rq->queuelist); ++ BUG_ON(bfqq->queued[sync] == 0); ++ bfqq->queued[sync]--; ++ bfqd->queued--; ++ elv_rb_del(&bfqq->sort_list, rq); ++ ++ if (RB_EMPTY_ROOT(&bfqq->sort_list)) { ++ if (bfq_bfqq_busy(bfqq) && bfqq != bfqd->in_service_queue) ++ bfq_del_bfqq_busy(bfqd, bfqq, 1); ++ /* ++ * Remove queue from request-position tree as it is empty. ++ */ ++ if (bfqq->pos_root != NULL) { ++ rb_erase(&bfqq->pos_node, bfqq->pos_root); ++ bfqq->pos_root = NULL; ++ } ++ } ++ ++ if (rq->cmd_flags & REQ_META) { ++ BUG_ON(bfqq->meta_pending == 0); ++ bfqq->meta_pending--; ++ } ++} ++ ++static int bfq_merge(struct request_queue *q, struct request **req, ++ struct bio *bio) ++{ ++ struct bfq_data *bfqd = q->elevator->elevator_data; ++ struct request *__rq; ++ ++ __rq = bfq_find_rq_fmerge(bfqd, bio); ++ if (__rq != NULL && elv_rq_merge_ok(__rq, bio)) { ++ *req = __rq; ++ return ELEVATOR_FRONT_MERGE; ++ } ++ ++ return ELEVATOR_NO_MERGE; ++} ++ ++static void bfq_merged_request(struct request_queue *q, struct request *req, ++ int type) ++{ ++ if (type == ELEVATOR_FRONT_MERGE && ++ rb_prev(&req->rb_node) && ++ blk_rq_pos(req) < ++ blk_rq_pos(container_of(rb_prev(&req->rb_node), ++ struct request, rb_node))) { ++ struct bfq_queue *bfqq = RQ_BFQQ(req); ++ struct bfq_data *bfqd = bfqq->bfqd; ++ struct request *prev, *next_rq; ++ ++ /* Reposition request in its sort_list */ ++ elv_rb_del(&bfqq->sort_list, req); ++ elv_rb_add(&bfqq->sort_list, req); ++ /* Choose next request to be served for bfqq */ ++ prev = bfqq->next_rq; ++ next_rq = bfq_choose_req(bfqd, bfqq->next_rq, req, ++ bfqd->last_position); ++ BUG_ON(next_rq == NULL); ++ bfqq->next_rq = next_rq; ++ /* ++ * If next_rq changes, update both the queue's budget to ++ * fit the new request and the queue's position in its ++ * rq_pos_tree. ++ */ ++ if (prev != bfqq->next_rq) { ++ bfq_updated_next_req(bfqd, bfqq); ++ bfq_rq_pos_tree_add(bfqd, bfqq); ++ } ++ } ++} ++ ++static void bfq_merged_requests(struct request_queue *q, struct request *rq, ++ struct request *next) ++{ ++ struct bfq_queue *bfqq = RQ_BFQQ(rq); ++ ++ /* ++ * Reposition in fifo if next is older than rq. ++ */ ++ if (!list_empty(&rq->queuelist) && !list_empty(&next->queuelist) && ++ time_before(next->fifo_time, rq->fifo_time)) { ++ list_move(&rq->queuelist, &next->queuelist); ++ rq->fifo_time = next->fifo_time; ++ } ++ ++ if (bfqq->next_rq == next) ++ bfqq->next_rq = rq; ++ ++ bfq_remove_request(next); ++} ++ ++/* Must be called with bfqq != NULL */ ++static inline void bfq_bfqq_end_wr(struct bfq_queue *bfqq) ++{ ++ BUG_ON(bfqq == NULL); ++ if (bfq_bfqq_busy(bfqq)) ++ bfqq->bfqd->wr_busy_queues--; ++ bfqq->wr_coeff = 1; ++ bfqq->wr_cur_max_time = 0; ++ /* Trigger a weight change on the next activation of the queue */ ++ bfqq->entity.ioprio_changed = 1; ++} ++ ++static void bfq_end_wr_async_queues(struct bfq_data *bfqd, ++ struct bfq_group *bfqg) ++{ ++ int i, j; ++ ++ for (i = 0; i < 2; i++) ++ for (j = 0; j < IOPRIO_BE_NR; j++) ++ if (bfqg->async_bfqq[i][j] != NULL) ++ bfq_bfqq_end_wr(bfqg->async_bfqq[i][j]); ++ if (bfqg->async_idle_bfqq != NULL) ++ bfq_bfqq_end_wr(bfqg->async_idle_bfqq); ++} ++ ++static void bfq_end_wr(struct bfq_data *bfqd) ++{ ++ struct bfq_queue *bfqq; ++ ++ spin_lock_irq(bfqd->queue->queue_lock); ++ ++ list_for_each_entry(bfqq, &bfqd->active_list, bfqq_list) ++ bfq_bfqq_end_wr(bfqq); ++ list_for_each_entry(bfqq, &bfqd->idle_list, bfqq_list) ++ bfq_bfqq_end_wr(bfqq); ++ bfq_end_wr_async(bfqd); ++ ++ spin_unlock_irq(bfqd->queue->queue_lock); ++} ++ ++static int bfq_allow_merge(struct request_queue *q, struct request *rq, ++ struct bio *bio) ++{ ++ struct bfq_data *bfqd = q->elevator->elevator_data; ++ struct bfq_io_cq *bic; ++ struct bfq_queue *bfqq; ++ ++ /* ++ * Disallow merge of a sync bio into an async request. ++ */ ++ if (bfq_bio_sync(bio) && !rq_is_sync(rq)) ++ return 0; ++ ++ /* ++ * Lookup the bfqq that this bio will be queued with. Allow ++ * merge only if rq is queued there. ++ * Queue lock is held here. ++ */ ++ bic = bfq_bic_lookup(bfqd, current->io_context); ++ if (bic == NULL) ++ return 0; ++ ++ bfqq = bic_to_bfqq(bic, bfq_bio_sync(bio)); ++ return bfqq == RQ_BFQQ(rq); ++} ++ ++static void __bfq_set_in_service_queue(struct bfq_data *bfqd, ++ struct bfq_queue *bfqq) ++{ ++ if (bfqq != NULL) { ++ bfq_mark_bfqq_must_alloc(bfqq); ++ bfq_mark_bfqq_budget_new(bfqq); ++ bfq_clear_bfqq_fifo_expire(bfqq); ++ ++ bfqd->budgets_assigned = (bfqd->budgets_assigned*7 + 256) / 8; ++ ++ bfq_log_bfqq(bfqd, bfqq, ++ "set_in_service_queue, cur-budget = %lu", ++ bfqq->entity.budget); ++ } ++ ++ bfqd->in_service_queue = bfqq; ++} ++ ++/* ++ * Get and set a new queue for service. ++ */ ++static struct bfq_queue *bfq_set_in_service_queue(struct bfq_data *bfqd, ++ struct bfq_queue *bfqq) ++{ ++ if (!bfqq) ++ bfqq = bfq_get_next_queue(bfqd); ++ else ++ bfq_get_next_queue_forced(bfqd, bfqq); ++ ++ __bfq_set_in_service_queue(bfqd, bfqq); ++ return bfqq; ++} ++ ++static inline sector_t bfq_dist_from_last(struct bfq_data *bfqd, ++ struct request *rq) ++{ ++ if (blk_rq_pos(rq) >= bfqd->last_position) ++ return blk_rq_pos(rq) - bfqd->last_position; ++ else ++ return bfqd->last_position - blk_rq_pos(rq); ++} ++ ++/* ++ * Return true if bfqq has no request pending and rq is close enough to ++ * bfqd->last_position, or if rq is closer to bfqd->last_position than ++ * bfqq->next_rq ++ */ ++static inline int bfq_rq_close(struct bfq_data *bfqd, struct request *rq) ++{ ++ return bfq_dist_from_last(bfqd, rq) <= BFQQ_SEEK_THR; ++} ++ ++static struct bfq_queue *bfqq_close(struct bfq_data *bfqd) ++{ ++ struct rb_root *root = &bfqd->rq_pos_tree; ++ struct rb_node *parent, *node; ++ struct bfq_queue *__bfqq; ++ sector_t sector = bfqd->last_position; ++ ++ if (RB_EMPTY_ROOT(root)) ++ return NULL; ++ ++ /* ++ * First, if we find a request starting at the end of the last ++ * request, choose it. ++ */ ++ __bfqq = bfq_rq_pos_tree_lookup(bfqd, root, sector, &parent, NULL); ++ if (__bfqq != NULL) ++ return __bfqq; ++ ++ /* ++ * If the exact sector wasn't found, the parent of the NULL leaf ++ * will contain the closest sector (rq_pos_tree sorted by ++ * next_request position). ++ */ ++ __bfqq = rb_entry(parent, struct bfq_queue, pos_node); ++ if (bfq_rq_close(bfqd, __bfqq->next_rq)) ++ return __bfqq; ++ ++ if (blk_rq_pos(__bfqq->next_rq) < sector) ++ node = rb_next(&__bfqq->pos_node); ++ else ++ node = rb_prev(&__bfqq->pos_node); ++ if (node == NULL) ++ return NULL; ++ ++ __bfqq = rb_entry(node, struct bfq_queue, pos_node); ++ if (bfq_rq_close(bfqd, __bfqq->next_rq)) ++ return __bfqq; ++ ++ return NULL; ++} ++ ++/* ++ * bfqd - obvious ++ * cur_bfqq - passed in so that we don't decide that the current queue ++ * is closely cooperating with itself. ++ * ++ * We are assuming that cur_bfqq has dispatched at least one request, ++ * and that bfqd->last_position reflects a position on the disk associated ++ * with the I/O issued by cur_bfqq. ++ */ ++static struct bfq_queue *bfq_close_cooperator(struct bfq_data *bfqd, ++ struct bfq_queue *cur_bfqq) ++{ ++ struct bfq_queue *bfqq; ++ ++ if (bfq_class_idle(cur_bfqq)) ++ return NULL; ++ if (!bfq_bfqq_sync(cur_bfqq)) ++ return NULL; ++ if (BFQQ_SEEKY(cur_bfqq)) ++ return NULL; ++ ++ /* If device has only one backlogged bfq_queue, don't search. */ ++ if (bfqd->busy_queues == 1) ++ return NULL; ++ ++ /* ++ * We should notice if some of the queues are cooperating, e.g. ++ * working closely on the same area of the disk. In that case, ++ * we can group them together and don't waste time idling. ++ */ ++ bfqq = bfqq_close(bfqd); ++ if (bfqq == NULL || bfqq == cur_bfqq) ++ return NULL; ++ ++ /* ++ * Do not merge queues from different bfq_groups. ++ */ ++ if (bfqq->entity.parent != cur_bfqq->entity.parent) ++ return NULL; ++ ++ /* ++ * It only makes sense to merge sync queues. ++ */ ++ if (!bfq_bfqq_sync(bfqq)) ++ return NULL; ++ if (BFQQ_SEEKY(bfqq)) ++ return NULL; ++ ++ /* ++ * Do not merge queues of different priority classes. ++ */ ++ if (bfq_class_rt(bfqq) != bfq_class_rt(cur_bfqq)) ++ return NULL; ++ ++ return bfqq; ++} ++ ++/* ++ * If enough samples have been computed, return the current max budget ++ * stored in bfqd, which is dynamically updated according to the ++ * estimated disk peak rate; otherwise return the default max budget ++ */ ++static inline unsigned long bfq_max_budget(struct bfq_data *bfqd) ++{ ++ if (bfqd->budgets_assigned < 194) ++ return bfq_default_max_budget; ++ else ++ return bfqd->bfq_max_budget; ++} ++ ++/* ++ * Return min budget, which is a fraction of the current or default ++ * max budget (trying with 1/32) ++ */ ++static inline unsigned long bfq_min_budget(struct bfq_data *bfqd) ++{ ++ if (bfqd->budgets_assigned < 194) ++ return bfq_default_max_budget / 32; ++ else ++ return bfqd->bfq_max_budget / 32; ++} ++ ++static void bfq_arm_slice_timer(struct bfq_data *bfqd) ++{ ++ struct bfq_queue *bfqq = bfqd->in_service_queue; ++ struct bfq_io_cq *bic; ++ unsigned long sl; ++ ++ BUG_ON(!RB_EMPTY_ROOT(&bfqq->sort_list)); ++ ++ /* Processes have exited, don't wait. */ ++ bic = bfqd->in_service_bic; ++ if (bic == NULL || atomic_read(&bic->icq.ioc->active_ref) == 0) ++ return; ++ ++ bfq_mark_bfqq_wait_request(bfqq); ++ ++ /* ++ * We don't want to idle for seeks, but we do want to allow ++ * fair distribution of slice time for a process doing back-to-back ++ * seeks. So allow a little bit of time for him to submit a new rq. ++ * ++ * To prevent processes with (partly) seeky workloads from ++ * being too ill-treated, grant them a small fraction of the ++ * assigned budget before reducing the waiting time to ++ * BFQ_MIN_TT. This happened to help reduce latency. ++ */ ++ sl = bfqd->bfq_slice_idle; ++ /* ++ * Unless the queue is being weight-raised, grant only minimum idle ++ * time if the queue either has been seeky for long enough or has ++ * already proved to be constantly seeky. ++ */ ++ if (bfq_sample_valid(bfqq->seek_samples) && ++ ((BFQQ_SEEKY(bfqq) && bfqq->entity.service > ++ bfq_max_budget(bfqq->bfqd) / 8) || ++ bfq_bfqq_constantly_seeky(bfqq)) && bfqq->wr_coeff == 1) ++ sl = min(sl, msecs_to_jiffies(BFQ_MIN_TT)); ++ else if (bfqq->wr_coeff > 1) ++ sl = sl * 3; ++ bfqd->last_idling_start = ktime_get(); ++ mod_timer(&bfqd->idle_slice_timer, jiffies + sl); ++ bfq_log(bfqd, "arm idle: %u/%u ms", ++ jiffies_to_msecs(sl), jiffies_to_msecs(bfqd->bfq_slice_idle)); ++} ++ ++/* ++ * Set the maximum time for the in-service queue to consume its ++ * budget. This prevents seeky processes from lowering the disk ++ * throughput (always guaranteed with a time slice scheme as in CFQ). ++ */ ++static void bfq_set_budget_timeout(struct bfq_data *bfqd) ++{ ++ struct bfq_queue *bfqq = bfqd->in_service_queue; ++ unsigned int timeout_coeff; ++ if (bfqq->wr_cur_max_time == bfqd->bfq_wr_rt_max_time) ++ timeout_coeff = 1; ++ else ++ timeout_coeff = bfqq->entity.weight / bfqq->entity.orig_weight; ++ ++ bfqd->last_budget_start = ktime_get(); ++ ++ bfq_clear_bfqq_budget_new(bfqq); ++ bfqq->budget_timeout = jiffies + ++ bfqd->bfq_timeout[bfq_bfqq_sync(bfqq)] * timeout_coeff; ++ ++ bfq_log_bfqq(bfqd, bfqq, "set budget_timeout %u", ++ jiffies_to_msecs(bfqd->bfq_timeout[bfq_bfqq_sync(bfqq)] * ++ timeout_coeff)); ++} ++ ++/* ++ * Move request from internal lists to the request queue dispatch list. ++ */ ++static void bfq_dispatch_insert(struct request_queue *q, struct request *rq) ++{ ++ struct bfq_data *bfqd = q->elevator->elevator_data; ++ struct bfq_queue *bfqq = RQ_BFQQ(rq); ++ ++ /* ++ * For consistency, the next instruction should have been executed ++ * after removing the request from the queue and dispatching it. ++ * We execute instead this instruction before bfq_remove_request() ++ * (and hence introduce a temporary inconsistency), for efficiency. ++ * In fact, in a forced_dispatch, this prevents two counters related ++ * to bfqq->dispatched to risk to be uselessly decremented if bfqq ++ * is not in service, and then to be incremented again after ++ * incrementing bfqq->dispatched. ++ */ ++ bfqq->dispatched++; ++ bfq_remove_request(rq); ++ elv_dispatch_sort(q, rq); ++ ++ if (bfq_bfqq_sync(bfqq)) ++ bfqd->sync_flight++; ++} ++ ++/* ++ * Return expired entry, or NULL to just start from scratch in rbtree. ++ */ ++static struct request *bfq_check_fifo(struct bfq_queue *bfqq) ++{ ++ struct request *rq = NULL; ++ ++ if (bfq_bfqq_fifo_expire(bfqq)) ++ return NULL; ++ ++ bfq_mark_bfqq_fifo_expire(bfqq); ++ ++ if (list_empty(&bfqq->fifo)) ++ return NULL; ++ ++ rq = rq_entry_fifo(bfqq->fifo.next); ++ ++ if (time_before(jiffies, rq->fifo_time)) ++ return NULL; ++ ++ return rq; ++} ++ ++/* Must be called with the queue_lock held. */ ++static int bfqq_process_refs(struct bfq_queue *bfqq) ++{ ++ int process_refs, io_refs; ++ ++ io_refs = bfqq->allocated[READ] + bfqq->allocated[WRITE]; ++ process_refs = atomic_read(&bfqq->ref) - io_refs - bfqq->entity.on_st; ++ BUG_ON(process_refs < 0); ++ return process_refs; ++} ++ ++static void bfq_setup_merge(struct bfq_queue *bfqq, struct bfq_queue *new_bfqq) ++{ ++ int process_refs, new_process_refs; ++ struct bfq_queue *__bfqq; ++ ++ /* ++ * If there are no process references on the new_bfqq, then it is ++ * unsafe to follow the ->new_bfqq chain as other bfqq's in the chain ++ * may have dropped their last reference (not just their last process ++ * reference). ++ */ ++ if (!bfqq_process_refs(new_bfqq)) ++ return; ++ ++ /* Avoid a circular list and skip interim queue merges. */ ++ while ((__bfqq = new_bfqq->new_bfqq)) { ++ if (__bfqq == bfqq) ++ return; ++ new_bfqq = __bfqq; ++ } ++ ++ process_refs = bfqq_process_refs(bfqq); ++ new_process_refs = bfqq_process_refs(new_bfqq); ++ /* ++ * If the process for the bfqq has gone away, there is no ++ * sense in merging the queues. ++ */ ++ if (process_refs == 0 || new_process_refs == 0) ++ return; ++ ++ /* ++ * Merge in the direction of the lesser amount of work. ++ */ ++ if (new_process_refs >= process_refs) { ++ bfqq->new_bfqq = new_bfqq; ++ atomic_add(process_refs, &new_bfqq->ref); ++ } else { ++ new_bfqq->new_bfqq = bfqq; ++ atomic_add(new_process_refs, &bfqq->ref); ++ } ++ bfq_log_bfqq(bfqq->bfqd, bfqq, "scheduling merge with queue %d", ++ new_bfqq->pid); ++} ++ ++static inline unsigned long bfq_bfqq_budget_left(struct bfq_queue *bfqq) ++{ ++ struct bfq_entity *entity = &bfqq->entity; ++ return entity->budget - entity->service; ++} ++ ++static void __bfq_bfqq_expire(struct bfq_data *bfqd, struct bfq_queue *bfqq) ++{ ++ BUG_ON(bfqq != bfqd->in_service_queue); ++ ++ __bfq_bfqd_reset_in_service(bfqd); ++ ++ /* ++ * If this bfqq is shared between multiple processes, check ++ * to make sure that those processes are still issuing I/Os ++ * within the mean seek distance. If not, it may be time to ++ * break the queues apart again. ++ */ ++ if (bfq_bfqq_coop(bfqq) && BFQQ_SEEKY(bfqq)) ++ bfq_mark_bfqq_split_coop(bfqq); ++ ++ if (RB_EMPTY_ROOT(&bfqq->sort_list)) { ++ /* ++ * Overloading budget_timeout field to store the time ++ * at which the queue remains with no backlog; used by ++ * the weight-raising mechanism. ++ */ ++ bfqq->budget_timeout = jiffies; ++ bfq_del_bfqq_busy(bfqd, bfqq, 1); ++ } else { ++ bfq_activate_bfqq(bfqd, bfqq); ++ /* ++ * Resort priority tree of potential close cooperators. ++ */ ++ bfq_rq_pos_tree_add(bfqd, bfqq); ++ } ++} ++ ++/** ++ * __bfq_bfqq_recalc_budget - try to adapt the budget to the @bfqq behavior. ++ * @bfqd: device data. ++ * @bfqq: queue to update. ++ * @reason: reason for expiration. ++ * ++ * Handle the feedback on @bfqq budget. See the body for detailed ++ * comments. ++ */ ++static void __bfq_bfqq_recalc_budget(struct bfq_data *bfqd, ++ struct bfq_queue *bfqq, ++ enum bfqq_expiration reason) ++{ ++ struct request *next_rq; ++ unsigned long budget, min_budget; ++ ++ budget = bfqq->max_budget; ++ min_budget = bfq_min_budget(bfqd); ++ ++ BUG_ON(bfqq != bfqd->in_service_queue); ++ ++ bfq_log_bfqq(bfqd, bfqq, "recalc_budg: last budg %lu, budg left %lu", ++ bfqq->entity.budget, bfq_bfqq_budget_left(bfqq)); ++ bfq_log_bfqq(bfqd, bfqq, "recalc_budg: last max_budg %lu, min budg %lu", ++ budget, bfq_min_budget(bfqd)); ++ bfq_log_bfqq(bfqd, bfqq, "recalc_budg: sync %d, seeky %d", ++ bfq_bfqq_sync(bfqq), BFQQ_SEEKY(bfqd->in_service_queue)); ++ ++ if (bfq_bfqq_sync(bfqq)) { ++ switch (reason) { ++ /* ++ * Caveat: in all the following cases we trade latency ++ * for throughput. ++ */ ++ case BFQ_BFQQ_TOO_IDLE: ++ /* ++ * This is the only case where we may reduce ++ * the budget: if there is no request of the ++ * process still waiting for completion, then ++ * we assume (tentatively) that the timer has ++ * expired because the batch of requests of ++ * the process could have been served with a ++ * smaller budget. Hence, betting that ++ * process will behave in the same way when it ++ * becomes backlogged again, we reduce its ++ * next budget. As long as we guess right, ++ * this budget cut reduces the latency ++ * experienced by the process. ++ * ++ * However, if there are still outstanding ++ * requests, then the process may have not yet ++ * issued its next request just because it is ++ * still waiting for the completion of some of ++ * the still outstanding ones. So in this ++ * subcase we do not reduce its budget, on the ++ * contrary we increase it to possibly boost ++ * the throughput, as discussed in the ++ * comments to the BUDGET_TIMEOUT case. ++ */ ++ if (bfqq->dispatched > 0) /* still outstanding reqs */ ++ budget = min(budget * 2, bfqd->bfq_max_budget); ++ else { ++ if (budget > 5 * min_budget) ++ budget -= 4 * min_budget; ++ else ++ budget = min_budget; ++ } ++ break; ++ case BFQ_BFQQ_BUDGET_TIMEOUT: ++ /* ++ * We double the budget here because: 1) it ++ * gives the chance to boost the throughput if ++ * this is not a seeky process (which may have ++ * bumped into this timeout because of, e.g., ++ * ZBR), 2) together with charge_full_budget ++ * it helps give seeky processes higher ++ * timestamps, and hence be served less ++ * frequently. ++ */ ++ budget = min(budget * 2, bfqd->bfq_max_budget); ++ break; ++ case BFQ_BFQQ_BUDGET_EXHAUSTED: ++ /* ++ * The process still has backlog, and did not ++ * let either the budget timeout or the disk ++ * idling timeout expire. Hence it is not ++ * seeky, has a short thinktime and may be ++ * happy with a higher budget too. So ++ * definitely increase the budget of this good ++ * candidate to boost the disk throughput. ++ */ ++ budget = min(budget * 4, bfqd->bfq_max_budget); ++ break; ++ case BFQ_BFQQ_NO_MORE_REQUESTS: ++ /* ++ * Leave the budget unchanged. ++ */ ++ default: ++ return; ++ } ++ } else /* async queue */ ++ /* async queues get always the maximum possible budget ++ * (their ability to dispatch is limited by ++ * @bfqd->bfq_max_budget_async_rq). ++ */ ++ budget = bfqd->bfq_max_budget; ++ ++ bfqq->max_budget = budget; ++ ++ if (bfqd->budgets_assigned >= 194 && bfqd->bfq_user_max_budget == 0 && ++ bfqq->max_budget > bfqd->bfq_max_budget) ++ bfqq->max_budget = bfqd->bfq_max_budget; ++ ++ /* ++ * Make sure that we have enough budget for the next request. ++ * Since the finish time of the bfqq must be kept in sync with ++ * the budget, be sure to call __bfq_bfqq_expire() after the ++ * update. ++ */ ++ next_rq = bfqq->next_rq; ++ if (next_rq != NULL) ++ bfqq->entity.budget = max_t(unsigned long, bfqq->max_budget, ++ bfq_serv_to_charge(next_rq, bfqq)); ++ else ++ bfqq->entity.budget = bfqq->max_budget; ++ ++ bfq_log_bfqq(bfqd, bfqq, "head sect: %u, new budget %lu", ++ next_rq != NULL ? blk_rq_sectors(next_rq) : 0, ++ bfqq->entity.budget); ++} ++ ++static unsigned long bfq_calc_max_budget(u64 peak_rate, u64 timeout) ++{ ++ unsigned long max_budget; ++ ++ /* ++ * The max_budget calculated when autotuning is equal to the ++ * amount of sectors transfered in timeout_sync at the ++ * estimated peak rate. ++ */ ++ max_budget = (unsigned long)(peak_rate * 1000 * ++ timeout >> BFQ_RATE_SHIFT); ++ ++ return max_budget; ++} ++ ++/* ++ * In addition to updating the peak rate, checks whether the process ++ * is "slow", and returns 1 if so. This slow flag is used, in addition ++ * to the budget timeout, to reduce the amount of service provided to ++ * seeky processes, and hence reduce their chances to lower the ++ * throughput. See the code for more details. ++ */ ++static int bfq_update_peak_rate(struct bfq_data *bfqd, struct bfq_queue *bfqq, ++ int compensate, enum bfqq_expiration reason) ++{ ++ u64 bw, usecs, expected, timeout; ++ ktime_t delta; ++ int update = 0; ++ ++ if (!bfq_bfqq_sync(bfqq) || bfq_bfqq_budget_new(bfqq)) ++ return 0; ++ ++ if (compensate) ++ delta = bfqd->last_idling_start; ++ else ++ delta = ktime_get(); ++ delta = ktime_sub(delta, bfqd->last_budget_start); ++ usecs = ktime_to_us(delta); ++ ++ /* Don't trust short/unrealistic values. */ ++ if (usecs < 100 || usecs >= LONG_MAX) ++ return 0; ++ ++ /* ++ * Calculate the bandwidth for the last slice. We use a 64 bit ++ * value to store the peak rate, in sectors per usec in fixed ++ * point math. We do so to have enough precision in the estimate ++ * and to avoid overflows. ++ */ ++ bw = (u64)bfqq->entity.service << BFQ_RATE_SHIFT; ++ do_div(bw, (unsigned long)usecs); ++ ++ timeout = jiffies_to_msecs(bfqd->bfq_timeout[BLK_RW_SYNC]); ++ ++ /* ++ * Use only long (> 20ms) intervals to filter out spikes for ++ * the peak rate estimation. ++ */ ++ if (usecs > 20000) { ++ if (bw > bfqd->peak_rate || ++ (!BFQQ_SEEKY(bfqq) && ++ reason == BFQ_BFQQ_BUDGET_TIMEOUT)) { ++ bfq_log(bfqd, "measured bw =%llu", bw); ++ /* ++ * To smooth oscillations use a low-pass filter with ++ * alpha=7/8, i.e., ++ * new_rate = (7/8) * old_rate + (1/8) * bw ++ */ ++ do_div(bw, 8); ++ if (bw == 0) ++ return 0; ++ bfqd->peak_rate *= 7; ++ do_div(bfqd->peak_rate, 8); ++ bfqd->peak_rate += bw; ++ update = 1; ++ bfq_log(bfqd, "new peak_rate=%llu", bfqd->peak_rate); ++ } ++ ++ update |= bfqd->peak_rate_samples == BFQ_PEAK_RATE_SAMPLES - 1; ++ ++ if (bfqd->peak_rate_samples < BFQ_PEAK_RATE_SAMPLES) ++ bfqd->peak_rate_samples++; ++ ++ if (bfqd->peak_rate_samples == BFQ_PEAK_RATE_SAMPLES && ++ update) { ++ int dev_type = blk_queue_nonrot(bfqd->queue); ++ if (bfqd->bfq_user_max_budget == 0) { ++ bfqd->bfq_max_budget = ++ bfq_calc_max_budget(bfqd->peak_rate, ++ timeout); ++ bfq_log(bfqd, "new max_budget=%lu", ++ bfqd->bfq_max_budget); ++ } ++ if (bfqd->device_speed == BFQ_BFQD_FAST && ++ bfqd->peak_rate < device_speed_thresh[dev_type]) { ++ bfqd->device_speed = BFQ_BFQD_SLOW; ++ bfqd->RT_prod = R_slow[dev_type] * ++ T_slow[dev_type]; ++ } else if (bfqd->device_speed == BFQ_BFQD_SLOW && ++ bfqd->peak_rate > device_speed_thresh[dev_type]) { ++ bfqd->device_speed = BFQ_BFQD_FAST; ++ bfqd->RT_prod = R_fast[dev_type] * ++ T_fast[dev_type]; ++ } ++ } ++ } ++ ++ /* ++ * If the process has been served for a too short time ++ * interval to let its possible sequential accesses prevail on ++ * the initial seek time needed to move the disk head on the ++ * first sector it requested, then give the process a chance ++ * and for the moment return false. ++ */ ++ if (bfqq->entity.budget <= bfq_max_budget(bfqd) / 8) ++ return 0; ++ ++ /* ++ * A process is considered ``slow'' (i.e., seeky, so that we ++ * cannot treat it fairly in the service domain, as it would ++ * slow down too much the other processes) if, when a slice ++ * ends for whatever reason, it has received service at a ++ * rate that would not be high enough to complete the budget ++ * before the budget timeout expiration. ++ */ ++ expected = bw * 1000 * timeout >> BFQ_RATE_SHIFT; ++ ++ /* ++ * Caveat: processes doing IO in the slower disk zones will ++ * tend to be slow(er) even if not seeky. And the estimated ++ * peak rate will actually be an average over the disk ++ * surface. Hence, to not be too harsh with unlucky processes, ++ * we keep a budget/3 margin of safety before declaring a ++ * process slow. ++ */ ++ return expected > (4 * bfqq->entity.budget) / 3; ++} ++ ++/* ++ * To be deemed as soft real-time, an application must meet two ++ * requirements. First, the application must not require an average ++ * bandwidth higher than the approximate bandwidth required to playback or ++ * record a compressed high-definition video. ++ * The next function is invoked on the completion of the last request of a ++ * batch, to compute the next-start time instant, soft_rt_next_start, such ++ * that, if the next request of the application does not arrive before ++ * soft_rt_next_start, then the above requirement on the bandwidth is met. ++ * ++ * The second requirement is that the request pattern of the application is ++ * isochronous, i.e., that, after issuing a request or a batch of requests, ++ * the application stops issuing new requests until all its pending requests ++ * have been completed. After that, the application may issue a new batch, ++ * and so on. ++ * For this reason the next function is invoked to compute ++ * soft_rt_next_start only for applications that meet this requirement, ++ * whereas soft_rt_next_start is set to infinity for applications that do ++ * not. ++ * ++ * Unfortunately, even a greedy application may happen to behave in an ++ * isochronous way if the CPU load is high. In fact, the application may ++ * stop issuing requests while the CPUs are busy serving other processes, ++ * then restart, then stop again for a while, and so on. In addition, if ++ * the disk achieves a low enough throughput with the request pattern ++ * issued by the application (e.g., because the request pattern is random ++ * and/or the device is slow), then the application may meet the above ++ * bandwidth requirement too. To prevent such a greedy application to be ++ * deemed as soft real-time, a further rule is used in the computation of ++ * soft_rt_next_start: soft_rt_next_start must be higher than the current ++ * time plus the maximum time for which the arrival of a request is waited ++ * for when a sync queue becomes idle, namely bfqd->bfq_slice_idle. ++ * This filters out greedy applications, as the latter issue instead their ++ * next request as soon as possible after the last one has been completed ++ * (in contrast, when a batch of requests is completed, a soft real-time ++ * application spends some time processing data). ++ * ++ * Unfortunately, the last filter may easily generate false positives if ++ * only bfqd->bfq_slice_idle is used as a reference time interval and one ++ * or both the following cases occur: ++ * 1) HZ is so low that the duration of a jiffy is comparable to or higher ++ * than bfqd->bfq_slice_idle. This happens, e.g., on slow devices with ++ * HZ=100. ++ * 2) jiffies, instead of increasing at a constant rate, may stop increasing ++ * for a while, then suddenly 'jump' by several units to recover the lost ++ * increments. This seems to happen, e.g., inside virtual machines. ++ * To address this issue, we do not use as a reference time interval just ++ * bfqd->bfq_slice_idle, but bfqd->bfq_slice_idle plus a few jiffies. In ++ * particular we add the minimum number of jiffies for which the filter ++ * seems to be quite precise also in embedded systems and KVM/QEMU virtual ++ * machines. ++ */ ++static inline unsigned long bfq_bfqq_softrt_next_start(struct bfq_data *bfqd, ++ struct bfq_queue *bfqq) ++{ ++ return max(bfqq->last_idle_bklogged + ++ HZ * bfqq->service_from_backlogged / ++ bfqd->bfq_wr_max_softrt_rate, ++ jiffies + bfqq->bfqd->bfq_slice_idle + 4); ++} ++ ++/* ++ * Return the largest-possible time instant such that, for as long as possible, ++ * the current time will be lower than this time instant according to the macro ++ * time_is_before_jiffies(). ++ */ ++static inline unsigned long bfq_infinity_from_now(unsigned long now) ++{ ++ return now + ULONG_MAX / 2; ++} ++ ++/** ++ * bfq_bfqq_expire - expire a queue. ++ * @bfqd: device owning the queue. ++ * @bfqq: the queue to expire. ++ * @compensate: if true, compensate for the time spent idling. ++ * @reason: the reason causing the expiration. ++ * ++ * ++ * If the process associated to the queue is slow (i.e., seeky), or in ++ * case of budget timeout, or, finally, if it is async, we ++ * artificially charge it an entire budget (independently of the ++ * actual service it received). As a consequence, the queue will get ++ * higher timestamps than the correct ones upon reactivation, and ++ * hence it will be rescheduled as if it had received more service ++ * than what it actually received. In the end, this class of processes ++ * will receive less service in proportion to how slowly they consume ++ * their budgets (and hence how seriously they tend to lower the ++ * throughput). ++ * ++ * In contrast, when a queue expires because it has been idling for ++ * too much or because it exhausted its budget, we do not touch the ++ * amount of service it has received. Hence when the queue will be ++ * reactivated and its timestamps updated, the latter will be in sync ++ * with the actual service received by the queue until expiration. ++ * ++ * Charging a full budget to the first type of queues and the exact ++ * service to the others has the effect of using the WF2Q+ policy to ++ * schedule the former on a timeslice basis, without violating the ++ * service domain guarantees of the latter. ++ */ ++static void bfq_bfqq_expire(struct bfq_data *bfqd, ++ struct bfq_queue *bfqq, ++ int compensate, ++ enum bfqq_expiration reason) ++{ ++ int slow; ++ BUG_ON(bfqq != bfqd->in_service_queue); ++ ++ /* Update disk peak rate for autotuning and check whether the ++ * process is slow (see bfq_update_peak_rate). ++ */ ++ slow = bfq_update_peak_rate(bfqd, bfqq, compensate, reason); ++ ++ /* ++ * As above explained, 'punish' slow (i.e., seeky), timed-out ++ * and async queues, to favor sequential sync workloads. ++ * ++ * Processes doing I/O in the slower disk zones will tend to be ++ * slow(er) even if not seeky. Hence, since the estimated peak ++ * rate is actually an average over the disk surface, these ++ * processes may timeout just for bad luck. To avoid punishing ++ * them we do not charge a full budget to a process that ++ * succeeded in consuming at least 2/3 of its budget. ++ */ ++ if (slow || (reason == BFQ_BFQQ_BUDGET_TIMEOUT && ++ bfq_bfqq_budget_left(bfqq) >= bfqq->entity.budget / 3)) ++ bfq_bfqq_charge_full_budget(bfqq); ++ ++ bfqq->service_from_backlogged += bfqq->entity.service; ++ ++ if (BFQQ_SEEKY(bfqq) && reason == BFQ_BFQQ_BUDGET_TIMEOUT && ++ !bfq_bfqq_constantly_seeky(bfqq)) { ++ bfq_mark_bfqq_constantly_seeky(bfqq); ++ if (!blk_queue_nonrot(bfqd->queue)) ++ bfqd->const_seeky_busy_in_flight_queues++; ++ } ++ ++ if (reason == BFQ_BFQQ_TOO_IDLE && ++ bfqq->entity.service <= 2 * bfqq->entity.budget / 10 ) ++ bfq_clear_bfqq_IO_bound(bfqq); ++ ++ if (bfqd->low_latency && bfqq->wr_coeff == 1) ++ bfqq->last_wr_start_finish = jiffies; ++ ++ if (bfqd->low_latency && bfqd->bfq_wr_max_softrt_rate > 0 && ++ RB_EMPTY_ROOT(&bfqq->sort_list)) { ++ /* ++ * If we get here, and there are no outstanding requests, ++ * then the request pattern is isochronous (see the comments ++ * to the function bfq_bfqq_softrt_next_start()). Hence we ++ * can compute soft_rt_next_start. If, instead, the queue ++ * still has outstanding requests, then we have to wait ++ * for the completion of all the outstanding requests to ++ * discover whether the request pattern is actually ++ * isochronous. ++ */ ++ if (bfqq->dispatched == 0) ++ bfqq->soft_rt_next_start = ++ bfq_bfqq_softrt_next_start(bfqd, bfqq); ++ else { ++ /* ++ * The application is still waiting for the ++ * completion of one or more requests: ++ * prevent it from possibly being incorrectly ++ * deemed as soft real-time by setting its ++ * soft_rt_next_start to infinity. In fact, ++ * without this assignment, the application ++ * would be incorrectly deemed as soft ++ * real-time if: ++ * 1) it issued a new request before the ++ * completion of all its in-flight ++ * requests, and ++ * 2) at that time, its soft_rt_next_start ++ * happened to be in the past. ++ */ ++ bfqq->soft_rt_next_start = ++ bfq_infinity_from_now(jiffies); ++ /* ++ * Schedule an update of soft_rt_next_start to when ++ * the task may be discovered to be isochronous. ++ */ ++ bfq_mark_bfqq_softrt_update(bfqq); ++ } ++ } ++ ++ bfq_log_bfqq(bfqd, bfqq, ++ "expire (%d, slow %d, num_disp %d, idle_win %d)", reason, ++ slow, bfqq->dispatched, bfq_bfqq_idle_window(bfqq)); ++ ++ /* ++ * Increase, decrease or leave budget unchanged according to ++ * reason. ++ */ ++ __bfq_bfqq_recalc_budget(bfqd, bfqq, reason); ++ __bfq_bfqq_expire(bfqd, bfqq); ++} ++ ++/* ++ * Budget timeout is not implemented through a dedicated timer, but ++ * just checked on request arrivals and completions, as well as on ++ * idle timer expirations. ++ */ ++static int bfq_bfqq_budget_timeout(struct bfq_queue *bfqq) ++{ ++ if (bfq_bfqq_budget_new(bfqq) || ++ time_before(jiffies, bfqq->budget_timeout)) ++ return 0; ++ return 1; ++} ++ ++/* ++ * If we expire a queue that is waiting for the arrival of a new ++ * request, we may prevent the fictitious timestamp back-shifting that ++ * allows the guarantees of the queue to be preserved (see [1] for ++ * this tricky aspect). Hence we return true only if this condition ++ * does not hold, or if the queue is slow enough to deserve only to be ++ * kicked off for preserving a high throughput. ++*/ ++static inline int bfq_may_expire_for_budg_timeout(struct bfq_queue *bfqq) ++{ ++ bfq_log_bfqq(bfqq->bfqd, bfqq, ++ "may_budget_timeout: wait_request %d left %d timeout %d", ++ bfq_bfqq_wait_request(bfqq), ++ bfq_bfqq_budget_left(bfqq) >= bfqq->entity.budget / 3, ++ bfq_bfqq_budget_timeout(bfqq)); ++ ++ return (!bfq_bfqq_wait_request(bfqq) || ++ bfq_bfqq_budget_left(bfqq) >= bfqq->entity.budget / 3) ++ && ++ bfq_bfqq_budget_timeout(bfqq); ++} ++ ++/* ++ * Device idling is allowed only for the queues for which this function ++ * returns true. For this reason, the return value of this function plays a ++ * critical role for both throughput boosting and service guarantees. The ++ * return value is computed through a logical expression. In this rather ++ * long comment, we try to briefly describe all the details and motivations ++ * behind the components of this logical expression. ++ * ++ * First, the expression is false if bfqq is not sync, or if: bfqq happened ++ * to become active during a large burst of queue activations, and the ++ * pattern of requests bfqq contains boosts the throughput if bfqq is ++ * expired. In fact, queues that became active during a large burst benefit ++ * only from throughput, as discussed in the comments to bfq_handle_burst. ++ * In this respect, expiring bfqq certainly boosts the throughput on NCQ- ++ * capable flash-based devices, whereas, on rotational devices, it boosts ++ * the throughput only if bfqq contains random requests. ++ * ++ * On the opposite end, if (a) bfqq is sync, (b) the above burst-related ++ * condition does not hold, and (c) bfqq is being weight-raised, then the ++ * expression always evaluates to true, as device idling is instrumental ++ * for preserving low-latency guarantees (see [1]). If, instead, conditions ++ * (a) and (b) do hold, but (c) does not, then the expression evaluates to ++ * true only if: (1) bfqq is I/O-bound and has a non-null idle window, and ++ * (2) at least one of the following two conditions holds. ++ * The first condition is that the device is not performing NCQ, because ++ * idling the device most certainly boosts the throughput if this condition ++ * holds and bfqq is I/O-bound and has been granted a non-null idle window. ++ * The second compound condition is made of the logical AND of two components. ++ * ++ * The first component is true only if there is no weight-raised busy ++ * queue. This guarantees that the device is not idled for a sync non- ++ * weight-raised queue when there are busy weight-raised queues. The former ++ * is then expired immediately if empty. Combined with the timestamping ++ * rules of BFQ (see [1] for details), this causes sync non-weight-raised ++ * queues to get a lower number of requests served, and hence to ask for a ++ * lower number of requests from the request pool, before the busy weight- ++ * raised queues get served again. ++ * ++ * This is beneficial for the processes associated with weight-raised ++ * queues, when the request pool is saturated (e.g., in the presence of ++ * write hogs). In fact, if the processes associated with the other queues ++ * ask for requests at a lower rate, then weight-raised processes have a ++ * higher probability to get a request from the pool immediately (or at ++ * least soon) when they need one. Hence they have a higher probability to ++ * actually get a fraction of the disk throughput proportional to their ++ * high weight. This is especially true with NCQ-capable drives, which ++ * enqueue several requests in advance and further reorder internally- ++ * queued requests. ++ * ++ * In the end, mistreating non-weight-raised queues when there are busy ++ * weight-raised queues seems to mitigate starvation problems in the ++ * presence of heavy write workloads and NCQ, and hence to guarantee a ++ * higher application and system responsiveness in these hostile scenarios. ++ * ++ * If the first component of the compound condition is instead true, i.e., ++ * there is no weight-raised busy queue, then the second component of the ++ * compound condition takes into account service-guarantee and throughput ++ * issues related to NCQ (recall that the compound condition is evaluated ++ * only if the device is detected as supporting NCQ). ++ * ++ * As for service guarantees, allowing the drive to enqueue more than one ++ * request at a time, and hence delegating de facto final scheduling ++ * decisions to the drive's internal scheduler, causes loss of control on ++ * the actual request service order. In this respect, when the drive is ++ * allowed to enqueue more than one request at a time, the service ++ * distribution enforced by the drive's internal scheduler is likely to ++ * coincide with the desired device-throughput distribution only in the ++ * following, perfectly symmetric, scenario: ++ * 1) all active queues have the same weight, ++ * 2) all active groups at the same level in the groups tree have the same ++ * weight, ++ * 3) all active groups at the same level in the groups tree have the same ++ * number of children. ++ * ++ * Even in such a scenario, sequential I/O may still receive a preferential ++ * treatment, but this is not likely to be a big issue with flash-based ++ * devices, because of their non-dramatic loss of throughput with random ++ * I/O. Things do differ with HDDs, for which additional care is taken, as ++ * explained after completing the discussion for flash-based devices. ++ * ++ * Unfortunately, keeping the necessary state for evaluating exactly the ++ * above symmetry conditions would be quite complex and time-consuming. ++ * Therefore BFQ evaluates instead the following stronger sub-conditions, ++ * for which it is much easier to maintain the needed state: ++ * 1) all active queues have the same weight, ++ * 2) all active groups have the same weight, ++ * 3) all active groups have at most one active child each. ++ * In particular, the last two conditions are always true if hierarchical ++ * support and the cgroups interface are not enabled, hence no state needs ++ * to be maintained in this case. ++ * ++ * According to the above considerations, the second component of the ++ * compound condition evaluates to true if any of the above symmetry ++ * sub-condition does not hold, or the device is not flash-based. Therefore, ++ * if also the first component is true, then idling is allowed for a sync ++ * queue. These are the only sub-conditions considered if the device is ++ * flash-based, as, for such a device, it is sensible to force idling only ++ * for service-guarantee issues. In fact, as for throughput, idling ++ * NCQ-capable flash-based devices would not boost the throughput even ++ * with sequential I/O; rather it would lower the throughput in proportion ++ * to how fast the device is. In the end, (only) if all the three ++ * sub-conditions hold and the device is flash-based, the compound ++ * condition evaluates to false and therefore no idling is performed. ++ * ++ * As already said, things change with a rotational device, where idling ++ * boosts the throughput with sequential I/O (even with NCQ). Hence, for ++ * such a device the second component of the compound condition evaluates ++ * to true also if the following additional sub-condition does not hold: ++ * the queue is constantly seeky. Unfortunately, this different behavior ++ * with respect to flash-based devices causes an additional asymmetry: if ++ * some sync queues enjoy idling and some other sync queues do not, then ++ * the latter get a low share of the device throughput, simply because the ++ * former get many requests served after being set as in service, whereas ++ * the latter do not. As a consequence, to guarantee the desired throughput ++ * distribution, on HDDs the compound expression evaluates to true (and ++ * hence device idling is performed) also if the following last symmetry ++ * condition does not hold: no other queue is benefiting from idling. Also ++ * this last condition is actually replaced with a simpler-to-maintain and ++ * stronger condition: there is no busy queue which is not constantly seeky ++ * (and hence may also benefit from idling). ++ * ++ * To sum up, when all the required symmetry and throughput-boosting ++ * sub-conditions hold, the second component of the compound condition ++ * evaluates to false, and hence no idling is performed. This helps to ++ * keep the drives' internal queues full on NCQ-capable devices, and hence ++ * to boost the throughput, without causing 'almost' any loss of service ++ * guarantees. The 'almost' follows from the fact that, if the internal ++ * queue of one such device is filled while all the sub-conditions hold, ++ * but at some point in time some sub-condition stops to hold, then it may ++ * become impossible to let requests be served in the new desired order ++ * until all the requests already queued in the device have been served. ++ */ ++static inline bool bfq_bfqq_must_not_expire(struct bfq_queue *bfqq) ++{ ++ struct bfq_data *bfqd = bfqq->bfqd; ++#ifdef CONFIG_CGROUP_BFQIO ++#define symmetric_scenario (!bfqd->active_numerous_groups && \ ++ !bfq_differentiated_weights(bfqd)) ++#else ++#define symmetric_scenario (!bfq_differentiated_weights(bfqd)) ++#endif ++#define cond_for_seeky_on_ncq_hdd (bfq_bfqq_constantly_seeky(bfqq) && \ ++ bfqd->busy_in_flight_queues == \ ++ bfqd->const_seeky_busy_in_flight_queues) ++ ++#define cond_for_expiring_in_burst (bfq_bfqq_in_large_burst(bfqq) && \ ++ bfqd->hw_tag && \ ++ (blk_queue_nonrot(bfqd->queue) || \ ++ bfq_bfqq_constantly_seeky(bfqq))) ++ ++/* ++ * Condition for expiring a non-weight-raised queue (and hence not idling ++ * the device). ++ */ ++#define cond_for_expiring_non_wr (bfqd->hw_tag && \ ++ (bfqd->wr_busy_queues > 0 || \ ++ (symmetric_scenario && \ ++ (blk_queue_nonrot(bfqd->queue) || \ ++ cond_for_seeky_on_ncq_hdd)))) ++ ++ return bfq_bfqq_sync(bfqq) && ++ !cond_for_expiring_in_burst && ++ (bfqq->wr_coeff > 1 || ++ (bfq_bfqq_IO_bound(bfqq) && bfq_bfqq_idle_window(bfqq) && ++ !cond_for_expiring_non_wr) ++ ); ++} ++ ++/* ++ * If the in-service queue is empty but sync, and the function ++ * bfq_bfqq_must_not_expire returns true, then: ++ * 1) the queue must remain in service and cannot be expired, and ++ * 2) the disk must be idled to wait for the possible arrival of a new ++ * request for the queue. ++ * See the comments to the function bfq_bfqq_must_not_expire for the reasons ++ * why performing device idling is the best choice to boost the throughput ++ * and preserve service guarantees when bfq_bfqq_must_not_expire itself ++ * returns true. ++ */ ++static inline bool bfq_bfqq_must_idle(struct bfq_queue *bfqq) ++{ ++ struct bfq_data *bfqd = bfqq->bfqd; ++ ++ return RB_EMPTY_ROOT(&bfqq->sort_list) && bfqd->bfq_slice_idle != 0 && ++ bfq_bfqq_must_not_expire(bfqq); ++} ++ ++/* ++ * Select a queue for service. If we have a current queue in service, ++ * check whether to continue servicing it, or retrieve and set a new one. ++ */ ++static struct bfq_queue *bfq_select_queue(struct bfq_data *bfqd) ++{ ++ struct bfq_queue *bfqq, *new_bfqq = NULL; ++ struct request *next_rq; ++ enum bfqq_expiration reason = BFQ_BFQQ_BUDGET_TIMEOUT; ++ ++ bfqq = bfqd->in_service_queue; ++ if (bfqq == NULL) ++ goto new_queue; ++ ++ bfq_log_bfqq(bfqd, bfqq, "select_queue: already in-service queue"); ++ ++ /* ++ * If another queue has a request waiting within our mean seek ++ * distance, let it run. The expire code will check for close ++ * cooperators and put the close queue at the front of the ++ * service tree. If possible, merge the expiring queue with the ++ * new bfqq. ++ */ ++ new_bfqq = bfq_close_cooperator(bfqd, bfqq); ++ if (new_bfqq != NULL && bfqq->new_bfqq == NULL) ++ bfq_setup_merge(bfqq, new_bfqq); ++ ++ if (bfq_may_expire_for_budg_timeout(bfqq) && ++ !timer_pending(&bfqd->idle_slice_timer) && ++ !bfq_bfqq_must_idle(bfqq)) ++ goto expire; ++ ++ next_rq = bfqq->next_rq; ++ /* ++ * If bfqq has requests queued and it has enough budget left to ++ * serve them, keep the queue, otherwise expire it. ++ */ ++ if (next_rq != NULL) { ++ if (bfq_serv_to_charge(next_rq, bfqq) > ++ bfq_bfqq_budget_left(bfqq)) { ++ reason = BFQ_BFQQ_BUDGET_EXHAUSTED; ++ goto expire; ++ } else { ++ /* ++ * The idle timer may be pending because we may ++ * not disable disk idling even when a new request ++ * arrives. ++ */ ++ if (timer_pending(&bfqd->idle_slice_timer)) { ++ /* ++ * If we get here: 1) at least a new request ++ * has arrived but we have not disabled the ++ * timer because the request was too small, ++ * 2) then the block layer has unplugged ++ * the device, causing the dispatch to be ++ * invoked. ++ * ++ * Since the device is unplugged, now the ++ * requests are probably large enough to ++ * provide a reasonable throughput. ++ * So we disable idling. ++ */ ++ bfq_clear_bfqq_wait_request(bfqq); ++ del_timer(&bfqd->idle_slice_timer); ++ } ++ if (new_bfqq == NULL) ++ goto keep_queue; ++ else ++ goto expire; ++ } ++ } ++ ++ /* ++ * No requests pending. If the in-service queue still has requests ++ * in flight (possibly waiting for a completion) or is idling for a ++ * new request, then keep it. ++ */ ++ if (new_bfqq == NULL && (timer_pending(&bfqd->idle_slice_timer) || ++ (bfqq->dispatched != 0 && bfq_bfqq_must_not_expire(bfqq)))) { ++ bfqq = NULL; ++ goto keep_queue; ++ } else if (new_bfqq != NULL && timer_pending(&bfqd->idle_slice_timer)) { ++ /* ++ * Expiring the queue because there is a close cooperator, ++ * cancel timer. ++ */ ++ bfq_clear_bfqq_wait_request(bfqq); ++ del_timer(&bfqd->idle_slice_timer); ++ } ++ ++ reason = BFQ_BFQQ_NO_MORE_REQUESTS; ++expire: ++ bfq_bfqq_expire(bfqd, bfqq, 0, reason); ++new_queue: ++ bfqq = bfq_set_in_service_queue(bfqd, new_bfqq); ++ bfq_log(bfqd, "select_queue: new queue %d returned", ++ bfqq != NULL ? bfqq->pid : 0); ++keep_queue: ++ return bfqq; ++} ++ ++static void bfq_update_wr_data(struct bfq_data *bfqd, ++ struct bfq_queue *bfqq) ++{ ++ if (bfqq->wr_coeff > 1) { /* queue is being boosted */ ++ struct bfq_entity *entity = &bfqq->entity; ++ ++ bfq_log_bfqq(bfqd, bfqq, ++ "raising period dur %u/%u msec, old coeff %u, w %d(%d)", ++ jiffies_to_msecs(jiffies - ++ bfqq->last_wr_start_finish), ++ jiffies_to_msecs(bfqq->wr_cur_max_time), ++ bfqq->wr_coeff, ++ bfqq->entity.weight, bfqq->entity.orig_weight); ++ ++ BUG_ON(bfqq != bfqd->in_service_queue && entity->weight != ++ entity->orig_weight * bfqq->wr_coeff); ++ if (entity->ioprio_changed) ++ bfq_log_bfqq(bfqd, bfqq, "WARN: pending prio change"); ++ /* ++ * If the queue was activated in a burst, or ++ * too much time has elapsed from the beginning ++ * of this weight-raising, then end weight raising. ++ */ ++ if (bfq_bfqq_in_large_burst(bfqq) || ++ time_is_before_jiffies(bfqq->last_wr_start_finish + ++ bfqq->wr_cur_max_time)) { ++ bfqq->last_wr_start_finish = jiffies; ++ bfq_log_bfqq(bfqd, bfqq, ++ "wrais ending at %lu, rais_max_time %u", ++ bfqq->last_wr_start_finish, ++ jiffies_to_msecs(bfqq->wr_cur_max_time)); ++ bfq_bfqq_end_wr(bfqq); ++ __bfq_entity_update_weight_prio( ++ bfq_entity_service_tree(entity), ++ entity); ++ } ++ } ++} ++ ++/* ++ * Dispatch one request from bfqq, moving it to the request queue ++ * dispatch list. ++ */ ++static int bfq_dispatch_request(struct bfq_data *bfqd, ++ struct bfq_queue *bfqq) ++{ ++ int dispatched = 0; ++ struct request *rq; ++ unsigned long service_to_charge; ++ ++ BUG_ON(RB_EMPTY_ROOT(&bfqq->sort_list)); ++ ++ /* Follow expired path, else get first next available. */ ++ rq = bfq_check_fifo(bfqq); ++ if (rq == NULL) ++ rq = bfqq->next_rq; ++ service_to_charge = bfq_serv_to_charge(rq, bfqq); ++ ++ if (service_to_charge > bfq_bfqq_budget_left(bfqq)) { ++ /* ++ * This may happen if the next rq is chosen in fifo order ++ * instead of sector order. The budget is properly ++ * dimensioned to be always sufficient to serve the next ++ * request only if it is chosen in sector order. The reason ++ * is that it would be quite inefficient and little useful ++ * to always make sure that the budget is large enough to ++ * serve even the possible next rq in fifo order. ++ * In fact, requests are seldom served in fifo order. ++ * ++ * Expire the queue for budget exhaustion, and make sure ++ * that the next act_budget is enough to serve the next ++ * request, even if it comes from the fifo expired path. ++ */ ++ bfqq->next_rq = rq; ++ /* ++ * Since this dispatch is failed, make sure that ++ * a new one will be performed ++ */ ++ if (!bfqd->rq_in_driver) ++ bfq_schedule_dispatch(bfqd); ++ goto expire; ++ } ++ ++ /* Finally, insert request into driver dispatch list. */ ++ bfq_bfqq_served(bfqq, service_to_charge); ++ bfq_dispatch_insert(bfqd->queue, rq); ++ ++ bfq_update_wr_data(bfqd, bfqq); ++ ++ bfq_log_bfqq(bfqd, bfqq, ++ "dispatched %u sec req (%llu), budg left %lu", ++ blk_rq_sectors(rq), ++ (long long unsigned)blk_rq_pos(rq), ++ bfq_bfqq_budget_left(bfqq)); ++ ++ dispatched++; ++ ++ if (bfqd->in_service_bic == NULL) { ++ atomic_long_inc(&RQ_BIC(rq)->icq.ioc->refcount); ++ bfqd->in_service_bic = RQ_BIC(rq); ++ } ++ ++ if (bfqd->busy_queues > 1 && ((!bfq_bfqq_sync(bfqq) && ++ dispatched >= bfqd->bfq_max_budget_async_rq) || ++ bfq_class_idle(bfqq))) ++ goto expire; ++ ++ return dispatched; ++ ++expire: ++ bfq_bfqq_expire(bfqd, bfqq, 0, BFQ_BFQQ_BUDGET_EXHAUSTED); ++ return dispatched; ++} ++ ++static int __bfq_forced_dispatch_bfqq(struct bfq_queue *bfqq) ++{ ++ int dispatched = 0; ++ ++ while (bfqq->next_rq != NULL) { ++ bfq_dispatch_insert(bfqq->bfqd->queue, bfqq->next_rq); ++ dispatched++; ++ } ++ ++ BUG_ON(!list_empty(&bfqq->fifo)); ++ return dispatched; ++} ++ ++/* ++ * Drain our current requests. ++ * Used for barriers and when switching io schedulers on-the-fly. ++ */ ++static int bfq_forced_dispatch(struct bfq_data *bfqd) ++{ ++ struct bfq_queue *bfqq, *n; ++ struct bfq_service_tree *st; ++ int dispatched = 0; ++ ++ bfqq = bfqd->in_service_queue; ++ if (bfqq != NULL) ++ __bfq_bfqq_expire(bfqd, bfqq); ++ ++ /* ++ * Loop through classes, and be careful to leave the scheduler ++ * in a consistent state, as feedback mechanisms and vtime ++ * updates cannot be disabled during the process. ++ */ ++ list_for_each_entry_safe(bfqq, n, &bfqd->active_list, bfqq_list) { ++ st = bfq_entity_service_tree(&bfqq->entity); ++ ++ dispatched += __bfq_forced_dispatch_bfqq(bfqq); ++ bfqq->max_budget = bfq_max_budget(bfqd); ++ ++ bfq_forget_idle(st); ++ } ++ ++ BUG_ON(bfqd->busy_queues != 0); ++ ++ return dispatched; ++} ++ ++static int bfq_dispatch_requests(struct request_queue *q, int force) ++{ ++ struct bfq_data *bfqd = q->elevator->elevator_data; ++ struct bfq_queue *bfqq; ++ int max_dispatch; ++ ++ bfq_log(bfqd, "dispatch requests: %d busy queues", bfqd->busy_queues); ++ if (bfqd->busy_queues == 0) ++ return 0; ++ ++ if (unlikely(force)) ++ return bfq_forced_dispatch(bfqd); ++ ++ bfqq = bfq_select_queue(bfqd); ++ if (bfqq == NULL) ++ return 0; ++ ++ max_dispatch = bfqd->bfq_quantum; ++ if (bfq_class_idle(bfqq)) ++ max_dispatch = 1; ++ ++ if (!bfq_bfqq_sync(bfqq)) ++ max_dispatch = bfqd->bfq_max_budget_async_rq; ++ ++ if (bfqq->dispatched >= max_dispatch) { ++ if (bfqd->busy_queues > 1) ++ return 0; ++ if (bfqq->dispatched >= 4 * max_dispatch) ++ return 0; ++ } ++ ++ if (bfqd->sync_flight != 0 && !bfq_bfqq_sync(bfqq)) ++ return 0; ++ ++ bfq_clear_bfqq_wait_request(bfqq); ++ BUG_ON(timer_pending(&bfqd->idle_slice_timer)); ++ ++ if (!bfq_dispatch_request(bfqd, bfqq)) ++ return 0; ++ ++ bfq_log_bfqq(bfqd, bfqq, "dispatched one request of %d (max_disp %d)", ++ bfqq->pid, max_dispatch); ++ ++ return 1; ++} ++ ++/* ++ * Task holds one reference to the queue, dropped when task exits. Each rq ++ * in-flight on this queue also holds a reference, dropped when rq is freed. ++ * ++ * Queue lock must be held here. ++ */ ++static void bfq_put_queue(struct bfq_queue *bfqq) ++{ ++ struct bfq_data *bfqd = bfqq->bfqd; ++ ++ BUG_ON(atomic_read(&bfqq->ref) <= 0); ++ ++ bfq_log_bfqq(bfqd, bfqq, "put_queue: %p %d", bfqq, ++ atomic_read(&bfqq->ref)); ++ if (!atomic_dec_and_test(&bfqq->ref)) ++ return; ++ ++ BUG_ON(rb_first(&bfqq->sort_list) != NULL); ++ BUG_ON(bfqq->allocated[READ] + bfqq->allocated[WRITE] != 0); ++ BUG_ON(bfqq->entity.tree != NULL); ++ BUG_ON(bfq_bfqq_busy(bfqq)); ++ BUG_ON(bfqd->in_service_queue == bfqq); ++ ++ if (bfq_bfqq_sync(bfqq)) ++ /* ++ * The fact that this queue is being destroyed does not ++ * invalidate the fact that this queue may have been ++ * activated during the current burst. As a consequence, ++ * although the queue does not exist anymore, and hence ++ * needs to be removed from the burst list if there, ++ * the burst size has not to be decremented. ++ */ ++ hlist_del_init(&bfqq->burst_list_node); ++ ++ bfq_log_bfqq(bfqd, bfqq, "put_queue: %p freed", bfqq); ++ ++ kmem_cache_free(bfq_pool, bfqq); ++} ++ ++static void bfq_put_cooperator(struct bfq_queue *bfqq) ++{ ++ struct bfq_queue *__bfqq, *next; ++ ++ /* ++ * If this queue was scheduled to merge with another queue, be ++ * sure to drop the reference taken on that queue (and others in ++ * the merge chain). See bfq_setup_merge and bfq_merge_bfqqs. ++ */ ++ __bfqq = bfqq->new_bfqq; ++ while (__bfqq) { ++ if (__bfqq == bfqq) ++ break; ++ next = __bfqq->new_bfqq; ++ bfq_put_queue(__bfqq); ++ __bfqq = next; ++ } ++} ++ ++static void bfq_exit_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq) ++{ ++ if (bfqq == bfqd->in_service_queue) { ++ __bfq_bfqq_expire(bfqd, bfqq); ++ bfq_schedule_dispatch(bfqd); ++ } ++ ++ bfq_log_bfqq(bfqd, bfqq, "exit_bfqq: %p, %d", bfqq, ++ atomic_read(&bfqq->ref)); ++ ++ bfq_put_cooperator(bfqq); ++ ++ bfq_put_queue(bfqq); ++} ++ ++static inline void bfq_init_icq(struct io_cq *icq) ++{ ++ struct bfq_io_cq *bic = icq_to_bic(icq); ++ ++ bic->ttime.last_end_request = jiffies; ++} ++ ++static void bfq_exit_icq(struct io_cq *icq) ++{ ++ struct bfq_io_cq *bic = icq_to_bic(icq); ++ struct bfq_data *bfqd = bic_to_bfqd(bic); ++ ++ if (bic->bfqq[BLK_RW_ASYNC]) { ++ bfq_exit_bfqq(bfqd, bic->bfqq[BLK_RW_ASYNC]); ++ bic->bfqq[BLK_RW_ASYNC] = NULL; ++ } ++ ++ if (bic->bfqq[BLK_RW_SYNC]) { ++ bfq_exit_bfqq(bfqd, bic->bfqq[BLK_RW_SYNC]); ++ bic->bfqq[BLK_RW_SYNC] = NULL; ++ } ++} ++ ++/* ++ * Update the entity prio values; note that the new values will not ++ * be used until the next (re)activation. ++ */ ++static void bfq_init_prio_data(struct bfq_queue *bfqq, struct bfq_io_cq *bic) ++{ ++ struct task_struct *tsk = current; ++ int ioprio_class; ++ ++ if (!bfq_bfqq_prio_changed(bfqq)) ++ return; ++ ++ ioprio_class = IOPRIO_PRIO_CLASS(bic->ioprio); ++ switch (ioprio_class) { ++ default: ++ dev_err(bfqq->bfqd->queue->backing_dev_info.dev, ++ "bfq: bad prio class %d\n", ioprio_class); ++ case IOPRIO_CLASS_NONE: ++ /* ++ * No prio set, inherit CPU scheduling settings. ++ */ ++ bfqq->entity.new_ioprio = task_nice_ioprio(tsk); ++ bfqq->entity.new_ioprio_class = task_nice_ioclass(tsk); ++ break; ++ case IOPRIO_CLASS_RT: ++ bfqq->entity.new_ioprio = IOPRIO_PRIO_DATA(bic->ioprio); ++ bfqq->entity.new_ioprio_class = IOPRIO_CLASS_RT; ++ break; ++ case IOPRIO_CLASS_BE: ++ bfqq->entity.new_ioprio = IOPRIO_PRIO_DATA(bic->ioprio); ++ bfqq->entity.new_ioprio_class = IOPRIO_CLASS_BE; ++ break; ++ case IOPRIO_CLASS_IDLE: ++ bfqq->entity.new_ioprio_class = IOPRIO_CLASS_IDLE; ++ bfqq->entity.new_ioprio = 7; ++ bfq_clear_bfqq_idle_window(bfqq); ++ break; ++ } ++ ++ if (bfqq->entity.new_ioprio < 0 || ++ bfqq->entity.new_ioprio >= IOPRIO_BE_NR) { ++ printk(KERN_CRIT "bfq_init_prio_data: new_ioprio %d\n", ++ bfqq->entity.new_ioprio); ++ BUG(); ++ } ++ ++ bfqq->entity.ioprio_changed = 1; ++ ++ bfq_clear_bfqq_prio_changed(bfqq); ++} ++ ++static void bfq_changed_ioprio(struct bfq_io_cq *bic) ++{ ++ struct bfq_data *bfqd; ++ struct bfq_queue *bfqq, *new_bfqq; ++ struct bfq_group *bfqg; ++ unsigned long uninitialized_var(flags); ++ int ioprio = bic->icq.ioc->ioprio; ++ ++ bfqd = bfq_get_bfqd_locked(&(bic->icq.q->elevator->elevator_data), ++ &flags); ++ /* ++ * This condition may trigger on a newly created bic, be sure to ++ * drop the lock before returning. ++ */ ++ if (unlikely(bfqd == NULL) || likely(bic->ioprio == ioprio)) ++ goto out; ++ ++ bfqq = bic->bfqq[BLK_RW_ASYNC]; ++ if (bfqq != NULL) { ++ bfqg = container_of(bfqq->entity.sched_data, struct bfq_group, ++ sched_data); ++ new_bfqq = bfq_get_queue(bfqd, bfqg, BLK_RW_ASYNC, bic, ++ GFP_ATOMIC); ++ if (new_bfqq != NULL) { ++ bic->bfqq[BLK_RW_ASYNC] = new_bfqq; ++ bfq_log_bfqq(bfqd, bfqq, ++ "changed_ioprio: bfqq %p %d", ++ bfqq, atomic_read(&bfqq->ref)); ++ bfq_put_queue(bfqq); ++ } ++ } ++ ++ bfqq = bic->bfqq[BLK_RW_SYNC]; ++ if (bfqq != NULL) ++ bfq_mark_bfqq_prio_changed(bfqq); ++ ++ bic->ioprio = ioprio; ++ ++out: ++ bfq_put_bfqd_unlock(bfqd, &flags); ++} ++ ++static void bfq_init_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq, ++ pid_t pid, int is_sync) ++{ ++ RB_CLEAR_NODE(&bfqq->entity.rb_node); ++ INIT_LIST_HEAD(&bfqq->fifo); ++ INIT_HLIST_NODE(&bfqq->burst_list_node); ++ ++ atomic_set(&bfqq->ref, 0); ++ bfqq->bfqd = bfqd; ++ ++ bfq_mark_bfqq_prio_changed(bfqq); ++ ++ if (is_sync) { ++ if (!bfq_class_idle(bfqq)) ++ bfq_mark_bfqq_idle_window(bfqq); ++ bfq_mark_bfqq_sync(bfqq); ++ } ++ bfq_mark_bfqq_IO_bound(bfqq); ++ ++ /* Tentative initial value to trade off between thr and lat */ ++ bfqq->max_budget = (2 * bfq_max_budget(bfqd)) / 3; ++ bfqq->pid = pid; ++ ++ bfqq->wr_coeff = 1; ++ bfqq->last_wr_start_finish = 0; ++ /* ++ * Set to the value for which bfqq will not be deemed as ++ * soft rt when it becomes backlogged. ++ */ ++ bfqq->soft_rt_next_start = bfq_infinity_from_now(jiffies); ++} ++ ++static struct bfq_queue *bfq_find_alloc_queue(struct bfq_data *bfqd, ++ struct bfq_group *bfqg, ++ int is_sync, ++ struct bfq_io_cq *bic, ++ gfp_t gfp_mask) ++{ ++ struct bfq_queue *bfqq, *new_bfqq = NULL; ++ ++retry: ++ /* bic always exists here */ ++ bfqq = bic_to_bfqq(bic, is_sync); ++ ++ /* ++ * Always try a new alloc if we fall back to the OOM bfqq ++ * originally, since it should just be a temporary situation. ++ */ ++ if (bfqq == NULL || bfqq == &bfqd->oom_bfqq) { ++ bfqq = NULL; ++ if (new_bfqq != NULL) { ++ bfqq = new_bfqq; ++ new_bfqq = NULL; ++ } else if (gfp_mask & __GFP_WAIT) { ++ spin_unlock_irq(bfqd->queue->queue_lock); ++ new_bfqq = kmem_cache_alloc_node(bfq_pool, ++ gfp_mask | __GFP_ZERO, ++ bfqd->queue->node); ++ spin_lock_irq(bfqd->queue->queue_lock); ++ if (new_bfqq != NULL) ++ goto retry; ++ } else { ++ bfqq = kmem_cache_alloc_node(bfq_pool, ++ gfp_mask | __GFP_ZERO, ++ bfqd->queue->node); ++ } ++ ++ if (bfqq != NULL) { ++ bfq_init_bfqq(bfqd, bfqq, current->pid, is_sync); ++ bfq_init_prio_data(bfqq, bic); ++ bfq_init_entity(&bfqq->entity, bfqg); ++ bfq_log_bfqq(bfqd, bfqq, "allocated"); ++ } else { ++ bfqq = &bfqd->oom_bfqq; ++ bfq_log_bfqq(bfqd, bfqq, "using oom bfqq"); ++ } ++ } ++ ++ if (new_bfqq != NULL) ++ kmem_cache_free(bfq_pool, new_bfqq); ++ ++ return bfqq; ++} ++ ++static struct bfq_queue **bfq_async_queue_prio(struct bfq_data *bfqd, ++ struct bfq_group *bfqg, ++ int ioprio_class, int ioprio) ++{ ++ switch (ioprio_class) { ++ case IOPRIO_CLASS_RT: ++ return &bfqg->async_bfqq[0][ioprio]; ++ case IOPRIO_CLASS_NONE: ++ ioprio = IOPRIO_NORM; ++ /* fall through */ ++ case IOPRIO_CLASS_BE: ++ return &bfqg->async_bfqq[1][ioprio]; ++ case IOPRIO_CLASS_IDLE: ++ return &bfqg->async_idle_bfqq; ++ default: ++ BUG(); ++ } ++} ++ ++static struct bfq_queue *bfq_get_queue(struct bfq_data *bfqd, ++ struct bfq_group *bfqg, int is_sync, ++ struct bfq_io_cq *bic, gfp_t gfp_mask) ++{ ++ const int ioprio = IOPRIO_PRIO_DATA(bic->ioprio); ++ const int ioprio_class = IOPRIO_PRIO_CLASS(bic->ioprio); ++ struct bfq_queue **async_bfqq = NULL; ++ struct bfq_queue *bfqq = NULL; ++ ++ if (!is_sync) { ++ async_bfqq = bfq_async_queue_prio(bfqd, bfqg, ioprio_class, ++ ioprio); ++ bfqq = *async_bfqq; ++ } ++ ++ if (bfqq == NULL) ++ bfqq = bfq_find_alloc_queue(bfqd, bfqg, is_sync, bic, gfp_mask); ++ ++ /* ++ * Pin the queue now that it's allocated, scheduler exit will ++ * prune it. ++ */ ++ if (!is_sync && *async_bfqq == NULL) { ++ atomic_inc(&bfqq->ref); ++ bfq_log_bfqq(bfqd, bfqq, "get_queue, bfqq not in async: %p, %d", ++ bfqq, atomic_read(&bfqq->ref)); ++ *async_bfqq = bfqq; ++ } ++ ++ atomic_inc(&bfqq->ref); ++ bfq_log_bfqq(bfqd, bfqq, "get_queue, at end: %p, %d", bfqq, ++ atomic_read(&bfqq->ref)); ++ return bfqq; ++} ++ ++static void bfq_update_io_thinktime(struct bfq_data *bfqd, ++ struct bfq_io_cq *bic) ++{ ++ unsigned long elapsed = jiffies - bic->ttime.last_end_request; ++ unsigned long ttime = min(elapsed, 2UL * bfqd->bfq_slice_idle); ++ ++ bic->ttime.ttime_samples = (7*bic->ttime.ttime_samples + 256) / 8; ++ bic->ttime.ttime_total = (7*bic->ttime.ttime_total + 256*ttime) / 8; ++ bic->ttime.ttime_mean = (bic->ttime.ttime_total + 128) / ++ bic->ttime.ttime_samples; ++} ++ ++static void bfq_update_io_seektime(struct bfq_data *bfqd, ++ struct bfq_queue *bfqq, ++ struct request *rq) ++{ ++ sector_t sdist; ++ u64 total; ++ ++ if (bfqq->last_request_pos < blk_rq_pos(rq)) ++ sdist = blk_rq_pos(rq) - bfqq->last_request_pos; ++ else ++ sdist = bfqq->last_request_pos - blk_rq_pos(rq); ++ ++ /* ++ * Don't allow the seek distance to get too large from the ++ * odd fragment, pagein, etc. ++ */ ++ if (bfqq->seek_samples == 0) /* first request, not really a seek */ ++ sdist = 0; ++ else if (bfqq->seek_samples <= 60) /* second & third seek */ ++ sdist = min(sdist, (bfqq->seek_mean * 4) + 2*1024*1024); ++ else ++ sdist = min(sdist, (bfqq->seek_mean * 4) + 2*1024*64); ++ ++ bfqq->seek_samples = (7*bfqq->seek_samples + 256) / 8; ++ bfqq->seek_total = (7*bfqq->seek_total + (u64)256*sdist) / 8; ++ total = bfqq->seek_total + (bfqq->seek_samples/2); ++ do_div(total, bfqq->seek_samples); ++ bfqq->seek_mean = (sector_t)total; ++ ++ bfq_log_bfqq(bfqd, bfqq, "dist=%llu mean=%llu", (u64)sdist, ++ (u64)bfqq->seek_mean); ++} ++ ++/* ++ * Disable idle window if the process thinks too long or seeks so much that ++ * it doesn't matter. ++ */ ++static void bfq_update_idle_window(struct bfq_data *bfqd, ++ struct bfq_queue *bfqq, ++ struct bfq_io_cq *bic) ++{ ++ int enable_idle; ++ ++ /* Don't idle for async or idle io prio class. */ ++ if (!bfq_bfqq_sync(bfqq) || bfq_class_idle(bfqq)) ++ return; ++ ++ enable_idle = bfq_bfqq_idle_window(bfqq); ++ ++ if (atomic_read(&bic->icq.ioc->active_ref) == 0 || ++ bfqd->bfq_slice_idle == 0 || ++ (bfqd->hw_tag && BFQQ_SEEKY(bfqq) && ++ bfqq->wr_coeff == 1)) ++ enable_idle = 0; ++ else if (bfq_sample_valid(bic->ttime.ttime_samples)) { ++ if (bic->ttime.ttime_mean > bfqd->bfq_slice_idle && ++ bfqq->wr_coeff == 1) ++ enable_idle = 0; ++ else ++ enable_idle = 1; ++ } ++ bfq_log_bfqq(bfqd, bfqq, "update_idle_window: enable_idle %d", ++ enable_idle); ++ ++ if (enable_idle) ++ bfq_mark_bfqq_idle_window(bfqq); ++ else ++ bfq_clear_bfqq_idle_window(bfqq); ++} ++ ++/* ++ * Called when a new fs request (rq) is added to bfqq. Check if there's ++ * something we should do about it. ++ */ ++static void bfq_rq_enqueued(struct bfq_data *bfqd, struct bfq_queue *bfqq, ++ struct request *rq) ++{ ++ struct bfq_io_cq *bic = RQ_BIC(rq); ++ ++ if (rq->cmd_flags & REQ_META) ++ bfqq->meta_pending++; ++ ++ bfq_update_io_thinktime(bfqd, bic); ++ bfq_update_io_seektime(bfqd, bfqq, rq); ++ if (!BFQQ_SEEKY(bfqq) && bfq_bfqq_constantly_seeky(bfqq)) { ++ bfq_clear_bfqq_constantly_seeky(bfqq); ++ if (!blk_queue_nonrot(bfqd->queue)) { ++ BUG_ON(!bfqd->const_seeky_busy_in_flight_queues); ++ bfqd->const_seeky_busy_in_flight_queues--; ++ } ++ } ++ if (bfqq->entity.service > bfq_max_budget(bfqd) / 8 || ++ !BFQQ_SEEKY(bfqq)) ++ bfq_update_idle_window(bfqd, bfqq, bic); ++ ++ bfq_log_bfqq(bfqd, bfqq, ++ "rq_enqueued: idle_window=%d (seeky %d, mean %llu)", ++ bfq_bfqq_idle_window(bfqq), BFQQ_SEEKY(bfqq), ++ (long long unsigned)bfqq->seek_mean); ++ ++ bfqq->last_request_pos = blk_rq_pos(rq) + blk_rq_sectors(rq); ++ ++ if (bfqq == bfqd->in_service_queue && bfq_bfqq_wait_request(bfqq)) { ++ int small_req = bfqq->queued[rq_is_sync(rq)] == 1 && ++ blk_rq_sectors(rq) < 32; ++ int budget_timeout = bfq_bfqq_budget_timeout(bfqq); ++ ++ /* ++ * There is just this request queued: if the request ++ * is small and the queue is not to be expired, then ++ * just exit. ++ * ++ * In this way, if the disk is being idled to wait for ++ * a new request from the in-service queue, we avoid ++ * unplugging the device and committing the disk to serve ++ * just a small request. On the contrary, we wait for ++ * the block layer to decide when to unplug the device: ++ * hopefully, new requests will be merged to this one ++ * quickly, then the device will be unplugged and ++ * larger requests will be dispatched. ++ */ ++ if (small_req && !budget_timeout) ++ return; ++ ++ /* ++ * A large enough request arrived, or the queue is to ++ * be expired: in both cases disk idling is to be ++ * stopped, so clear wait_request flag and reset ++ * timer. ++ */ ++ bfq_clear_bfqq_wait_request(bfqq); ++ del_timer(&bfqd->idle_slice_timer); ++ ++ /* ++ * The queue is not empty, because a new request just ++ * arrived. Hence we can safely expire the queue, in ++ * case of budget timeout, without risking that the ++ * timestamps of the queue are not updated correctly. ++ * See [1] for more details. ++ */ ++ if (budget_timeout) ++ bfq_bfqq_expire(bfqd, bfqq, 0, BFQ_BFQQ_BUDGET_TIMEOUT); ++ ++ /* ++ * Let the request rip immediately, or let a new queue be ++ * selected if bfqq has just been expired. ++ */ ++ __blk_run_queue(bfqd->queue); ++ } ++} ++ ++static void bfq_insert_request(struct request_queue *q, struct request *rq) ++{ ++ struct bfq_data *bfqd = q->elevator->elevator_data; ++ struct bfq_queue *bfqq = RQ_BFQQ(rq); ++ ++ assert_spin_locked(bfqd->queue->queue_lock); ++ bfq_init_prio_data(bfqq, RQ_BIC(rq)); ++ ++ bfq_add_request(rq); ++ ++ rq->fifo_time = jiffies + bfqd->bfq_fifo_expire[rq_is_sync(rq)]; ++ list_add_tail(&rq->queuelist, &bfqq->fifo); ++ ++ bfq_rq_enqueued(bfqd, bfqq, rq); ++} ++ ++static void bfq_update_hw_tag(struct bfq_data *bfqd) ++{ ++ bfqd->max_rq_in_driver = max(bfqd->max_rq_in_driver, ++ bfqd->rq_in_driver); ++ ++ if (bfqd->hw_tag == 1) ++ return; ++ ++ /* ++ * This sample is valid if the number of outstanding requests ++ * is large enough to allow a queueing behavior. Note that the ++ * sum is not exact, as it's not taking into account deactivated ++ * requests. ++ */ ++ if (bfqd->rq_in_driver + bfqd->queued < BFQ_HW_QUEUE_THRESHOLD) ++ return; ++ ++ if (bfqd->hw_tag_samples++ < BFQ_HW_QUEUE_SAMPLES) ++ return; ++ ++ bfqd->hw_tag = bfqd->max_rq_in_driver > BFQ_HW_QUEUE_THRESHOLD; ++ bfqd->max_rq_in_driver = 0; ++ bfqd->hw_tag_samples = 0; ++} ++ ++static void bfq_completed_request(struct request_queue *q, struct request *rq) ++{ ++ struct bfq_queue *bfqq = RQ_BFQQ(rq); ++ struct bfq_data *bfqd = bfqq->bfqd; ++ bool sync = bfq_bfqq_sync(bfqq); ++ ++ bfq_log_bfqq(bfqd, bfqq, "completed one req with %u sects left (%d)", ++ blk_rq_sectors(rq), sync); ++ ++ bfq_update_hw_tag(bfqd); ++ ++ BUG_ON(!bfqd->rq_in_driver); ++ BUG_ON(!bfqq->dispatched); ++ bfqd->rq_in_driver--; ++ bfqq->dispatched--; ++ ++ if (!bfqq->dispatched && !bfq_bfqq_busy(bfqq)) { ++ bfq_weights_tree_remove(bfqd, &bfqq->entity, ++ &bfqd->queue_weights_tree); ++ if (!blk_queue_nonrot(bfqd->queue)) { ++ BUG_ON(!bfqd->busy_in_flight_queues); ++ bfqd->busy_in_flight_queues--; ++ if (bfq_bfqq_constantly_seeky(bfqq)) { ++ BUG_ON(!bfqd-> ++ const_seeky_busy_in_flight_queues); ++ bfqd->const_seeky_busy_in_flight_queues--; ++ } ++ } ++ } ++ ++ if (sync) { ++ bfqd->sync_flight--; ++ RQ_BIC(rq)->ttime.last_end_request = jiffies; ++ } ++ ++ /* ++ * If we are waiting to discover whether the request pattern of the ++ * task associated with the queue is actually isochronous, and ++ * both requisites for this condition to hold are satisfied, then ++ * compute soft_rt_next_start (see the comments to the function ++ * bfq_bfqq_softrt_next_start()). ++ */ ++ if (bfq_bfqq_softrt_update(bfqq) && bfqq->dispatched == 0 && ++ RB_EMPTY_ROOT(&bfqq->sort_list)) ++ bfqq->soft_rt_next_start = ++ bfq_bfqq_softrt_next_start(bfqd, bfqq); ++ ++ /* ++ * If this is the in-service queue, check if it needs to be expired, ++ * or if we want to idle in case it has no pending requests. ++ */ ++ if (bfqd->in_service_queue == bfqq) { ++ if (bfq_bfqq_budget_new(bfqq)) ++ bfq_set_budget_timeout(bfqd); ++ ++ if (bfq_bfqq_must_idle(bfqq)) { ++ bfq_arm_slice_timer(bfqd); ++ goto out; ++ } else if (bfq_may_expire_for_budg_timeout(bfqq)) ++ bfq_bfqq_expire(bfqd, bfqq, 0, BFQ_BFQQ_BUDGET_TIMEOUT); ++ else if (RB_EMPTY_ROOT(&bfqq->sort_list) && ++ (bfqq->dispatched == 0 || ++ !bfq_bfqq_must_not_expire(bfqq))) ++ bfq_bfqq_expire(bfqd, bfqq, 0, ++ BFQ_BFQQ_NO_MORE_REQUESTS); ++ } ++ ++ if (!bfqd->rq_in_driver) ++ bfq_schedule_dispatch(bfqd); ++ ++out: ++ return; ++} ++ ++static inline int __bfq_may_queue(struct bfq_queue *bfqq) ++{ ++ if (bfq_bfqq_wait_request(bfqq) && bfq_bfqq_must_alloc(bfqq)) { ++ bfq_clear_bfqq_must_alloc(bfqq); ++ return ELV_MQUEUE_MUST; ++ } ++ ++ return ELV_MQUEUE_MAY; ++} ++ ++static int bfq_may_queue(struct request_queue *q, int rw) ++{ ++ struct bfq_data *bfqd = q->elevator->elevator_data; ++ struct task_struct *tsk = current; ++ struct bfq_io_cq *bic; ++ struct bfq_queue *bfqq; ++ ++ /* ++ * Don't force setup of a queue from here, as a call to may_queue ++ * does not necessarily imply that a request actually will be ++ * queued. So just lookup a possibly existing queue, or return ++ * 'may queue' if that fails. ++ */ ++ bic = bfq_bic_lookup(bfqd, tsk->io_context); ++ if (bic == NULL) ++ return ELV_MQUEUE_MAY; ++ ++ bfqq = bic_to_bfqq(bic, rw_is_sync(rw)); ++ if (bfqq != NULL) { ++ bfq_init_prio_data(bfqq, bic); ++ ++ return __bfq_may_queue(bfqq); ++ } ++ ++ return ELV_MQUEUE_MAY; ++} ++ ++/* ++ * Queue lock held here. ++ */ ++static void bfq_put_request(struct request *rq) ++{ ++ struct bfq_queue *bfqq = RQ_BFQQ(rq); ++ ++ if (bfqq != NULL) { ++ const int rw = rq_data_dir(rq); ++ ++ BUG_ON(!bfqq->allocated[rw]); ++ bfqq->allocated[rw]--; ++ ++ rq->elv.priv[0] = NULL; ++ rq->elv.priv[1] = NULL; ++ ++ bfq_log_bfqq(bfqq->bfqd, bfqq, "put_request %p, %d", ++ bfqq, atomic_read(&bfqq->ref)); ++ bfq_put_queue(bfqq); ++ } ++} ++ ++static struct bfq_queue * ++bfq_merge_bfqqs(struct bfq_data *bfqd, struct bfq_io_cq *bic, ++ struct bfq_queue *bfqq) ++{ ++ bfq_log_bfqq(bfqd, bfqq, "merging with queue %lu", ++ (long unsigned)bfqq->new_bfqq->pid); ++ bic_set_bfqq(bic, bfqq->new_bfqq, 1); ++ bfq_mark_bfqq_coop(bfqq->new_bfqq); ++ bfq_put_queue(bfqq); ++ return bic_to_bfqq(bic, 1); ++} ++ ++/* ++ * Returns NULL if a new bfqq should be allocated, or the old bfqq if this ++ * was the last process referring to said bfqq. ++ */ ++static struct bfq_queue * ++bfq_split_bfqq(struct bfq_io_cq *bic, struct bfq_queue *bfqq) ++{ ++ bfq_log_bfqq(bfqq->bfqd, bfqq, "splitting queue"); ++ if (bfqq_process_refs(bfqq) == 1) { ++ bfqq->pid = current->pid; ++ bfq_clear_bfqq_coop(bfqq); ++ bfq_clear_bfqq_split_coop(bfqq); ++ return bfqq; ++ } ++ ++ bic_set_bfqq(bic, NULL, 1); ++ ++ bfq_put_cooperator(bfqq); ++ ++ bfq_put_queue(bfqq); ++ return NULL; ++} ++ ++/* ++ * Allocate bfq data structures associated with this request. ++ */ ++static int bfq_set_request(struct request_queue *q, struct request *rq, ++ struct bio *bio, gfp_t gfp_mask) ++{ ++ struct bfq_data *bfqd = q->elevator->elevator_data; ++ struct bfq_io_cq *bic = icq_to_bic(rq->elv.icq); ++ const int rw = rq_data_dir(rq); ++ const int is_sync = rq_is_sync(rq); ++ struct bfq_queue *bfqq; ++ struct bfq_group *bfqg; ++ unsigned long flags; ++ ++ might_sleep_if(gfp_mask & __GFP_WAIT); ++ ++ bfq_changed_ioprio(bic); ++ ++ spin_lock_irqsave(q->queue_lock, flags); ++ ++ if (bic == NULL) ++ goto queue_fail; ++ ++ bfqg = bfq_bic_update_cgroup(bic); ++ ++new_queue: ++ bfqq = bic_to_bfqq(bic, is_sync); ++ if (bfqq == NULL || bfqq == &bfqd->oom_bfqq) { ++ bfqq = bfq_get_queue(bfqd, bfqg, is_sync, bic, gfp_mask); ++ bic_set_bfqq(bic, bfqq, is_sync); ++ } else { ++ /* ++ * If the queue was seeky for too long, break it apart. ++ */ ++ if (bfq_bfqq_coop(bfqq) && bfq_bfqq_split_coop(bfqq)) { ++ bfq_log_bfqq(bfqd, bfqq, "breaking apart bfqq"); ++ bfqq = bfq_split_bfqq(bic, bfqq); ++ if (!bfqq) ++ goto new_queue; ++ } ++ ++ /* ++ * Check to see if this queue is scheduled to merge with ++ * another closely cooperating queue. The merging of queues ++ * happens here as it must be done in process context. ++ * The reference on new_bfqq was taken in merge_bfqqs. ++ */ ++ if (bfqq->new_bfqq != NULL) ++ bfqq = bfq_merge_bfqqs(bfqd, bic, bfqq); ++ } ++ ++ bfqq->allocated[rw]++; ++ atomic_inc(&bfqq->ref); ++ bfq_log_bfqq(bfqd, bfqq, "set_request: bfqq %p, %d", bfqq, ++ atomic_read(&bfqq->ref)); ++ ++ rq->elv.priv[0] = bic; ++ rq->elv.priv[1] = bfqq; ++ ++ spin_unlock_irqrestore(q->queue_lock, flags); ++ ++ return 0; ++ ++queue_fail: ++ bfq_schedule_dispatch(bfqd); ++ spin_unlock_irqrestore(q->queue_lock, flags); ++ ++ return 1; ++} ++ ++static void bfq_kick_queue(struct work_struct *work) ++{ ++ struct bfq_data *bfqd = ++ container_of(work, struct bfq_data, unplug_work); ++ struct request_queue *q = bfqd->queue; ++ ++ spin_lock_irq(q->queue_lock); ++ __blk_run_queue(q); ++ spin_unlock_irq(q->queue_lock); ++} ++ ++/* ++ * Handler of the expiration of the timer running if the in-service queue ++ * is idling inside its time slice. ++ */ ++static void bfq_idle_slice_timer(unsigned long data) ++{ ++ struct bfq_data *bfqd = (struct bfq_data *)data; ++ struct bfq_queue *bfqq; ++ unsigned long flags; ++ enum bfqq_expiration reason; ++ ++ spin_lock_irqsave(bfqd->queue->queue_lock, flags); ++ ++ bfqq = bfqd->in_service_queue; ++ /* ++ * Theoretical race here: the in-service queue can be NULL or ++ * different from the queue that was idling if the timer handler ++ * spins on the queue_lock and a new request arrives for the ++ * current queue and there is a full dispatch cycle that changes ++ * the in-service queue. This can hardly happen, but in the worst ++ * case we just expire a queue too early. ++ */ ++ if (bfqq != NULL) { ++ bfq_log_bfqq(bfqd, bfqq, "slice_timer expired"); ++ if (bfq_bfqq_budget_timeout(bfqq)) ++ /* ++ * Also here the queue can be safely expired ++ * for budget timeout without wasting ++ * guarantees ++ */ ++ reason = BFQ_BFQQ_BUDGET_TIMEOUT; ++ else if (bfqq->queued[0] == 0 && bfqq->queued[1] == 0) ++ /* ++ * The queue may not be empty upon timer expiration, ++ * because we may not disable the timer when the ++ * first request of the in-service queue arrives ++ * during disk idling. ++ */ ++ reason = BFQ_BFQQ_TOO_IDLE; ++ else ++ goto schedule_dispatch; ++ ++ bfq_bfqq_expire(bfqd, bfqq, 1, reason); ++ } ++ ++schedule_dispatch: ++ bfq_schedule_dispatch(bfqd); ++ ++ spin_unlock_irqrestore(bfqd->queue->queue_lock, flags); ++} ++ ++static void bfq_shutdown_timer_wq(struct bfq_data *bfqd) ++{ ++ del_timer_sync(&bfqd->idle_slice_timer); ++ cancel_work_sync(&bfqd->unplug_work); ++} ++ ++static inline void __bfq_put_async_bfqq(struct bfq_data *bfqd, ++ struct bfq_queue **bfqq_ptr) ++{ ++ struct bfq_group *root_group = bfqd->root_group; ++ struct bfq_queue *bfqq = *bfqq_ptr; ++ ++ bfq_log(bfqd, "put_async_bfqq: %p", bfqq); ++ if (bfqq != NULL) { ++ bfq_bfqq_move(bfqd, bfqq, &bfqq->entity, root_group); ++ bfq_log_bfqq(bfqd, bfqq, "put_async_bfqq: putting %p, %d", ++ bfqq, atomic_read(&bfqq->ref)); ++ bfq_put_queue(bfqq); ++ *bfqq_ptr = NULL; ++ } ++} ++ ++/* ++ * Release all the bfqg references to its async queues. If we are ++ * deallocating the group these queues may still contain requests, so ++ * we reparent them to the root cgroup (i.e., the only one that will ++ * exist for sure until all the requests on a device are gone). ++ */ ++static void bfq_put_async_queues(struct bfq_data *bfqd, struct bfq_group *bfqg) ++{ ++ int i, j; ++ ++ for (i = 0; i < 2; i++) ++ for (j = 0; j < IOPRIO_BE_NR; j++) ++ __bfq_put_async_bfqq(bfqd, &bfqg->async_bfqq[i][j]); ++ ++ __bfq_put_async_bfqq(bfqd, &bfqg->async_idle_bfqq); ++} ++ ++static void bfq_exit_queue(struct elevator_queue *e) ++{ ++ struct bfq_data *bfqd = e->elevator_data; ++ struct request_queue *q = bfqd->queue; ++ struct bfq_queue *bfqq, *n; ++ ++ bfq_shutdown_timer_wq(bfqd); ++ ++ spin_lock_irq(q->queue_lock); ++ ++ BUG_ON(bfqd->in_service_queue != NULL); ++ list_for_each_entry_safe(bfqq, n, &bfqd->idle_list, bfqq_list) ++ bfq_deactivate_bfqq(bfqd, bfqq, 0); ++ ++ bfq_disconnect_groups(bfqd); ++ spin_unlock_irq(q->queue_lock); ++ ++ bfq_shutdown_timer_wq(bfqd); ++ ++ synchronize_rcu(); ++ ++ BUG_ON(timer_pending(&bfqd->idle_slice_timer)); ++ ++ bfq_free_root_group(bfqd); ++ kfree(bfqd); ++} ++ ++static int bfq_init_queue(struct request_queue *q, struct elevator_type *e) ++{ ++ struct bfq_group *bfqg; ++ struct bfq_data *bfqd; ++ struct elevator_queue *eq; ++ ++ eq = elevator_alloc(q, e); ++ if (eq == NULL) ++ return -ENOMEM; ++ ++ bfqd = kzalloc_node(sizeof(*bfqd), GFP_KERNEL, q->node); ++ if (bfqd == NULL) { ++ kobject_put(&eq->kobj); ++ return -ENOMEM; ++ } ++ eq->elevator_data = bfqd; ++ ++ /* ++ * Our fallback bfqq if bfq_find_alloc_queue() runs into OOM issues. ++ * Grab a permanent reference to it, so that the normal code flow ++ * will not attempt to free it. ++ */ ++ bfq_init_bfqq(bfqd, &bfqd->oom_bfqq, 1, 0); ++ atomic_inc(&bfqd->oom_bfqq.ref); ++ bfqd->oom_bfqq.entity.new_ioprio = BFQ_DEFAULT_QUEUE_IOPRIO; ++ bfqd->oom_bfqq.entity.new_ioprio_class = IOPRIO_CLASS_BE; ++ /* ++ * Trigger weight initialization, according to ioprio, at the ++ * oom_bfqq's first activation. The oom_bfqq's ioprio and ioprio ++ * class won't be changed any more. ++ */ ++ bfqd->oom_bfqq.entity.ioprio_changed = 1; ++ ++ bfqd->queue = q; ++ ++ spin_lock_irq(q->queue_lock); ++ q->elevator = eq; ++ spin_unlock_irq(q->queue_lock); ++ ++ bfqg = bfq_alloc_root_group(bfqd, q->node); ++ if (bfqg == NULL) { ++ kfree(bfqd); ++ kobject_put(&eq->kobj); ++ return -ENOMEM; ++ } ++ ++ bfqd->root_group = bfqg; ++ bfq_init_entity(&bfqd->oom_bfqq.entity, bfqd->root_group); ++#ifdef CONFIG_CGROUP_BFQIO ++ bfqd->active_numerous_groups = 0; ++#endif ++ ++ init_timer(&bfqd->idle_slice_timer); ++ bfqd->idle_slice_timer.function = bfq_idle_slice_timer; ++ bfqd->idle_slice_timer.data = (unsigned long)bfqd; ++ ++ bfqd->rq_pos_tree = RB_ROOT; ++ bfqd->queue_weights_tree = RB_ROOT; ++ bfqd->group_weights_tree = RB_ROOT; ++ ++ INIT_WORK(&bfqd->unplug_work, bfq_kick_queue); ++ ++ INIT_LIST_HEAD(&bfqd->active_list); ++ INIT_LIST_HEAD(&bfqd->idle_list); ++ INIT_HLIST_HEAD(&bfqd->burst_list); ++ ++ bfqd->hw_tag = -1; ++ ++ bfqd->bfq_max_budget = bfq_default_max_budget; ++ ++ bfqd->bfq_quantum = bfq_quantum; ++ bfqd->bfq_fifo_expire[0] = bfq_fifo_expire[0]; ++ bfqd->bfq_fifo_expire[1] = bfq_fifo_expire[1]; ++ bfqd->bfq_back_max = bfq_back_max; ++ bfqd->bfq_back_penalty = bfq_back_penalty; ++ bfqd->bfq_slice_idle = bfq_slice_idle; ++ bfqd->bfq_class_idle_last_service = 0; ++ bfqd->bfq_max_budget_async_rq = bfq_max_budget_async_rq; ++ bfqd->bfq_timeout[BLK_RW_ASYNC] = bfq_timeout_async; ++ bfqd->bfq_timeout[BLK_RW_SYNC] = bfq_timeout_sync; ++ ++ bfqd->bfq_coop_thresh = 2; ++ bfqd->bfq_failed_cooperations = 7000; ++ bfqd->bfq_requests_within_timer = 120; ++ ++ bfqd->bfq_large_burst_thresh = 11; ++ bfqd->bfq_burst_interval = msecs_to_jiffies(500); ++ ++ bfqd->low_latency = true; ++ ++ bfqd->bfq_wr_coeff = 20; ++ bfqd->bfq_wr_rt_max_time = msecs_to_jiffies(300); ++ bfqd->bfq_wr_max_time = 0; ++ bfqd->bfq_wr_min_idle_time = msecs_to_jiffies(2000); ++ bfqd->bfq_wr_min_inter_arr_async = msecs_to_jiffies(500); ++ bfqd->bfq_wr_max_softrt_rate = 7000; /* ++ * Approximate rate required ++ * to playback or record a ++ * high-definition compressed ++ * video. ++ */ ++ bfqd->wr_busy_queues = 0; ++ bfqd->busy_in_flight_queues = 0; ++ bfqd->const_seeky_busy_in_flight_queues = 0; ++ ++ /* ++ * Begin by assuming, optimistically, that the device peak rate is ++ * equal to the highest reference rate. ++ */ ++ bfqd->RT_prod = R_fast[blk_queue_nonrot(bfqd->queue)] * ++ T_fast[blk_queue_nonrot(bfqd->queue)]; ++ bfqd->peak_rate = R_fast[blk_queue_nonrot(bfqd->queue)]; ++ bfqd->device_speed = BFQ_BFQD_FAST; ++ ++ return 0; ++} ++ ++static void bfq_slab_kill(void) ++{ ++ if (bfq_pool != NULL) ++ kmem_cache_destroy(bfq_pool); ++} ++ ++static int __init bfq_slab_setup(void) ++{ ++ bfq_pool = KMEM_CACHE(bfq_queue, 0); ++ if (bfq_pool == NULL) ++ return -ENOMEM; ++ return 0; ++} ++ ++static ssize_t bfq_var_show(unsigned int var, char *page) ++{ ++ return sprintf(page, "%d\n", var); ++} ++ ++static ssize_t bfq_var_store(unsigned long *var, const char *page, ++ size_t count) ++{ ++ unsigned long new_val; ++ int ret = kstrtoul(page, 10, &new_val); ++ ++ if (ret == 0) ++ *var = new_val; ++ ++ return count; ++} ++ ++static ssize_t bfq_wr_max_time_show(struct elevator_queue *e, char *page) ++{ ++ struct bfq_data *bfqd = e->elevator_data; ++ return sprintf(page, "%d\n", bfqd->bfq_wr_max_time > 0 ? ++ jiffies_to_msecs(bfqd->bfq_wr_max_time) : ++ jiffies_to_msecs(bfq_wr_duration(bfqd))); ++} ++ ++static ssize_t bfq_weights_show(struct elevator_queue *e, char *page) ++{ ++ struct bfq_queue *bfqq; ++ struct bfq_data *bfqd = e->elevator_data; ++ ssize_t num_char = 0; ++ ++ num_char += sprintf(page + num_char, "Tot reqs queued %d\n\n", ++ bfqd->queued); ++ ++ spin_lock_irq(bfqd->queue->queue_lock); ++ ++ num_char += sprintf(page + num_char, "Active:\n"); ++ list_for_each_entry(bfqq, &bfqd->active_list, bfqq_list) { ++ num_char += sprintf(page + num_char, ++ "pid%d: weight %hu, nr_queued %d %d, dur %d/%u\n", ++ bfqq->pid, ++ bfqq->entity.weight, ++ bfqq->queued[0], ++ bfqq->queued[1], ++ jiffies_to_msecs(jiffies - bfqq->last_wr_start_finish), ++ jiffies_to_msecs(bfqq->wr_cur_max_time)); ++ } ++ ++ num_char += sprintf(page + num_char, "Idle:\n"); ++ list_for_each_entry(bfqq, &bfqd->idle_list, bfqq_list) { ++ num_char += sprintf(page + num_char, ++ "pid%d: weight %hu, dur %d/%u\n", ++ bfqq->pid, ++ bfqq->entity.weight, ++ jiffies_to_msecs(jiffies - ++ bfqq->last_wr_start_finish), ++ jiffies_to_msecs(bfqq->wr_cur_max_time)); ++ } ++ ++ spin_unlock_irq(bfqd->queue->queue_lock); ++ ++ return num_char; ++} ++ ++#define SHOW_FUNCTION(__FUNC, __VAR, __CONV) \ ++static ssize_t __FUNC(struct elevator_queue *e, char *page) \ ++{ \ ++ struct bfq_data *bfqd = e->elevator_data; \ ++ unsigned int __data = __VAR; \ ++ if (__CONV) \ ++ __data = jiffies_to_msecs(__data); \ ++ return bfq_var_show(__data, (page)); \ ++} ++SHOW_FUNCTION(bfq_quantum_show, bfqd->bfq_quantum, 0); ++SHOW_FUNCTION(bfq_fifo_expire_sync_show, bfqd->bfq_fifo_expire[1], 1); ++SHOW_FUNCTION(bfq_fifo_expire_async_show, bfqd->bfq_fifo_expire[0], 1); ++SHOW_FUNCTION(bfq_back_seek_max_show, bfqd->bfq_back_max, 0); ++SHOW_FUNCTION(bfq_back_seek_penalty_show, bfqd->bfq_back_penalty, 0); ++SHOW_FUNCTION(bfq_slice_idle_show, bfqd->bfq_slice_idle, 1); ++SHOW_FUNCTION(bfq_max_budget_show, bfqd->bfq_user_max_budget, 0); ++SHOW_FUNCTION(bfq_max_budget_async_rq_show, ++ bfqd->bfq_max_budget_async_rq, 0); ++SHOW_FUNCTION(bfq_timeout_sync_show, bfqd->bfq_timeout[BLK_RW_SYNC], 1); ++SHOW_FUNCTION(bfq_timeout_async_show, bfqd->bfq_timeout[BLK_RW_ASYNC], 1); ++SHOW_FUNCTION(bfq_low_latency_show, bfqd->low_latency, 0); ++SHOW_FUNCTION(bfq_wr_coeff_show, bfqd->bfq_wr_coeff, 0); ++SHOW_FUNCTION(bfq_wr_rt_max_time_show, bfqd->bfq_wr_rt_max_time, 1); ++SHOW_FUNCTION(bfq_wr_min_idle_time_show, bfqd->bfq_wr_min_idle_time, 1); ++SHOW_FUNCTION(bfq_wr_min_inter_arr_async_show, bfqd->bfq_wr_min_inter_arr_async, ++ 1); ++SHOW_FUNCTION(bfq_wr_max_softrt_rate_show, bfqd->bfq_wr_max_softrt_rate, 0); ++#undef SHOW_FUNCTION ++ ++#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV) \ ++static ssize_t \ ++__FUNC(struct elevator_queue *e, const char *page, size_t count) \ ++{ \ ++ struct bfq_data *bfqd = e->elevator_data; \ ++ unsigned long uninitialized_var(__data); \ ++ int ret = bfq_var_store(&__data, (page), count); \ ++ if (__data < (MIN)) \ ++ __data = (MIN); \ ++ else if (__data > (MAX)) \ ++ __data = (MAX); \ ++ if (__CONV) \ ++ *(__PTR) = msecs_to_jiffies(__data); \ ++ else \ ++ *(__PTR) = __data; \ ++ return ret; \ ++} ++STORE_FUNCTION(bfq_quantum_store, &bfqd->bfq_quantum, 1, INT_MAX, 0); ++STORE_FUNCTION(bfq_fifo_expire_sync_store, &bfqd->bfq_fifo_expire[1], 1, ++ INT_MAX, 1); ++STORE_FUNCTION(bfq_fifo_expire_async_store, &bfqd->bfq_fifo_expire[0], 1, ++ INT_MAX, 1); ++STORE_FUNCTION(bfq_back_seek_max_store, &bfqd->bfq_back_max, 0, INT_MAX, 0); ++STORE_FUNCTION(bfq_back_seek_penalty_store, &bfqd->bfq_back_penalty, 1, ++ INT_MAX, 0); ++STORE_FUNCTION(bfq_slice_idle_store, &bfqd->bfq_slice_idle, 0, INT_MAX, 1); ++STORE_FUNCTION(bfq_max_budget_async_rq_store, &bfqd->bfq_max_budget_async_rq, ++ 1, INT_MAX, 0); ++STORE_FUNCTION(bfq_timeout_async_store, &bfqd->bfq_timeout[BLK_RW_ASYNC], 0, ++ INT_MAX, 1); ++STORE_FUNCTION(bfq_wr_coeff_store, &bfqd->bfq_wr_coeff, 1, INT_MAX, 0); ++STORE_FUNCTION(bfq_wr_max_time_store, &bfqd->bfq_wr_max_time, 0, INT_MAX, 1); ++STORE_FUNCTION(bfq_wr_rt_max_time_store, &bfqd->bfq_wr_rt_max_time, 0, INT_MAX, ++ 1); ++STORE_FUNCTION(bfq_wr_min_idle_time_store, &bfqd->bfq_wr_min_idle_time, 0, ++ INT_MAX, 1); ++STORE_FUNCTION(bfq_wr_min_inter_arr_async_store, ++ &bfqd->bfq_wr_min_inter_arr_async, 0, INT_MAX, 1); ++STORE_FUNCTION(bfq_wr_max_softrt_rate_store, &bfqd->bfq_wr_max_softrt_rate, 0, ++ INT_MAX, 0); ++#undef STORE_FUNCTION ++ ++/* do nothing for the moment */ ++static ssize_t bfq_weights_store(struct elevator_queue *e, ++ const char *page, size_t count) ++{ ++ return count; ++} ++ ++static inline unsigned long bfq_estimated_max_budget(struct bfq_data *bfqd) ++{ ++ u64 timeout = jiffies_to_msecs(bfqd->bfq_timeout[BLK_RW_SYNC]); ++ ++ if (bfqd->peak_rate_samples >= BFQ_PEAK_RATE_SAMPLES) ++ return bfq_calc_max_budget(bfqd->peak_rate, timeout); ++ else ++ return bfq_default_max_budget; ++} ++ ++static ssize_t bfq_max_budget_store(struct elevator_queue *e, ++ const char *page, size_t count) ++{ ++ struct bfq_data *bfqd = e->elevator_data; ++ unsigned long uninitialized_var(__data); ++ int ret = bfq_var_store(&__data, (page), count); ++ ++ if (__data == 0) ++ bfqd->bfq_max_budget = bfq_estimated_max_budget(bfqd); ++ else { ++ if (__data > INT_MAX) ++ __data = INT_MAX; ++ bfqd->bfq_max_budget = __data; ++ } ++ ++ bfqd->bfq_user_max_budget = __data; ++ ++ return ret; ++} ++ ++static ssize_t bfq_timeout_sync_store(struct elevator_queue *e, ++ const char *page, size_t count) ++{ ++ struct bfq_data *bfqd = e->elevator_data; ++ unsigned long uninitialized_var(__data); ++ int ret = bfq_var_store(&__data, (page), count); ++ ++ if (__data < 1) ++ __data = 1; ++ else if (__data > INT_MAX) ++ __data = INT_MAX; ++ ++ bfqd->bfq_timeout[BLK_RW_SYNC] = msecs_to_jiffies(__data); ++ if (bfqd->bfq_user_max_budget == 0) ++ bfqd->bfq_max_budget = bfq_estimated_max_budget(bfqd); ++ ++ return ret; ++} ++ ++static ssize_t bfq_low_latency_store(struct elevator_queue *e, ++ const char *page, size_t count) ++{ ++ struct bfq_data *bfqd = e->elevator_data; ++ unsigned long uninitialized_var(__data); ++ int ret = bfq_var_store(&__data, (page), count); ++ ++ if (__data > 1) ++ __data = 1; ++ if (__data == 0 && bfqd->low_latency != 0) ++ bfq_end_wr(bfqd); ++ bfqd->low_latency = __data; ++ ++ return ret; ++} ++ ++#define BFQ_ATTR(name) \ ++ __ATTR(name, S_IRUGO|S_IWUSR, bfq_##name##_show, bfq_##name##_store) ++ ++static struct elv_fs_entry bfq_attrs[] = { ++ BFQ_ATTR(quantum), ++ BFQ_ATTR(fifo_expire_sync), ++ BFQ_ATTR(fifo_expire_async), ++ BFQ_ATTR(back_seek_max), ++ BFQ_ATTR(back_seek_penalty), ++ BFQ_ATTR(slice_idle), ++ BFQ_ATTR(max_budget), ++ BFQ_ATTR(max_budget_async_rq), ++ BFQ_ATTR(timeout_sync), ++ BFQ_ATTR(timeout_async), ++ BFQ_ATTR(low_latency), ++ BFQ_ATTR(wr_coeff), ++ BFQ_ATTR(wr_max_time), ++ BFQ_ATTR(wr_rt_max_time), ++ BFQ_ATTR(wr_min_idle_time), ++ BFQ_ATTR(wr_min_inter_arr_async), ++ BFQ_ATTR(wr_max_softrt_rate), ++ BFQ_ATTR(weights), ++ __ATTR_NULL ++}; ++ ++static struct elevator_type iosched_bfq = { ++ .ops = { ++ .elevator_merge_fn = bfq_merge, ++ .elevator_merged_fn = bfq_merged_request, ++ .elevator_merge_req_fn = bfq_merged_requests, ++ .elevator_allow_merge_fn = bfq_allow_merge, ++ .elevator_dispatch_fn = bfq_dispatch_requests, ++ .elevator_add_req_fn = bfq_insert_request, ++ .elevator_activate_req_fn = bfq_activate_request, ++ .elevator_deactivate_req_fn = bfq_deactivate_request, ++ .elevator_completed_req_fn = bfq_completed_request, ++ .elevator_former_req_fn = elv_rb_former_request, ++ .elevator_latter_req_fn = elv_rb_latter_request, ++ .elevator_init_icq_fn = bfq_init_icq, ++ .elevator_exit_icq_fn = bfq_exit_icq, ++ .elevator_set_req_fn = bfq_set_request, ++ .elevator_put_req_fn = bfq_put_request, ++ .elevator_may_queue_fn = bfq_may_queue, ++ .elevator_init_fn = bfq_init_queue, ++ .elevator_exit_fn = bfq_exit_queue, ++ }, ++ .icq_size = sizeof(struct bfq_io_cq), ++ .icq_align = __alignof__(struct bfq_io_cq), ++ .elevator_attrs = bfq_attrs, ++ .elevator_name = "bfq", ++ .elevator_owner = THIS_MODULE, ++}; ++ ++static int __init bfq_init(void) ++{ ++ /* ++ * Can be 0 on HZ < 1000 setups. ++ */ ++ if (bfq_slice_idle == 0) ++ bfq_slice_idle = 1; ++ ++ if (bfq_timeout_async == 0) ++ bfq_timeout_async = 1; ++ ++ if (bfq_slab_setup()) ++ return -ENOMEM; ++ ++ /* ++ * Times to load large popular applications for the typical systems ++ * installed on the reference devices (see the comments before the ++ * definitions of the two arrays). ++ */ ++ T_slow[0] = msecs_to_jiffies(2600); ++ T_slow[1] = msecs_to_jiffies(1000); ++ T_fast[0] = msecs_to_jiffies(5500); ++ T_fast[1] = msecs_to_jiffies(2000); ++ ++ /* ++ * Thresholds that determine the switch between speed classes (see ++ * the comments before the definition of the array). ++ */ ++ device_speed_thresh[0] = (R_fast[0] + R_slow[0]) / 2; ++ device_speed_thresh[1] = (R_fast[1] + R_slow[1]) / 2; ++ ++ elv_register(&iosched_bfq); ++ pr_info("BFQ I/O-scheduler version: v7r7"); ++ ++ return 0; ++} ++ ++static void __exit bfq_exit(void) ++{ ++ elv_unregister(&iosched_bfq); ++ bfq_slab_kill(); ++} ++ ++module_init(bfq_init); ++module_exit(bfq_exit); ++ ++MODULE_AUTHOR("Fabio Checconi, Paolo Valente"); ++MODULE_LICENSE("GPL"); +diff --git a/block/bfq-sched.c b/block/bfq-sched.c +new file mode 100644 +index 0000000..2931563 +--- /dev/null ++++ b/block/bfq-sched.c +@@ -0,0 +1,1214 @@ ++/* ++ * BFQ: Hierarchical B-WF2Q+ scheduler. ++ * ++ * Based on ideas and code from CFQ: ++ * Copyright (C) 2003 Jens Axboe ++ * ++ * Copyright (C) 2008 Fabio Checconi ++ * Paolo Valente ++ * ++ * Copyright (C) 2010 Paolo Valente ++ */ ++ ++#ifdef CONFIG_CGROUP_BFQIO ++#define for_each_entity(entity) \ ++ for (; entity != NULL; entity = entity->parent) ++ ++#define for_each_entity_safe(entity, parent) \ ++ for (; entity && ({ parent = entity->parent; 1; }); entity = parent) ++ ++static struct bfq_entity *bfq_lookup_next_entity(struct bfq_sched_data *sd, ++ int extract, ++ struct bfq_data *bfqd); ++ ++static inline void bfq_update_budget(struct bfq_entity *next_in_service) ++{ ++ struct bfq_entity *bfqg_entity; ++ struct bfq_group *bfqg; ++ struct bfq_sched_data *group_sd; ++ ++ BUG_ON(next_in_service == NULL); ++ ++ group_sd = next_in_service->sched_data; ++ ++ bfqg = container_of(group_sd, struct bfq_group, sched_data); ++ /* ++ * bfq_group's my_entity field is not NULL only if the group ++ * is not the root group. We must not touch the root entity ++ * as it must never become an in-service entity. ++ */ ++ bfqg_entity = bfqg->my_entity; ++ if (bfqg_entity != NULL) ++ bfqg_entity->budget = next_in_service->budget; ++} ++ ++static int bfq_update_next_in_service(struct bfq_sched_data *sd) ++{ ++ struct bfq_entity *next_in_service; ++ ++ if (sd->in_service_entity != NULL) ++ /* will update/requeue at the end of service */ ++ return 0; ++ ++ /* ++ * NOTE: this can be improved in many ways, such as returning ++ * 1 (and thus propagating upwards the update) only when the ++ * budget changes, or caching the bfqq that will be scheduled ++ * next from this subtree. By now we worry more about ++ * correctness than about performance... ++ */ ++ next_in_service = bfq_lookup_next_entity(sd, 0, NULL); ++ sd->next_in_service = next_in_service; ++ ++ if (next_in_service != NULL) ++ bfq_update_budget(next_in_service); ++ ++ return 1; ++} ++ ++static inline void bfq_check_next_in_service(struct bfq_sched_data *sd, ++ struct bfq_entity *entity) ++{ ++ BUG_ON(sd->next_in_service != entity); ++} ++#else ++#define for_each_entity(entity) \ ++ for (; entity != NULL; entity = NULL) ++ ++#define for_each_entity_safe(entity, parent) \ ++ for (parent = NULL; entity != NULL; entity = parent) ++ ++static inline int bfq_update_next_in_service(struct bfq_sched_data *sd) ++{ ++ return 0; ++} ++ ++static inline void bfq_check_next_in_service(struct bfq_sched_data *sd, ++ struct bfq_entity *entity) ++{ ++} ++ ++static inline void bfq_update_budget(struct bfq_entity *next_in_service) ++{ ++} ++#endif ++ ++/* ++ * Shift for timestamp calculations. This actually limits the maximum ++ * service allowed in one timestamp delta (small shift values increase it), ++ * the maximum total weight that can be used for the queues in the system ++ * (big shift values increase it), and the period of virtual time ++ * wraparounds. ++ */ ++#define WFQ_SERVICE_SHIFT 22 ++ ++/** ++ * bfq_gt - compare two timestamps. ++ * @a: first ts. ++ * @b: second ts. ++ * ++ * Return @a > @b, dealing with wrapping correctly. ++ */ ++static inline int bfq_gt(u64 a, u64 b) ++{ ++ return (s64)(a - b) > 0; ++} ++ ++static inline struct bfq_queue *bfq_entity_to_bfqq(struct bfq_entity *entity) ++{ ++ struct bfq_queue *bfqq = NULL; ++ ++ BUG_ON(entity == NULL); ++ ++ if (entity->my_sched_data == NULL) ++ bfqq = container_of(entity, struct bfq_queue, entity); ++ ++ return bfqq; ++} ++ ++ ++/** ++ * bfq_delta - map service into the virtual time domain. ++ * @service: amount of service. ++ * @weight: scale factor (weight of an entity or weight sum). ++ */ ++static inline u64 bfq_delta(unsigned long service, ++ unsigned long weight) ++{ ++ u64 d = (u64)service << WFQ_SERVICE_SHIFT; ++ ++ do_div(d, weight); ++ return d; ++} ++ ++/** ++ * bfq_calc_finish - assign the finish time to an entity. ++ * @entity: the entity to act upon. ++ * @service: the service to be charged to the entity. ++ */ ++static inline void bfq_calc_finish(struct bfq_entity *entity, ++ unsigned long service) ++{ ++ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); ++ ++ BUG_ON(entity->weight == 0); ++ ++ entity->finish = entity->start + ++ bfq_delta(service, entity->weight); ++ ++ if (bfqq != NULL) { ++ bfq_log_bfqq(bfqq->bfqd, bfqq, ++ "calc_finish: serv %lu, w %d", ++ service, entity->weight); ++ bfq_log_bfqq(bfqq->bfqd, bfqq, ++ "calc_finish: start %llu, finish %llu, delta %llu", ++ entity->start, entity->finish, ++ bfq_delta(service, entity->weight)); ++ } ++} ++ ++/** ++ * bfq_entity_of - get an entity from a node. ++ * @node: the node field of the entity. ++ * ++ * Convert a node pointer to the relative entity. This is used only ++ * to simplify the logic of some functions and not as the generic ++ * conversion mechanism because, e.g., in the tree walking functions, ++ * the check for a %NULL value would be redundant. ++ */ ++static inline struct bfq_entity *bfq_entity_of(struct rb_node *node) ++{ ++ struct bfq_entity *entity = NULL; ++ ++ if (node != NULL) ++ entity = rb_entry(node, struct bfq_entity, rb_node); ++ ++ return entity; ++} ++ ++/** ++ * bfq_extract - remove an entity from a tree. ++ * @root: the tree root. ++ * @entity: the entity to remove. ++ */ ++static inline void bfq_extract(struct rb_root *root, ++ struct bfq_entity *entity) ++{ ++ BUG_ON(entity->tree != root); ++ ++ entity->tree = NULL; ++ rb_erase(&entity->rb_node, root); ++} ++ ++/** ++ * bfq_idle_extract - extract an entity from the idle tree. ++ * @st: the service tree of the owning @entity. ++ * @entity: the entity being removed. ++ */ ++static void bfq_idle_extract(struct bfq_service_tree *st, ++ struct bfq_entity *entity) ++{ ++ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); ++ struct rb_node *next; ++ ++ BUG_ON(entity->tree != &st->idle); ++ ++ if (entity == st->first_idle) { ++ next = rb_next(&entity->rb_node); ++ st->first_idle = bfq_entity_of(next); ++ } ++ ++ if (entity == st->last_idle) { ++ next = rb_prev(&entity->rb_node); ++ st->last_idle = bfq_entity_of(next); ++ } ++ ++ bfq_extract(&st->idle, entity); ++ ++ if (bfqq != NULL) ++ list_del(&bfqq->bfqq_list); ++} ++ ++/** ++ * bfq_insert - generic tree insertion. ++ * @root: tree root. ++ * @entity: entity to insert. ++ * ++ * This is used for the idle and the active tree, since they are both ++ * ordered by finish time. ++ */ ++static void bfq_insert(struct rb_root *root, struct bfq_entity *entity) ++{ ++ struct bfq_entity *entry; ++ struct rb_node **node = &root->rb_node; ++ struct rb_node *parent = NULL; ++ ++ BUG_ON(entity->tree != NULL); ++ ++ while (*node != NULL) { ++ parent = *node; ++ entry = rb_entry(parent, struct bfq_entity, rb_node); ++ ++ if (bfq_gt(entry->finish, entity->finish)) ++ node = &parent->rb_left; ++ else ++ node = &parent->rb_right; ++ } ++ ++ rb_link_node(&entity->rb_node, parent, node); ++ rb_insert_color(&entity->rb_node, root); ++ ++ entity->tree = root; ++} ++ ++/** ++ * bfq_update_min - update the min_start field of a entity. ++ * @entity: the entity to update. ++ * @node: one of its children. ++ * ++ * This function is called when @entity may store an invalid value for ++ * min_start due to updates to the active tree. The function assumes ++ * that the subtree rooted at @node (which may be its left or its right ++ * child) has a valid min_start value. ++ */ ++static inline void bfq_update_min(struct bfq_entity *entity, ++ struct rb_node *node) ++{ ++ struct bfq_entity *child; ++ ++ if (node != NULL) { ++ child = rb_entry(node, struct bfq_entity, rb_node); ++ if (bfq_gt(entity->min_start, child->min_start)) ++ entity->min_start = child->min_start; ++ } ++} ++ ++/** ++ * bfq_update_active_node - recalculate min_start. ++ * @node: the node to update. ++ * ++ * @node may have changed position or one of its children may have moved, ++ * this function updates its min_start value. The left and right subtrees ++ * are assumed to hold a correct min_start value. ++ */ ++static inline void bfq_update_active_node(struct rb_node *node) ++{ ++ struct bfq_entity *entity = rb_entry(node, struct bfq_entity, rb_node); ++ ++ entity->min_start = entity->start; ++ bfq_update_min(entity, node->rb_right); ++ bfq_update_min(entity, node->rb_left); ++} ++ ++/** ++ * bfq_update_active_tree - update min_start for the whole active tree. ++ * @node: the starting node. ++ * ++ * @node must be the deepest modified node after an update. This function ++ * updates its min_start using the values held by its children, assuming ++ * that they did not change, and then updates all the nodes that may have ++ * changed in the path to the root. The only nodes that may have changed ++ * are the ones in the path or their siblings. ++ */ ++static void bfq_update_active_tree(struct rb_node *node) ++{ ++ struct rb_node *parent; ++ ++up: ++ bfq_update_active_node(node); ++ ++ parent = rb_parent(node); ++ if (parent == NULL) ++ return; ++ ++ if (node == parent->rb_left && parent->rb_right != NULL) ++ bfq_update_active_node(parent->rb_right); ++ else if (parent->rb_left != NULL) ++ bfq_update_active_node(parent->rb_left); ++ ++ node = parent; ++ goto up; ++} ++ ++static void bfq_weights_tree_add(struct bfq_data *bfqd, ++ struct bfq_entity *entity, ++ struct rb_root *root); ++ ++static void bfq_weights_tree_remove(struct bfq_data *bfqd, ++ struct bfq_entity *entity, ++ struct rb_root *root); ++ ++ ++/** ++ * bfq_active_insert - insert an entity in the active tree of its ++ * group/device. ++ * @st: the service tree of the entity. ++ * @entity: the entity being inserted. ++ * ++ * The active tree is ordered by finish time, but an extra key is kept ++ * per each node, containing the minimum value for the start times of ++ * its children (and the node itself), so it's possible to search for ++ * the eligible node with the lowest finish time in logarithmic time. ++ */ ++static void bfq_active_insert(struct bfq_service_tree *st, ++ struct bfq_entity *entity) ++{ ++ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); ++ struct rb_node *node = &entity->rb_node; ++#ifdef CONFIG_CGROUP_BFQIO ++ struct bfq_sched_data *sd = NULL; ++ struct bfq_group *bfqg = NULL; ++ struct bfq_data *bfqd = NULL; ++#endif ++ ++ bfq_insert(&st->active, entity); ++ ++ if (node->rb_left != NULL) ++ node = node->rb_left; ++ else if (node->rb_right != NULL) ++ node = node->rb_right; ++ ++ bfq_update_active_tree(node); ++ ++#ifdef CONFIG_CGROUP_BFQIO ++ sd = entity->sched_data; ++ bfqg = container_of(sd, struct bfq_group, sched_data); ++ BUG_ON(!bfqg); ++ bfqd = (struct bfq_data *)bfqg->bfqd; ++#endif ++ if (bfqq != NULL) ++ list_add(&bfqq->bfqq_list, &bfqq->bfqd->active_list); ++#ifdef CONFIG_CGROUP_BFQIO ++ else { /* bfq_group */ ++ BUG_ON(!bfqd); ++ bfq_weights_tree_add(bfqd, entity, &bfqd->group_weights_tree); ++ } ++ if (bfqg != bfqd->root_group) { ++ BUG_ON(!bfqg); ++ BUG_ON(!bfqd); ++ bfqg->active_entities++; ++ if (bfqg->active_entities == 2) ++ bfqd->active_numerous_groups++; ++ } ++#endif ++} ++ ++/** ++ * bfq_ioprio_to_weight - calc a weight from an ioprio. ++ * @ioprio: the ioprio value to convert. ++ */ ++static inline unsigned short bfq_ioprio_to_weight(int ioprio) ++{ ++ BUG_ON(ioprio < 0 || ioprio >= IOPRIO_BE_NR); ++ return IOPRIO_BE_NR - ioprio; ++} ++ ++/** ++ * bfq_weight_to_ioprio - calc an ioprio from a weight. ++ * @weight: the weight value to convert. ++ * ++ * To preserve as mush as possible the old only-ioprio user interface, ++ * 0 is used as an escape ioprio value for weights (numerically) equal or ++ * larger than IOPRIO_BE_NR ++ */ ++static inline unsigned short bfq_weight_to_ioprio(int weight) ++{ ++ BUG_ON(weight < BFQ_MIN_WEIGHT || weight > BFQ_MAX_WEIGHT); ++ return IOPRIO_BE_NR - weight < 0 ? 0 : IOPRIO_BE_NR - weight; ++} ++ ++static inline void bfq_get_entity(struct bfq_entity *entity) ++{ ++ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); ++ ++ if (bfqq != NULL) { ++ atomic_inc(&bfqq->ref); ++ bfq_log_bfqq(bfqq->bfqd, bfqq, "get_entity: %p %d", ++ bfqq, atomic_read(&bfqq->ref)); ++ } ++} ++ ++/** ++ * bfq_find_deepest - find the deepest node that an extraction can modify. ++ * @node: the node being removed. ++ * ++ * Do the first step of an extraction in an rb tree, looking for the ++ * node that will replace @node, and returning the deepest node that ++ * the following modifications to the tree can touch. If @node is the ++ * last node in the tree return %NULL. ++ */ ++static struct rb_node *bfq_find_deepest(struct rb_node *node) ++{ ++ struct rb_node *deepest; ++ ++ if (node->rb_right == NULL && node->rb_left == NULL) ++ deepest = rb_parent(node); ++ else if (node->rb_right == NULL) ++ deepest = node->rb_left; ++ else if (node->rb_left == NULL) ++ deepest = node->rb_right; ++ else { ++ deepest = rb_next(node); ++ if (deepest->rb_right != NULL) ++ deepest = deepest->rb_right; ++ else if (rb_parent(deepest) != node) ++ deepest = rb_parent(deepest); ++ } ++ ++ return deepest; ++} ++ ++/** ++ * bfq_active_extract - remove an entity from the active tree. ++ * @st: the service_tree containing the tree. ++ * @entity: the entity being removed. ++ */ ++static void bfq_active_extract(struct bfq_service_tree *st, ++ struct bfq_entity *entity) ++{ ++ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); ++ struct rb_node *node; ++#ifdef CONFIG_CGROUP_BFQIO ++ struct bfq_sched_data *sd = NULL; ++ struct bfq_group *bfqg = NULL; ++ struct bfq_data *bfqd = NULL; ++#endif ++ ++ node = bfq_find_deepest(&entity->rb_node); ++ bfq_extract(&st->active, entity); ++ ++ if (node != NULL) ++ bfq_update_active_tree(node); ++ ++#ifdef CONFIG_CGROUP_BFQIO ++ sd = entity->sched_data; ++ bfqg = container_of(sd, struct bfq_group, sched_data); ++ BUG_ON(!bfqg); ++ bfqd = (struct bfq_data *)bfqg->bfqd; ++#endif ++ if (bfqq != NULL) ++ list_del(&bfqq->bfqq_list); ++#ifdef CONFIG_CGROUP_BFQIO ++ else { /* bfq_group */ ++ BUG_ON(!bfqd); ++ bfq_weights_tree_remove(bfqd, entity, ++ &bfqd->group_weights_tree); ++ } ++ if (bfqg != bfqd->root_group) { ++ BUG_ON(!bfqg); ++ BUG_ON(!bfqd); ++ BUG_ON(!bfqg->active_entities); ++ bfqg->active_entities--; ++ if (bfqg->active_entities == 1) { ++ BUG_ON(!bfqd->active_numerous_groups); ++ bfqd->active_numerous_groups--; ++ } ++ } ++#endif ++} ++ ++/** ++ * bfq_idle_insert - insert an entity into the idle tree. ++ * @st: the service tree containing the tree. ++ * @entity: the entity to insert. ++ */ ++static void bfq_idle_insert(struct bfq_service_tree *st, ++ struct bfq_entity *entity) ++{ ++ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); ++ struct bfq_entity *first_idle = st->first_idle; ++ struct bfq_entity *last_idle = st->last_idle; ++ ++ if (first_idle == NULL || bfq_gt(first_idle->finish, entity->finish)) ++ st->first_idle = entity; ++ if (last_idle == NULL || bfq_gt(entity->finish, last_idle->finish)) ++ st->last_idle = entity; ++ ++ bfq_insert(&st->idle, entity); ++ ++ if (bfqq != NULL) ++ list_add(&bfqq->bfqq_list, &bfqq->bfqd->idle_list); ++} ++ ++/** ++ * bfq_forget_entity - remove an entity from the wfq trees. ++ * @st: the service tree. ++ * @entity: the entity being removed. ++ * ++ * Update the device status and forget everything about @entity, putting ++ * the device reference to it, if it is a queue. Entities belonging to ++ * groups are not refcounted. ++ */ ++static void bfq_forget_entity(struct bfq_service_tree *st, ++ struct bfq_entity *entity) ++{ ++ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); ++ struct bfq_sched_data *sd; ++ ++ BUG_ON(!entity->on_st); ++ ++ entity->on_st = 0; ++ st->wsum -= entity->weight; ++ if (bfqq != NULL) { ++ sd = entity->sched_data; ++ bfq_log_bfqq(bfqq->bfqd, bfqq, "forget_entity: %p %d", ++ bfqq, atomic_read(&bfqq->ref)); ++ bfq_put_queue(bfqq); ++ } ++} ++ ++/** ++ * bfq_put_idle_entity - release the idle tree ref of an entity. ++ * @st: service tree for the entity. ++ * @entity: the entity being released. ++ */ ++static void bfq_put_idle_entity(struct bfq_service_tree *st, ++ struct bfq_entity *entity) ++{ ++ bfq_idle_extract(st, entity); ++ bfq_forget_entity(st, entity); ++} ++ ++/** ++ * bfq_forget_idle - update the idle tree if necessary. ++ * @st: the service tree to act upon. ++ * ++ * To preserve the global O(log N) complexity we only remove one entry here; ++ * as the idle tree will not grow indefinitely this can be done safely. ++ */ ++static void bfq_forget_idle(struct bfq_service_tree *st) ++{ ++ struct bfq_entity *first_idle = st->first_idle; ++ struct bfq_entity *last_idle = st->last_idle; ++ ++ if (RB_EMPTY_ROOT(&st->active) && last_idle != NULL && ++ !bfq_gt(last_idle->finish, st->vtime)) { ++ /* ++ * Forget the whole idle tree, increasing the vtime past ++ * the last finish time of idle entities. ++ */ ++ st->vtime = last_idle->finish; ++ } ++ ++ if (first_idle != NULL && !bfq_gt(first_idle->finish, st->vtime)) ++ bfq_put_idle_entity(st, first_idle); ++} ++ ++static struct bfq_service_tree * ++__bfq_entity_update_weight_prio(struct bfq_service_tree *old_st, ++ struct bfq_entity *entity) ++{ ++ struct bfq_service_tree *new_st = old_st; ++ ++ if (entity->ioprio_changed) { ++ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); ++ unsigned short prev_weight, new_weight; ++ struct bfq_data *bfqd = NULL; ++ struct rb_root *root; ++#ifdef CONFIG_CGROUP_BFQIO ++ struct bfq_sched_data *sd; ++ struct bfq_group *bfqg; ++#endif ++ ++ if (bfqq != NULL) ++ bfqd = bfqq->bfqd; ++#ifdef CONFIG_CGROUP_BFQIO ++ else { ++ sd = entity->my_sched_data; ++ bfqg = container_of(sd, struct bfq_group, sched_data); ++ BUG_ON(!bfqg); ++ bfqd = (struct bfq_data *)bfqg->bfqd; ++ BUG_ON(!bfqd); ++ } ++#endif ++ ++ BUG_ON(old_st->wsum < entity->weight); ++ old_st->wsum -= entity->weight; ++ ++ if (entity->new_weight != entity->orig_weight) { ++ if (entity->new_weight < BFQ_MIN_WEIGHT || ++ entity->new_weight > BFQ_MAX_WEIGHT) { ++ printk(KERN_CRIT "update_weight_prio: " ++ "new_weight %d\n", ++ entity->new_weight); ++ BUG(); ++ } ++ entity->orig_weight = entity->new_weight; ++ entity->ioprio = ++ bfq_weight_to_ioprio(entity->orig_weight); ++ } else if (entity->new_ioprio != entity->ioprio) { ++ entity->ioprio = entity->new_ioprio; ++ entity->orig_weight = ++ bfq_ioprio_to_weight(entity->ioprio); ++ } else ++ entity->new_weight = entity->orig_weight = ++ bfq_ioprio_to_weight(entity->ioprio); ++ ++ entity->ioprio_class = entity->new_ioprio_class; ++ entity->ioprio_changed = 0; ++ ++ /* ++ * NOTE: here we may be changing the weight too early, ++ * this will cause unfairness. The correct approach ++ * would have required additional complexity to defer ++ * weight changes to the proper time instants (i.e., ++ * when entity->finish <= old_st->vtime). ++ */ ++ new_st = bfq_entity_service_tree(entity); ++ ++ prev_weight = entity->weight; ++ new_weight = entity->orig_weight * ++ (bfqq != NULL ? bfqq->wr_coeff : 1); ++ /* ++ * If the weight of the entity changes, remove the entity ++ * from its old weight counter (if there is a counter ++ * associated with the entity), and add it to the counter ++ * associated with its new weight. ++ */ ++ if (prev_weight != new_weight) { ++ root = bfqq ? &bfqd->queue_weights_tree : ++ &bfqd->group_weights_tree; ++ bfq_weights_tree_remove(bfqd, entity, root); ++ } ++ entity->weight = new_weight; ++ /* ++ * Add the entity to its weights tree only if it is ++ * not associated with a weight-raised queue. ++ */ ++ if (prev_weight != new_weight && ++ (bfqq ? bfqq->wr_coeff == 1 : 1)) ++ /* If we get here, root has been initialized. */ ++ bfq_weights_tree_add(bfqd, entity, root); ++ ++ new_st->wsum += entity->weight; ++ ++ if (new_st != old_st) ++ entity->start = new_st->vtime; ++ } ++ ++ return new_st; ++} ++ ++/** ++ * bfq_bfqq_served - update the scheduler status after selection for ++ * service. ++ * @bfqq: the queue being served. ++ * @served: bytes to transfer. ++ * ++ * NOTE: this can be optimized, as the timestamps of upper level entities ++ * are synchronized every time a new bfqq is selected for service. By now, ++ * we keep it to better check consistency. ++ */ ++static void bfq_bfqq_served(struct bfq_queue *bfqq, unsigned long served) ++{ ++ struct bfq_entity *entity = &bfqq->entity; ++ struct bfq_service_tree *st; ++ ++ for_each_entity(entity) { ++ st = bfq_entity_service_tree(entity); ++ ++ entity->service += served; ++ BUG_ON(entity->service > entity->budget); ++ BUG_ON(st->wsum == 0); ++ ++ st->vtime += bfq_delta(served, st->wsum); ++ bfq_forget_idle(st); ++ } ++ bfq_log_bfqq(bfqq->bfqd, bfqq, "bfqq_served %lu secs", served); ++} ++ ++/** ++ * bfq_bfqq_charge_full_budget - set the service to the entity budget. ++ * @bfqq: the queue that needs a service update. ++ * ++ * When it's not possible to be fair in the service domain, because ++ * a queue is not consuming its budget fast enough (the meaning of ++ * fast depends on the timeout parameter), we charge it a full ++ * budget. In this way we should obtain a sort of time-domain ++ * fairness among all the seeky/slow queues. ++ */ ++static inline void bfq_bfqq_charge_full_budget(struct bfq_queue *bfqq) ++{ ++ struct bfq_entity *entity = &bfqq->entity; ++ ++ bfq_log_bfqq(bfqq->bfqd, bfqq, "charge_full_budget"); ++ ++ bfq_bfqq_served(bfqq, entity->budget - entity->service); ++} ++ ++/** ++ * __bfq_activate_entity - activate an entity. ++ * @entity: the entity being activated. ++ * ++ * Called whenever an entity is activated, i.e., it is not active and one ++ * of its children receives a new request, or has to be reactivated due to ++ * budget exhaustion. It uses the current budget of the entity (and the ++ * service received if @entity is active) of the queue to calculate its ++ * timestamps. ++ */ ++static void __bfq_activate_entity(struct bfq_entity *entity) ++{ ++ struct bfq_sched_data *sd = entity->sched_data; ++ struct bfq_service_tree *st = bfq_entity_service_tree(entity); ++ ++ if (entity == sd->in_service_entity) { ++ BUG_ON(entity->tree != NULL); ++ /* ++ * If we are requeueing the current entity we have ++ * to take care of not charging to it service it has ++ * not received. ++ */ ++ bfq_calc_finish(entity, entity->service); ++ entity->start = entity->finish; ++ sd->in_service_entity = NULL; ++ } else if (entity->tree == &st->active) { ++ /* ++ * Requeueing an entity due to a change of some ++ * next_in_service entity below it. We reuse the ++ * old start time. ++ */ ++ bfq_active_extract(st, entity); ++ } else if (entity->tree == &st->idle) { ++ /* ++ * Must be on the idle tree, bfq_idle_extract() will ++ * check for that. ++ */ ++ bfq_idle_extract(st, entity); ++ entity->start = bfq_gt(st->vtime, entity->finish) ? ++ st->vtime : entity->finish; ++ } else { ++ /* ++ * The finish time of the entity may be invalid, and ++ * it is in the past for sure, otherwise the queue ++ * would have been on the idle tree. ++ */ ++ entity->start = st->vtime; ++ st->wsum += entity->weight; ++ bfq_get_entity(entity); ++ ++ BUG_ON(entity->on_st); ++ entity->on_st = 1; ++ } ++ ++ st = __bfq_entity_update_weight_prio(st, entity); ++ bfq_calc_finish(entity, entity->budget); ++ bfq_active_insert(st, entity); ++} ++ ++/** ++ * bfq_activate_entity - activate an entity and its ancestors if necessary. ++ * @entity: the entity to activate. ++ * ++ * Activate @entity and all the entities on the path from it to the root. ++ */ ++static void bfq_activate_entity(struct bfq_entity *entity) ++{ ++ struct bfq_sched_data *sd; ++ ++ for_each_entity(entity) { ++ __bfq_activate_entity(entity); ++ ++ sd = entity->sched_data; ++ if (!bfq_update_next_in_service(sd)) ++ /* ++ * No need to propagate the activation to the ++ * upper entities, as they will be updated when ++ * the in-service entity is rescheduled. ++ */ ++ break; ++ } ++} ++ ++/** ++ * __bfq_deactivate_entity - deactivate an entity from its service tree. ++ * @entity: the entity to deactivate. ++ * @requeue: if false, the entity will not be put into the idle tree. ++ * ++ * Deactivate an entity, independently from its previous state. If the ++ * entity was not on a service tree just return, otherwise if it is on ++ * any scheduler tree, extract it from that tree, and if necessary ++ * and if the caller did not specify @requeue, put it on the idle tree. ++ * ++ * Return %1 if the caller should update the entity hierarchy, i.e., ++ * if the entity was in service or if it was the next_in_service for ++ * its sched_data; return %0 otherwise. ++ */ ++static int __bfq_deactivate_entity(struct bfq_entity *entity, int requeue) ++{ ++ struct bfq_sched_data *sd = entity->sched_data; ++ struct bfq_service_tree *st = bfq_entity_service_tree(entity); ++ int was_in_service = entity == sd->in_service_entity; ++ int ret = 0; ++ ++ if (!entity->on_st) ++ return 0; ++ ++ BUG_ON(was_in_service && entity->tree != NULL); ++ ++ if (was_in_service) { ++ bfq_calc_finish(entity, entity->service); ++ sd->in_service_entity = NULL; ++ } else if (entity->tree == &st->active) ++ bfq_active_extract(st, entity); ++ else if (entity->tree == &st->idle) ++ bfq_idle_extract(st, entity); ++ else if (entity->tree != NULL) ++ BUG(); ++ ++ if (was_in_service || sd->next_in_service == entity) ++ ret = bfq_update_next_in_service(sd); ++ ++ if (!requeue || !bfq_gt(entity->finish, st->vtime)) ++ bfq_forget_entity(st, entity); ++ else ++ bfq_idle_insert(st, entity); ++ ++ BUG_ON(sd->in_service_entity == entity); ++ BUG_ON(sd->next_in_service == entity); ++ ++ return ret; ++} ++ ++/** ++ * bfq_deactivate_entity - deactivate an entity. ++ * @entity: the entity to deactivate. ++ * @requeue: true if the entity can be put on the idle tree ++ */ ++static void bfq_deactivate_entity(struct bfq_entity *entity, int requeue) ++{ ++ struct bfq_sched_data *sd; ++ struct bfq_entity *parent; ++ ++ for_each_entity_safe(entity, parent) { ++ sd = entity->sched_data; ++ ++ if (!__bfq_deactivate_entity(entity, requeue)) ++ /* ++ * The parent entity is still backlogged, and ++ * we don't need to update it as it is still ++ * in service. ++ */ ++ break; ++ ++ if (sd->next_in_service != NULL) ++ /* ++ * The parent entity is still backlogged and ++ * the budgets on the path towards the root ++ * need to be updated. ++ */ ++ goto update; ++ ++ /* ++ * If we reach there the parent is no more backlogged and ++ * we want to propagate the dequeue upwards. ++ */ ++ requeue = 1; ++ } ++ ++ return; ++ ++update: ++ entity = parent; ++ for_each_entity(entity) { ++ __bfq_activate_entity(entity); ++ ++ sd = entity->sched_data; ++ if (!bfq_update_next_in_service(sd)) ++ break; ++ } ++} ++ ++/** ++ * bfq_update_vtime - update vtime if necessary. ++ * @st: the service tree to act upon. ++ * ++ * If necessary update the service tree vtime to have at least one ++ * eligible entity, skipping to its start time. Assumes that the ++ * active tree of the device is not empty. ++ * ++ * NOTE: this hierarchical implementation updates vtimes quite often, ++ * we may end up with reactivated processes getting timestamps after a ++ * vtime skip done because we needed a ->first_active entity on some ++ * intermediate node. ++ */ ++static void bfq_update_vtime(struct bfq_service_tree *st) ++{ ++ struct bfq_entity *entry; ++ struct rb_node *node = st->active.rb_node; ++ ++ entry = rb_entry(node, struct bfq_entity, rb_node); ++ if (bfq_gt(entry->min_start, st->vtime)) { ++ st->vtime = entry->min_start; ++ bfq_forget_idle(st); ++ } ++} ++ ++/** ++ * bfq_first_active_entity - find the eligible entity with ++ * the smallest finish time ++ * @st: the service tree to select from. ++ * ++ * This function searches the first schedulable entity, starting from the ++ * root of the tree and going on the left every time on this side there is ++ * a subtree with at least one eligible (start >= vtime) entity. The path on ++ * the right is followed only if a) the left subtree contains no eligible ++ * entities and b) no eligible entity has been found yet. ++ */ ++static struct bfq_entity *bfq_first_active_entity(struct bfq_service_tree *st) ++{ ++ struct bfq_entity *entry, *first = NULL; ++ struct rb_node *node = st->active.rb_node; ++ ++ while (node != NULL) { ++ entry = rb_entry(node, struct bfq_entity, rb_node); ++left: ++ if (!bfq_gt(entry->start, st->vtime)) ++ first = entry; ++ ++ BUG_ON(bfq_gt(entry->min_start, st->vtime)); ++ ++ if (node->rb_left != NULL) { ++ entry = rb_entry(node->rb_left, ++ struct bfq_entity, rb_node); ++ if (!bfq_gt(entry->min_start, st->vtime)) { ++ node = node->rb_left; ++ goto left; ++ } ++ } ++ if (first != NULL) ++ break; ++ node = node->rb_right; ++ } ++ ++ BUG_ON(first == NULL && !RB_EMPTY_ROOT(&st->active)); ++ return first; ++} ++ ++/** ++ * __bfq_lookup_next_entity - return the first eligible entity in @st. ++ * @st: the service tree. ++ * ++ * Update the virtual time in @st and return the first eligible entity ++ * it contains. ++ */ ++static struct bfq_entity *__bfq_lookup_next_entity(struct bfq_service_tree *st, ++ bool force) ++{ ++ struct bfq_entity *entity, *new_next_in_service = NULL; ++ ++ if (RB_EMPTY_ROOT(&st->active)) ++ return NULL; ++ ++ bfq_update_vtime(st); ++ entity = bfq_first_active_entity(st); ++ BUG_ON(bfq_gt(entity->start, st->vtime)); ++ ++ /* ++ * If the chosen entity does not match with the sched_data's ++ * next_in_service and we are forcedly serving the IDLE priority ++ * class tree, bubble up budget update. ++ */ ++ if (unlikely(force && entity != entity->sched_data->next_in_service)) { ++ new_next_in_service = entity; ++ for_each_entity(new_next_in_service) ++ bfq_update_budget(new_next_in_service); ++ } ++ ++ return entity; ++} ++ ++/** ++ * bfq_lookup_next_entity - return the first eligible entity in @sd. ++ * @sd: the sched_data. ++ * @extract: if true the returned entity will be also extracted from @sd. ++ * ++ * NOTE: since we cache the next_in_service entity at each level of the ++ * hierarchy, the complexity of the lookup can be decreased with ++ * absolutely no effort just returning the cached next_in_service value; ++ * we prefer to do full lookups to test the consistency of * the data ++ * structures. ++ */ ++static struct bfq_entity *bfq_lookup_next_entity(struct bfq_sched_data *sd, ++ int extract, ++ struct bfq_data *bfqd) ++{ ++ struct bfq_service_tree *st = sd->service_tree; ++ struct bfq_entity *entity; ++ int i = 0; ++ ++ BUG_ON(sd->in_service_entity != NULL); ++ ++ if (bfqd != NULL && ++ jiffies - bfqd->bfq_class_idle_last_service > BFQ_CL_IDLE_TIMEOUT) { ++ entity = __bfq_lookup_next_entity(st + BFQ_IOPRIO_CLASSES - 1, ++ true); ++ if (entity != NULL) { ++ i = BFQ_IOPRIO_CLASSES - 1; ++ bfqd->bfq_class_idle_last_service = jiffies; ++ sd->next_in_service = entity; ++ } ++ } ++ for (; i < BFQ_IOPRIO_CLASSES; i++) { ++ entity = __bfq_lookup_next_entity(st + i, false); ++ if (entity != NULL) { ++ if (extract) { ++ bfq_check_next_in_service(sd, entity); ++ bfq_active_extract(st + i, entity); ++ sd->in_service_entity = entity; ++ sd->next_in_service = NULL; ++ } ++ break; ++ } ++ } ++ ++ return entity; ++} ++ ++/* ++ * Get next queue for service. ++ */ ++static struct bfq_queue *bfq_get_next_queue(struct bfq_data *bfqd) ++{ ++ struct bfq_entity *entity = NULL; ++ struct bfq_sched_data *sd; ++ struct bfq_queue *bfqq; ++ ++ BUG_ON(bfqd->in_service_queue != NULL); ++ ++ if (bfqd->busy_queues == 0) ++ return NULL; ++ ++ sd = &bfqd->root_group->sched_data; ++ for (; sd != NULL; sd = entity->my_sched_data) { ++ entity = bfq_lookup_next_entity(sd, 1, bfqd); ++ BUG_ON(entity == NULL); ++ entity->service = 0; ++ } ++ ++ bfqq = bfq_entity_to_bfqq(entity); ++ BUG_ON(bfqq == NULL); ++ ++ return bfqq; ++} ++ ++/* ++ * Forced extraction of the given queue. ++ */ ++static void bfq_get_next_queue_forced(struct bfq_data *bfqd, ++ struct bfq_queue *bfqq) ++{ ++ struct bfq_entity *entity; ++ struct bfq_sched_data *sd; ++ ++ BUG_ON(bfqd->in_service_queue != NULL); ++ ++ entity = &bfqq->entity; ++ /* ++ * Bubble up extraction/update from the leaf to the root. ++ */ ++ for_each_entity(entity) { ++ sd = entity->sched_data; ++ bfq_update_budget(entity); ++ bfq_update_vtime(bfq_entity_service_tree(entity)); ++ bfq_active_extract(bfq_entity_service_tree(entity), entity); ++ sd->in_service_entity = entity; ++ sd->next_in_service = NULL; ++ entity->service = 0; ++ } ++ ++ return; ++} ++ ++static void __bfq_bfqd_reset_in_service(struct bfq_data *bfqd) ++{ ++ if (bfqd->in_service_bic != NULL) { ++ put_io_context(bfqd->in_service_bic->icq.ioc); ++ bfqd->in_service_bic = NULL; ++ } ++ ++ bfqd->in_service_queue = NULL; ++ del_timer(&bfqd->idle_slice_timer); ++} ++ ++static void bfq_deactivate_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq, ++ int requeue) ++{ ++ struct bfq_entity *entity = &bfqq->entity; ++ ++ if (bfqq == bfqd->in_service_queue) ++ __bfq_bfqd_reset_in_service(bfqd); ++ ++ bfq_deactivate_entity(entity, requeue); ++} ++ ++static void bfq_activate_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq) ++{ ++ struct bfq_entity *entity = &bfqq->entity; ++ ++ bfq_activate_entity(entity); ++} ++ ++/* ++ * Called when the bfqq no longer has requests pending, remove it from ++ * the service tree. ++ */ ++static void bfq_del_bfqq_busy(struct bfq_data *bfqd, struct bfq_queue *bfqq, ++ int requeue) ++{ ++ BUG_ON(!bfq_bfqq_busy(bfqq)); ++ BUG_ON(!RB_EMPTY_ROOT(&bfqq->sort_list)); ++ ++ bfq_log_bfqq(bfqd, bfqq, "del from busy"); ++ ++ bfq_clear_bfqq_busy(bfqq); ++ ++ BUG_ON(bfqd->busy_queues == 0); ++ bfqd->busy_queues--; ++ ++ if (!bfqq->dispatched) { ++ bfq_weights_tree_remove(bfqd, &bfqq->entity, ++ &bfqd->queue_weights_tree); ++ if (!blk_queue_nonrot(bfqd->queue)) { ++ BUG_ON(!bfqd->busy_in_flight_queues); ++ bfqd->busy_in_flight_queues--; ++ if (bfq_bfqq_constantly_seeky(bfqq)) { ++ BUG_ON(!bfqd-> ++ const_seeky_busy_in_flight_queues); ++ bfqd->const_seeky_busy_in_flight_queues--; ++ } ++ } ++ } ++ if (bfqq->wr_coeff > 1) ++ bfqd->wr_busy_queues--; ++ ++ bfq_deactivate_bfqq(bfqd, bfqq, requeue); ++} ++ ++/* ++ * Called when an inactive queue receives a new request. ++ */ ++static void bfq_add_bfqq_busy(struct bfq_data *bfqd, struct bfq_queue *bfqq) ++{ ++ BUG_ON(bfq_bfqq_busy(bfqq)); ++ BUG_ON(bfqq == bfqd->in_service_queue); ++ ++ bfq_log_bfqq(bfqd, bfqq, "add to busy"); ++ ++ bfq_activate_bfqq(bfqd, bfqq); ++ ++ bfq_mark_bfqq_busy(bfqq); ++ bfqd->busy_queues++; ++ ++ if (!bfqq->dispatched) { ++ if (bfqq->wr_coeff == 1) ++ bfq_weights_tree_add(bfqd, &bfqq->entity, ++ &bfqd->queue_weights_tree); ++ if (!blk_queue_nonrot(bfqd->queue)) { ++ bfqd->busy_in_flight_queues++; ++ if (bfq_bfqq_constantly_seeky(bfqq)) ++ bfqd->const_seeky_busy_in_flight_queues++; ++ } ++ } ++ if (bfqq->wr_coeff > 1) ++ bfqd->wr_busy_queues++; ++} +diff --git a/block/bfq.h b/block/bfq.h +new file mode 100644 +index 0000000..3c5d85e +--- /dev/null ++++ b/block/bfq.h +@@ -0,0 +1,775 @@ ++/* ++ * BFQ-v7r7 for 3.19.0: data structures and common functions prototypes. ++ * ++ * Based on ideas and code from CFQ: ++ * Copyright (C) 2003 Jens Axboe ++ * ++ * Copyright (C) 2008 Fabio Checconi ++ * Paolo Valente ++ * ++ * Copyright (C) 2010 Paolo Valente ++ */ ++ ++#ifndef _BFQ_H ++#define _BFQ_H ++ ++#include ++#include ++#include ++#include ++ ++#define BFQ_IOPRIO_CLASSES 3 ++#define BFQ_CL_IDLE_TIMEOUT (HZ/5) ++ ++#define BFQ_MIN_WEIGHT 1 ++#define BFQ_MAX_WEIGHT 1000 ++ ++#define BFQ_DEFAULT_QUEUE_IOPRIO 4 ++ ++#define BFQ_DEFAULT_GRP_WEIGHT 10 ++#define BFQ_DEFAULT_GRP_IOPRIO 0 ++#define BFQ_DEFAULT_GRP_CLASS IOPRIO_CLASS_BE ++ ++struct bfq_entity; ++ ++/** ++ * struct bfq_service_tree - per ioprio_class service tree. ++ * @active: tree for active entities (i.e., those backlogged). ++ * @idle: tree for idle entities (i.e., those not backlogged, with V <= F_i). ++ * @first_idle: idle entity with minimum F_i. ++ * @last_idle: idle entity with maximum F_i. ++ * @vtime: scheduler virtual time. ++ * @wsum: scheduler weight sum; active and idle entities contribute to it. ++ * ++ * Each service tree represents a B-WF2Q+ scheduler on its own. Each ++ * ioprio_class has its own independent scheduler, and so its own ++ * bfq_service_tree. All the fields are protected by the queue lock ++ * of the containing bfqd. ++ */ ++struct bfq_service_tree { ++ struct rb_root active; ++ struct rb_root idle; ++ ++ struct bfq_entity *first_idle; ++ struct bfq_entity *last_idle; ++ ++ u64 vtime; ++ unsigned long wsum; ++}; ++ ++/** ++ * struct bfq_sched_data - multi-class scheduler. ++ * @in_service_entity: entity in service. ++ * @next_in_service: head-of-the-line entity in the scheduler. ++ * @service_tree: array of service trees, one per ioprio_class. ++ * ++ * bfq_sched_data is the basic scheduler queue. It supports three ++ * ioprio_classes, and can be used either as a toplevel queue or as ++ * an intermediate queue on a hierarchical setup. ++ * @next_in_service points to the active entity of the sched_data ++ * service trees that will be scheduled next. ++ * ++ * The supported ioprio_classes are the same as in CFQ, in descending ++ * priority order, IOPRIO_CLASS_RT, IOPRIO_CLASS_BE, IOPRIO_CLASS_IDLE. ++ * Requests from higher priority queues are served before all the ++ * requests from lower priority queues; among requests of the same ++ * queue requests are served according to B-WF2Q+. ++ * All the fields are protected by the queue lock of the containing bfqd. ++ */ ++struct bfq_sched_data { ++ struct bfq_entity *in_service_entity; ++ struct bfq_entity *next_in_service; ++ struct bfq_service_tree service_tree[BFQ_IOPRIO_CLASSES]; ++}; ++ ++/** ++ * struct bfq_weight_counter - counter of the number of all active entities ++ * with a given weight. ++ * @weight: weight of the entities that this counter refers to. ++ * @num_active: number of active entities with this weight. ++ * @weights_node: weights tree member (see bfq_data's @queue_weights_tree ++ * and @group_weights_tree). ++ */ ++struct bfq_weight_counter { ++ short int weight; ++ unsigned int num_active; ++ struct rb_node weights_node; ++}; ++ ++/** ++ * struct bfq_entity - schedulable entity. ++ * @rb_node: service_tree member. ++ * @weight_counter: pointer to the weight counter associated with this entity. ++ * @on_st: flag, true if the entity is on a tree (either the active or ++ * the idle one of its service_tree). ++ * @finish: B-WF2Q+ finish timestamp (aka F_i). ++ * @start: B-WF2Q+ start timestamp (aka S_i). ++ * @tree: tree the entity is enqueued into; %NULL if not on a tree. ++ * @min_start: minimum start time of the (active) subtree rooted at ++ * this entity; used for O(log N) lookups into active trees. ++ * @service: service received during the last round of service. ++ * @budget: budget used to calculate F_i; F_i = S_i + @budget / @weight. ++ * @weight: weight of the queue ++ * @parent: parent entity, for hierarchical scheduling. ++ * @my_sched_data: for non-leaf nodes in the cgroup hierarchy, the ++ * associated scheduler queue, %NULL on leaf nodes. ++ * @sched_data: the scheduler queue this entity belongs to. ++ * @ioprio: the ioprio in use. ++ * @new_weight: when a weight change is requested, the new weight value. ++ * @orig_weight: original weight, used to implement weight boosting ++ * @new_ioprio: when an ioprio change is requested, the new ioprio value. ++ * @ioprio_class: the ioprio_class in use. ++ * @new_ioprio_class: when an ioprio_class change is requested, the new ++ * ioprio_class value. ++ * @ioprio_changed: flag, true when the user requested a weight, ioprio or ++ * ioprio_class change. ++ * ++ * A bfq_entity is used to represent either a bfq_queue (leaf node in the ++ * cgroup hierarchy) or a bfq_group into the upper level scheduler. Each ++ * entity belongs to the sched_data of the parent group in the cgroup ++ * hierarchy. Non-leaf entities have also their own sched_data, stored ++ * in @my_sched_data. ++ * ++ * Each entity stores independently its priority values; this would ++ * allow different weights on different devices, but this ++ * functionality is not exported to userspace by now. Priorities and ++ * weights are updated lazily, first storing the new values into the ++ * new_* fields, then setting the @ioprio_changed flag. As soon as ++ * there is a transition in the entity state that allows the priority ++ * update to take place the effective and the requested priority ++ * values are synchronized. ++ * ++ * Unless cgroups are used, the weight value is calculated from the ++ * ioprio to export the same interface as CFQ. When dealing with ++ * ``well-behaved'' queues (i.e., queues that do not spend too much ++ * time to consume their budget and have true sequential behavior, and ++ * when there are no external factors breaking anticipation) the ++ * relative weights at each level of the cgroups hierarchy should be ++ * guaranteed. All the fields are protected by the queue lock of the ++ * containing bfqd. ++ */ ++struct bfq_entity { ++ struct rb_node rb_node; ++ struct bfq_weight_counter *weight_counter; ++ ++ int on_st; ++ ++ u64 finish; ++ u64 start; ++ ++ struct rb_root *tree; ++ ++ u64 min_start; ++ ++ unsigned long service, budget; ++ unsigned short weight, new_weight; ++ unsigned short orig_weight; ++ ++ struct bfq_entity *parent; ++ ++ struct bfq_sched_data *my_sched_data; ++ struct bfq_sched_data *sched_data; ++ ++ unsigned short ioprio, new_ioprio; ++ unsigned short ioprio_class, new_ioprio_class; ++ ++ int ioprio_changed; ++}; ++ ++struct bfq_group; ++ ++/** ++ * struct bfq_queue - leaf schedulable entity. ++ * @ref: reference counter. ++ * @bfqd: parent bfq_data. ++ * @new_bfqq: shared bfq_queue if queue is cooperating with ++ * one or more other queues. ++ * @pos_node: request-position tree member (see bfq_data's @rq_pos_tree). ++ * @pos_root: request-position tree root (see bfq_data's @rq_pos_tree). ++ * @sort_list: sorted list of pending requests. ++ * @next_rq: if fifo isn't expired, next request to serve. ++ * @queued: nr of requests queued in @sort_list. ++ * @allocated: currently allocated requests. ++ * @meta_pending: pending metadata requests. ++ * @fifo: fifo list of requests in sort_list. ++ * @entity: entity representing this queue in the scheduler. ++ * @max_budget: maximum budget allowed from the feedback mechanism. ++ * @budget_timeout: budget expiration (in jiffies). ++ * @dispatched: number of requests on the dispatch list or inside driver. ++ * @flags: status flags. ++ * @bfqq_list: node for active/idle bfqq list inside our bfqd. ++ * @burst_list_node: node for the device's burst list. ++ * @seek_samples: number of seeks sampled ++ * @seek_total: sum of the distances of the seeks sampled ++ * @seek_mean: mean seek distance ++ * @last_request_pos: position of the last request enqueued ++ * @requests_within_timer: number of consecutive pairs of request completion ++ * and arrival, such that the queue becomes idle ++ * after the completion, but the next request arrives ++ * within an idle time slice; used only if the queue's ++ * IO_bound has been cleared. ++ * @pid: pid of the process owning the queue, used for logging purposes. ++ * @last_wr_start_finish: start time of the current weight-raising period if ++ * the @bfq-queue is being weight-raised, otherwise ++ * finish time of the last weight-raising period ++ * @wr_cur_max_time: current max raising time for this queue ++ * @soft_rt_next_start: minimum time instant such that, only if a new ++ * request is enqueued after this time instant in an ++ * idle @bfq_queue with no outstanding requests, then ++ * the task associated with the queue it is deemed as ++ * soft real-time (see the comments to the function ++ * bfq_bfqq_softrt_next_start()). ++ * @last_idle_bklogged: time of the last transition of the @bfq_queue from ++ * idle to backlogged ++ * @service_from_backlogged: cumulative service received from the @bfq_queue ++ * since the last transition from idle to ++ * backlogged ++ * ++ * A bfq_queue is a leaf request queue; it can be associated with an io_context ++ * or more, if it is async or shared between cooperating processes. @cgroup ++ * holds a reference to the cgroup, to be sure that it does not disappear while ++ * a bfqq still references it (mostly to avoid races between request issuing and ++ * task migration followed by cgroup destruction). ++ * All the fields are protected by the queue lock of the containing bfqd. ++ */ ++struct bfq_queue { ++ atomic_t ref; ++ struct bfq_data *bfqd; ++ ++ /* fields for cooperating queues handling */ ++ struct bfq_queue *new_bfqq; ++ struct rb_node pos_node; ++ struct rb_root *pos_root; ++ ++ struct rb_root sort_list; ++ struct request *next_rq; ++ int queued[2]; ++ int allocated[2]; ++ int meta_pending; ++ struct list_head fifo; ++ ++ struct bfq_entity entity; ++ ++ unsigned long max_budget; ++ unsigned long budget_timeout; ++ ++ int dispatched; ++ ++ unsigned int flags; ++ ++ struct list_head bfqq_list; ++ ++ struct hlist_node burst_list_node; ++ ++ unsigned int seek_samples; ++ u64 seek_total; ++ sector_t seek_mean; ++ sector_t last_request_pos; ++ ++ unsigned int requests_within_timer; ++ ++ pid_t pid; ++ ++ /* weight-raising fields */ ++ unsigned long wr_cur_max_time; ++ unsigned long soft_rt_next_start; ++ unsigned long last_wr_start_finish; ++ unsigned int wr_coeff; ++ unsigned long last_idle_bklogged; ++ unsigned long service_from_backlogged; ++}; ++ ++/** ++ * struct bfq_ttime - per process thinktime stats. ++ * @ttime_total: total process thinktime ++ * @ttime_samples: number of thinktime samples ++ * @ttime_mean: average process thinktime ++ */ ++struct bfq_ttime { ++ unsigned long last_end_request; ++ ++ unsigned long ttime_total; ++ unsigned long ttime_samples; ++ unsigned long ttime_mean; ++}; ++ ++/** ++ * struct bfq_io_cq - per (request_queue, io_context) structure. ++ * @icq: associated io_cq structure ++ * @bfqq: array of two process queues, the sync and the async ++ * @ttime: associated @bfq_ttime struct ++ */ ++struct bfq_io_cq { ++ struct io_cq icq; /* must be the first member */ ++ struct bfq_queue *bfqq[2]; ++ struct bfq_ttime ttime; ++ int ioprio; ++}; ++ ++enum bfq_device_speed { ++ BFQ_BFQD_FAST, ++ BFQ_BFQD_SLOW, ++}; ++ ++/** ++ * struct bfq_data - per device data structure. ++ * @queue: request queue for the managed device. ++ * @root_group: root bfq_group for the device. ++ * @rq_pos_tree: rbtree sorted by next_request position, used when ++ * determining if two or more queues have interleaving ++ * requests (see bfq_close_cooperator()). ++ * @active_numerous_groups: number of bfq_groups containing more than one ++ * active @bfq_entity. ++ * @queue_weights_tree: rbtree of weight counters of @bfq_queues, sorted by ++ * weight. Used to keep track of whether all @bfq_queues ++ * have the same weight. The tree contains one counter ++ * for each distinct weight associated to some active ++ * and not weight-raised @bfq_queue (see the comments to ++ * the functions bfq_weights_tree_[add|remove] for ++ * further details). ++ * @group_weights_tree: rbtree of non-queue @bfq_entity weight counters, sorted ++ * by weight. Used to keep track of whether all ++ * @bfq_groups have the same weight. The tree contains ++ * one counter for each distinct weight associated to ++ * some active @bfq_group (see the comments to the ++ * functions bfq_weights_tree_[add|remove] for further ++ * details). ++ * @busy_queues: number of bfq_queues containing requests (including the ++ * queue in service, even if it is idling). ++ * @busy_in_flight_queues: number of @bfq_queues containing pending or ++ * in-flight requests, plus the @bfq_queue in ++ * service, even if idle but waiting for the ++ * possible arrival of its next sync request. This ++ * field is updated only if the device is rotational, ++ * but used only if the device is also NCQ-capable. ++ * The reason why the field is updated also for non- ++ * NCQ-capable rotational devices is related to the ++ * fact that the value of @hw_tag may be set also ++ * later than when busy_in_flight_queues may need to ++ * be incremented for the first time(s). Taking also ++ * this possibility into account, to avoid unbalanced ++ * increments/decrements, would imply more overhead ++ * than just updating busy_in_flight_queues ++ * regardless of the value of @hw_tag. ++ * @const_seeky_busy_in_flight_queues: number of constantly-seeky @bfq_queues ++ * (that is, seeky queues that expired ++ * for budget timeout at least once) ++ * containing pending or in-flight ++ * requests, including the in-service ++ * @bfq_queue if constantly seeky. This ++ * field is updated only if the device ++ * is rotational, but used only if the ++ * device is also NCQ-capable (see the ++ * comments to @busy_in_flight_queues). ++ * @wr_busy_queues: number of weight-raised busy @bfq_queues. ++ * @queued: number of queued requests. ++ * @rq_in_driver: number of requests dispatched and waiting for completion. ++ * @sync_flight: number of sync requests in the driver. ++ * @max_rq_in_driver: max number of reqs in driver in the last ++ * @hw_tag_samples completed requests. ++ * @hw_tag_samples: nr of samples used to calculate hw_tag. ++ * @hw_tag: flag set to one if the driver is showing a queueing behavior. ++ * @budgets_assigned: number of budgets assigned. ++ * @idle_slice_timer: timer set when idling for the next sequential request ++ * from the queue in service. ++ * @unplug_work: delayed work to restart dispatching on the request queue. ++ * @in_service_queue: bfq_queue in service. ++ * @in_service_bic: bfq_io_cq (bic) associated with the @in_service_queue. ++ * @last_position: on-disk position of the last served request. ++ * @last_budget_start: beginning of the last budget. ++ * @last_idling_start: beginning of the last idle slice. ++ * @peak_rate: peak transfer rate observed for a budget. ++ * @peak_rate_samples: number of samples used to calculate @peak_rate. ++ * @bfq_max_budget: maximum budget allotted to a bfq_queue before ++ * rescheduling. ++ * @group_list: list of all the bfq_groups active on the device. ++ * @active_list: list of all the bfq_queues active on the device. ++ * @idle_list: list of all the bfq_queues idle on the device. ++ * @bfq_quantum: max number of requests dispatched per dispatch round. ++ * @bfq_fifo_expire: timeout for async/sync requests; when it expires ++ * requests are served in fifo order. ++ * @bfq_back_penalty: weight of backward seeks wrt forward ones. ++ * @bfq_back_max: maximum allowed backward seek. ++ * @bfq_slice_idle: maximum idling time. ++ * @bfq_user_max_budget: user-configured max budget value ++ * (0 for auto-tuning). ++ * @bfq_max_budget_async_rq: maximum budget (in nr of requests) allotted to ++ * async queues. ++ * @bfq_timeout: timeout for bfq_queues to consume their budget; used to ++ * to prevent seeky queues to impose long latencies to well ++ * behaved ones (this also implies that seeky queues cannot ++ * receive guarantees in the service domain; after a timeout ++ * they are charged for the whole allocated budget, to try ++ * to preserve a behavior reasonably fair among them, but ++ * without service-domain guarantees). ++ * @bfq_coop_thresh: number of queue merges after which a @bfq_queue is ++ * no more granted any weight-raising. ++ * @bfq_failed_cooperations: number of consecutive failed cooperation ++ * chances after which weight-raising is restored ++ * to a queue subject to more than bfq_coop_thresh ++ * queue merges. ++ * @bfq_requests_within_timer: number of consecutive requests that must be ++ * issued within the idle time slice to set ++ * again idling to a queue which was marked as ++ * non-I/O-bound (see the definition of the ++ * IO_bound flag for further details). ++ * @last_ins_in_burst: last time at which a queue entered the current ++ * burst of queues being activated shortly after ++ * each other; for more details about this and the ++ * following parameters related to a burst of ++ * activations, see the comments to the function ++ * @bfq_handle_burst. ++ * @bfq_burst_interval: reference time interval used to decide whether a ++ * queue has been activated shortly after ++ * @last_ins_in_burst. ++ * @burst_size: number of queues in the current burst of queue activations. ++ * @bfq_large_burst_thresh: maximum burst size above which the current ++ * queue-activation burst is deemed as 'large'. ++ * @large_burst: true if a large queue-activation burst is in progress. ++ * @burst_list: head of the burst list (as for the above fields, more details ++ * in the comments to the function bfq_handle_burst). ++ * @low_latency: if set to true, low-latency heuristics are enabled. ++ * @bfq_wr_coeff: maximum factor by which the weight of a weight-raised ++ * queue is multiplied. ++ * @bfq_wr_max_time: maximum duration of a weight-raising period (jiffies). ++ * @bfq_wr_rt_max_time: maximum duration for soft real-time processes. ++ * @bfq_wr_min_idle_time: minimum idle period after which weight-raising ++ * may be reactivated for a queue (in jiffies). ++ * @bfq_wr_min_inter_arr_async: minimum period between request arrivals ++ * after which weight-raising may be ++ * reactivated for an already busy queue ++ * (in jiffies). ++ * @bfq_wr_max_softrt_rate: max service-rate for a soft real-time queue, ++ * sectors per seconds. ++ * @RT_prod: cached value of the product R*T used for computing the maximum ++ * duration of the weight raising automatically. ++ * @device_speed: device-speed class for the low-latency heuristic. ++ * @oom_bfqq: fallback dummy bfqq for extreme OOM conditions. ++ * ++ * All the fields are protected by the @queue lock. ++ */ ++struct bfq_data { ++ struct request_queue *queue; ++ ++ struct bfq_group *root_group; ++ struct rb_root rq_pos_tree; ++ ++#ifdef CONFIG_CGROUP_BFQIO ++ int active_numerous_groups; ++#endif ++ ++ struct rb_root queue_weights_tree; ++ struct rb_root group_weights_tree; ++ ++ int busy_queues; ++ int busy_in_flight_queues; ++ int const_seeky_busy_in_flight_queues; ++ int wr_busy_queues; ++ int queued; ++ int rq_in_driver; ++ int sync_flight; ++ ++ int max_rq_in_driver; ++ int hw_tag_samples; ++ int hw_tag; ++ ++ int budgets_assigned; ++ ++ struct timer_list idle_slice_timer; ++ struct work_struct unplug_work; ++ ++ struct bfq_queue *in_service_queue; ++ struct bfq_io_cq *in_service_bic; ++ ++ sector_t last_position; ++ ++ ktime_t last_budget_start; ++ ktime_t last_idling_start; ++ int peak_rate_samples; ++ u64 peak_rate; ++ unsigned long bfq_max_budget; ++ ++ struct hlist_head group_list; ++ struct list_head active_list; ++ struct list_head idle_list; ++ ++ unsigned int bfq_quantum; ++ unsigned int bfq_fifo_expire[2]; ++ unsigned int bfq_back_penalty; ++ unsigned int bfq_back_max; ++ unsigned int bfq_slice_idle; ++ u64 bfq_class_idle_last_service; ++ ++ unsigned int bfq_user_max_budget; ++ unsigned int bfq_max_budget_async_rq; ++ unsigned int bfq_timeout[2]; ++ ++ unsigned int bfq_coop_thresh; ++ unsigned int bfq_failed_cooperations; ++ unsigned int bfq_requests_within_timer; ++ ++ unsigned long last_ins_in_burst; ++ unsigned long bfq_burst_interval; ++ int burst_size; ++ unsigned long bfq_large_burst_thresh; ++ bool large_burst; ++ struct hlist_head burst_list; ++ ++ bool low_latency; ++ ++ /* parameters of the low_latency heuristics */ ++ unsigned int bfq_wr_coeff; ++ unsigned int bfq_wr_max_time; ++ unsigned int bfq_wr_rt_max_time; ++ unsigned int bfq_wr_min_idle_time; ++ unsigned long bfq_wr_min_inter_arr_async; ++ unsigned int bfq_wr_max_softrt_rate; ++ u64 RT_prod; ++ enum bfq_device_speed device_speed; ++ ++ struct bfq_queue oom_bfqq; ++}; ++ ++enum bfqq_state_flags { ++ BFQ_BFQQ_FLAG_busy = 0, /* has requests or is in service */ ++ BFQ_BFQQ_FLAG_wait_request, /* waiting for a request */ ++ BFQ_BFQQ_FLAG_must_alloc, /* must be allowed rq alloc */ ++ BFQ_BFQQ_FLAG_fifo_expire, /* FIFO checked in this slice */ ++ BFQ_BFQQ_FLAG_idle_window, /* slice idling enabled */ ++ BFQ_BFQQ_FLAG_prio_changed, /* task priority has changed */ ++ BFQ_BFQQ_FLAG_sync, /* synchronous queue */ ++ BFQ_BFQQ_FLAG_budget_new, /* no completion with this budget */ ++ BFQ_BFQQ_FLAG_IO_bound, /* ++ * bfqq has timed-out at least once ++ * having consumed at most 2/10 of ++ * its budget ++ */ ++ BFQ_BFQQ_FLAG_in_large_burst, /* ++ * bfqq activated in a large burst, ++ * see comments to bfq_handle_burst. ++ */ ++ BFQ_BFQQ_FLAG_constantly_seeky, /* ++ * bfqq has proved to be slow and ++ * seeky until budget timeout ++ */ ++ BFQ_BFQQ_FLAG_softrt_update, /* ++ * may need softrt-next-start ++ * update ++ */ ++ BFQ_BFQQ_FLAG_coop, /* bfqq is shared */ ++ BFQ_BFQQ_FLAG_split_coop, /* shared bfqq will be splitted */ ++}; ++ ++#define BFQ_BFQQ_FNS(name) \ ++static inline void bfq_mark_bfqq_##name(struct bfq_queue *bfqq) \ ++{ \ ++ (bfqq)->flags |= (1 << BFQ_BFQQ_FLAG_##name); \ ++} \ ++static inline void bfq_clear_bfqq_##name(struct bfq_queue *bfqq) \ ++{ \ ++ (bfqq)->flags &= ~(1 << BFQ_BFQQ_FLAG_##name); \ ++} \ ++static inline int bfq_bfqq_##name(const struct bfq_queue *bfqq) \ ++{ \ ++ return ((bfqq)->flags & (1 << BFQ_BFQQ_FLAG_##name)) != 0; \ ++} ++ ++BFQ_BFQQ_FNS(busy); ++BFQ_BFQQ_FNS(wait_request); ++BFQ_BFQQ_FNS(must_alloc); ++BFQ_BFQQ_FNS(fifo_expire); ++BFQ_BFQQ_FNS(idle_window); ++BFQ_BFQQ_FNS(prio_changed); ++BFQ_BFQQ_FNS(sync); ++BFQ_BFQQ_FNS(budget_new); ++BFQ_BFQQ_FNS(IO_bound); ++BFQ_BFQQ_FNS(in_large_burst); ++BFQ_BFQQ_FNS(constantly_seeky); ++BFQ_BFQQ_FNS(coop); ++BFQ_BFQQ_FNS(split_coop); ++BFQ_BFQQ_FNS(softrt_update); ++#undef BFQ_BFQQ_FNS ++ ++/* Logging facilities. */ ++#define bfq_log_bfqq(bfqd, bfqq, fmt, args...) \ ++ blk_add_trace_msg((bfqd)->queue, "bfq%d " fmt, (bfqq)->pid, ##args) ++ ++#define bfq_log(bfqd, fmt, args...) \ ++ blk_add_trace_msg((bfqd)->queue, "bfq " fmt, ##args) ++ ++/* Expiration reasons. */ ++enum bfqq_expiration { ++ BFQ_BFQQ_TOO_IDLE = 0, /* ++ * queue has been idling for ++ * too long ++ */ ++ BFQ_BFQQ_BUDGET_TIMEOUT, /* budget took too long to be used */ ++ BFQ_BFQQ_BUDGET_EXHAUSTED, /* budget consumed */ ++ BFQ_BFQQ_NO_MORE_REQUESTS, /* the queue has no more requests */ ++}; ++ ++#ifdef CONFIG_CGROUP_BFQIO ++/** ++ * struct bfq_group - per (device, cgroup) data structure. ++ * @entity: schedulable entity to insert into the parent group sched_data. ++ * @sched_data: own sched_data, to contain child entities (they may be ++ * both bfq_queues and bfq_groups). ++ * @group_node: node to be inserted into the bfqio_cgroup->group_data ++ * list of the containing cgroup's bfqio_cgroup. ++ * @bfqd_node: node to be inserted into the @bfqd->group_list list ++ * of the groups active on the same device; used for cleanup. ++ * @bfqd: the bfq_data for the device this group acts upon. ++ * @async_bfqq: array of async queues for all the tasks belonging to ++ * the group, one queue per ioprio value per ioprio_class, ++ * except for the idle class that has only one queue. ++ * @async_idle_bfqq: async queue for the idle class (ioprio is ignored). ++ * @my_entity: pointer to @entity, %NULL for the toplevel group; used ++ * to avoid too many special cases during group creation/ ++ * migration. ++ * @active_entities: number of active entities belonging to the group; ++ * unused for the root group. Used to know whether there ++ * are groups with more than one active @bfq_entity ++ * (see the comments to the function ++ * bfq_bfqq_must_not_expire()). ++ * ++ * Each (device, cgroup) pair has its own bfq_group, i.e., for each cgroup ++ * there is a set of bfq_groups, each one collecting the lower-level ++ * entities belonging to the group that are acting on the same device. ++ * ++ * Locking works as follows: ++ * o @group_node is protected by the bfqio_cgroup lock, and is accessed ++ * via RCU from its readers. ++ * o @bfqd is protected by the queue lock, RCU is used to access it ++ * from the readers. ++ * o All the other fields are protected by the @bfqd queue lock. ++ */ ++struct bfq_group { ++ struct bfq_entity entity; ++ struct bfq_sched_data sched_data; ++ ++ struct hlist_node group_node; ++ struct hlist_node bfqd_node; ++ ++ void *bfqd; ++ ++ struct bfq_queue *async_bfqq[2][IOPRIO_BE_NR]; ++ struct bfq_queue *async_idle_bfqq; ++ ++ struct bfq_entity *my_entity; ++ ++ int active_entities; ++}; ++ ++/** ++ * struct bfqio_cgroup - bfq cgroup data structure. ++ * @css: subsystem state for bfq in the containing cgroup. ++ * @online: flag marked when the subsystem is inserted. ++ * @weight: cgroup weight. ++ * @ioprio: cgroup ioprio. ++ * @ioprio_class: cgroup ioprio_class. ++ * @lock: spinlock that protects @ioprio, @ioprio_class and @group_data. ++ * @group_data: list containing the bfq_group belonging to this cgroup. ++ * ++ * @group_data is accessed using RCU, with @lock protecting the updates, ++ * @ioprio and @ioprio_class are protected by @lock. ++ */ ++struct bfqio_cgroup { ++ struct cgroup_subsys_state css; ++ bool online; ++ ++ unsigned short weight, ioprio, ioprio_class; ++ ++ spinlock_t lock; ++ struct hlist_head group_data; ++}; ++#else ++struct bfq_group { ++ struct bfq_sched_data sched_data; ++ ++ struct bfq_queue *async_bfqq[2][IOPRIO_BE_NR]; ++ struct bfq_queue *async_idle_bfqq; ++}; ++#endif ++ ++static inline struct bfq_service_tree * ++bfq_entity_service_tree(struct bfq_entity *entity) ++{ ++ struct bfq_sched_data *sched_data = entity->sched_data; ++ unsigned int idx = entity->ioprio_class - 1; ++ ++ BUG_ON(idx >= BFQ_IOPRIO_CLASSES); ++ BUG_ON(sched_data == NULL); ++ ++ return sched_data->service_tree + idx; ++} ++ ++static inline struct bfq_queue *bic_to_bfqq(struct bfq_io_cq *bic, ++ bool is_sync) ++{ ++ return bic->bfqq[is_sync]; ++} ++ ++static inline void bic_set_bfqq(struct bfq_io_cq *bic, ++ struct bfq_queue *bfqq, bool is_sync) ++{ ++ bic->bfqq[is_sync] = bfqq; ++} ++ ++static inline struct bfq_data *bic_to_bfqd(struct bfq_io_cq *bic) ++{ ++ return bic->icq.q->elevator->elevator_data; ++} ++ ++/** ++ * bfq_get_bfqd_locked - get a lock to a bfqd using a RCU protected pointer. ++ * @ptr: a pointer to a bfqd. ++ * @flags: storage for the flags to be saved. ++ * ++ * This function allows bfqg->bfqd to be protected by the ++ * queue lock of the bfqd they reference; the pointer is dereferenced ++ * under RCU, so the storage for bfqd is assured to be safe as long ++ * as the RCU read side critical section does not end. After the ++ * bfqd->queue->queue_lock is taken the pointer is rechecked, to be ++ * sure that no other writer accessed it. If we raced with a writer, ++ * the function returns NULL, with the queue unlocked, otherwise it ++ * returns the dereferenced pointer, with the queue locked. ++ */ ++static inline struct bfq_data *bfq_get_bfqd_locked(void **ptr, ++ unsigned long *flags) ++{ ++ struct bfq_data *bfqd; ++ ++ rcu_read_lock(); ++ bfqd = rcu_dereference(*(struct bfq_data **)ptr); ++ ++ if (bfqd != NULL) { ++ spin_lock_irqsave(bfqd->queue->queue_lock, *flags); ++ if (*ptr == bfqd) ++ goto out; ++ spin_unlock_irqrestore(bfqd->queue->queue_lock, *flags); ++ } ++ ++ bfqd = NULL; ++out: ++ rcu_read_unlock(); ++ return bfqd; ++} ++ ++static inline void bfq_put_bfqd_unlock(struct bfq_data *bfqd, ++ unsigned long *flags) ++{ ++ spin_unlock_irqrestore(bfqd->queue->queue_lock, *flags); ++} ++ ++static void bfq_changed_ioprio(struct bfq_io_cq *bic); ++static void bfq_put_queue(struct bfq_queue *bfqq); ++static void bfq_dispatch_insert(struct request_queue *q, struct request *rq); ++static struct bfq_queue *bfq_get_queue(struct bfq_data *bfqd, ++ struct bfq_group *bfqg, int is_sync, ++ struct bfq_io_cq *bic, gfp_t gfp_mask); ++static void bfq_end_wr_async_queues(struct bfq_data *bfqd, ++ struct bfq_group *bfqg); ++static void bfq_put_async_queues(struct bfq_data *bfqd, struct bfq_group *bfqg); ++static void bfq_exit_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq); ++ ++#endif /* _BFQ_H */ +-- +2.3.0 + diff --git a/kernel/tools/cpupowertools/files/patches/gentoo/5002_block-introduce-the-BFQ-v7r7-I-O-sched-for-3.19.patch1.txt b/kernel/tools/cpupowertools/files/patches/gentoo/5002_block-introduce-the-BFQ-v7r7-I-O-sched-for-3.19.patch1.txt new file mode 100644 index 00000000..fb96ff28 --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/gentoo/5002_block-introduce-the-BFQ-v7r7-I-O-sched-for-3.19.patch1.txt @@ -0,0 +1,6966 @@ +From 5bfaaa91a51940efaccb66bc5cd562ba3b9d4053 Mon Sep 17 00:00:00 2001 +From: Paolo Valente +Date: Thu, 9 May 2013 19:10:02 +0200 +Subject: [PATCH 2/3] block: introduce the BFQ-v7r7 I/O sched for 3.19 + +Add the BFQ-v7r7 I/O scheduler to 3.19. +The general structure is borrowed from CFQ, as much of the code for +handling I/O contexts. Over time, several useful features have been +ported from CFQ as well (details in the changelog in README.BFQ). A +(bfq_)queue is associated to each task doing I/O on a device, and each +time a scheduling decision has to be made a queue is selected and served +until it expires. + + - Slices are given in the service domain: tasks are assigned + budgets, measured in number of sectors. Once got the disk, a task + must however consume its assigned budget within a configurable + maximum time (by default, the maximum possible value of the + budgets is automatically computed to comply with this timeout). + This allows the desired latency vs "throughput boosting" tradeoff + to be set. + + - Budgets are scheduled according to a variant of WF2Q+, implemented + using an augmented rb-tree to take eligibility into account while + preserving an O(log N) overall complexity. + + - A low-latency tunable is provided; if enabled, both interactive + and soft real-time applications are guaranteed a very low latency. + + - Latency guarantees are preserved also in the presence of NCQ. + + - Also with flash-based devices, a high throughput is achieved + while still preserving latency guarantees. + + - BFQ features Early Queue Merge (EQM), a sort of fusion of the + cooperating-queue-merging and the preemption mechanisms present + in CFQ. EQM is in fact a unified mechanism that tries to get a + sequential read pattern, and hence a high throughput, with any + set of processes performing interleaved I/O over a contiguous + sequence of sectors. + + - BFQ supports full hierarchical scheduling, exporting a cgroups + interface. Since each node has a full scheduler, each group can + be assigned its own weight. + + - If the cgroups interface is not used, only I/O priorities can be + assigned to processes, with ioprio values mapped to weights + with the relation weight = IOPRIO_BE_NR - ioprio. + + - ioprio classes are served in strict priority order, i.e., lower + priority queues are not served as long as there are higher + priority queues. Among queues in the same class the bandwidth is + distributed in proportion to the weight of each queue. A very + thin extra bandwidth is however guaranteed to the Idle class, to + prevent it from starving. + +Signed-off-by: Paolo Valente +Signed-off-by: Arianna Avanzini +--- + block/bfq-cgroup.c | 936 ++++++++++++ + block/bfq-ioc.c | 36 + + block/bfq-iosched.c | 3902 +++++++++++++++++++++++++++++++++++++++++++++++++++ + block/bfq-sched.c | 1214 ++++++++++++++++ + block/bfq.h | 775 ++++++++++ + 5 files changed, 6863 insertions(+) + create mode 100644 block/bfq-cgroup.c + create mode 100644 block/bfq-ioc.c + create mode 100644 block/bfq-iosched.c + create mode 100644 block/bfq-sched.c + create mode 100644 block/bfq.h + +diff --git a/block/bfq-cgroup.c b/block/bfq-cgroup.c +new file mode 100644 +index 0000000..11e2f1d +--- /dev/null ++++ b/block/bfq-cgroup.c +@@ -0,0 +1,936 @@ ++/* ++ * BFQ: CGROUPS support. ++ * ++ * Based on ideas and code from CFQ: ++ * Copyright (C) 2003 Jens Axboe ++ * ++ * Copyright (C) 2008 Fabio Checconi ++ * Paolo Valente ++ * ++ * Copyright (C) 2010 Paolo Valente ++ * ++ * Licensed under the GPL-2 as detailed in the accompanying COPYING.BFQ ++ * file. ++ */ ++ ++#ifdef CONFIG_CGROUP_BFQIO ++ ++static DEFINE_MUTEX(bfqio_mutex); ++ ++static bool bfqio_is_removed(struct bfqio_cgroup *bgrp) ++{ ++ return bgrp ? !bgrp->online : false; ++} ++ ++static struct bfqio_cgroup bfqio_root_cgroup = { ++ .weight = BFQ_DEFAULT_GRP_WEIGHT, ++ .ioprio = BFQ_DEFAULT_GRP_IOPRIO, ++ .ioprio_class = BFQ_DEFAULT_GRP_CLASS, ++}; ++ ++static inline void bfq_init_entity(struct bfq_entity *entity, ++ struct bfq_group *bfqg) ++{ ++ entity->weight = entity->new_weight; ++ entity->orig_weight = entity->new_weight; ++ entity->ioprio = entity->new_ioprio; ++ entity->ioprio_class = entity->new_ioprio_class; ++ entity->parent = bfqg->my_entity; ++ entity->sched_data = &bfqg->sched_data; ++} ++ ++static struct bfqio_cgroup *css_to_bfqio(struct cgroup_subsys_state *css) ++{ ++ return css ? container_of(css, struct bfqio_cgroup, css) : NULL; ++} ++ ++/* ++ * Search the bfq_group for bfqd into the hash table (by now only a list) ++ * of bgrp. Must be called under rcu_read_lock(). ++ */ ++static struct bfq_group *bfqio_lookup_group(struct bfqio_cgroup *bgrp, ++ struct bfq_data *bfqd) ++{ ++ struct bfq_group *bfqg; ++ void *key; ++ ++ hlist_for_each_entry_rcu(bfqg, &bgrp->group_data, group_node) { ++ key = rcu_dereference(bfqg->bfqd); ++ if (key == bfqd) ++ return bfqg; ++ } ++ ++ return NULL; ++} ++ ++static inline void bfq_group_init_entity(struct bfqio_cgroup *bgrp, ++ struct bfq_group *bfqg) ++{ ++ struct bfq_entity *entity = &bfqg->entity; ++ ++ /* ++ * If the weight of the entity has never been set via the sysfs ++ * interface, then bgrp->weight == 0. In this case we initialize ++ * the weight from the current ioprio value. Otherwise, the group ++ * weight, if set, has priority over the ioprio value. ++ */ ++ if (bgrp->weight == 0) { ++ entity->new_weight = bfq_ioprio_to_weight(bgrp->ioprio); ++ entity->new_ioprio = bgrp->ioprio; ++ } else { ++ if (bgrp->weight < BFQ_MIN_WEIGHT || ++ bgrp->weight > BFQ_MAX_WEIGHT) { ++ printk(KERN_CRIT "bfq_group_init_entity: " ++ "bgrp->weight %d\n", bgrp->weight); ++ BUG(); ++ } ++ entity->new_weight = bgrp->weight; ++ entity->new_ioprio = bfq_weight_to_ioprio(bgrp->weight); ++ } ++ entity->orig_weight = entity->weight = entity->new_weight; ++ entity->ioprio = entity->new_ioprio; ++ entity->ioprio_class = entity->new_ioprio_class = bgrp->ioprio_class; ++ entity->my_sched_data = &bfqg->sched_data; ++ bfqg->active_entities = 0; ++} ++ ++static inline void bfq_group_set_parent(struct bfq_group *bfqg, ++ struct bfq_group *parent) ++{ ++ struct bfq_entity *entity; ++ ++ BUG_ON(parent == NULL); ++ BUG_ON(bfqg == NULL); ++ ++ entity = &bfqg->entity; ++ entity->parent = parent->my_entity; ++ entity->sched_data = &parent->sched_data; ++} ++ ++/** ++ * bfq_group_chain_alloc - allocate a chain of groups. ++ * @bfqd: queue descriptor. ++ * @css: the leaf cgroup_subsys_state this chain starts from. ++ * ++ * Allocate a chain of groups starting from the one belonging to ++ * @cgroup up to the root cgroup. Stop if a cgroup on the chain ++ * to the root has already an allocated group on @bfqd. ++ */ ++static struct bfq_group *bfq_group_chain_alloc(struct bfq_data *bfqd, ++ struct cgroup_subsys_state *css) ++{ ++ struct bfqio_cgroup *bgrp; ++ struct bfq_group *bfqg, *prev = NULL, *leaf = NULL; ++ ++ for (; css != NULL; css = css->parent) { ++ bgrp = css_to_bfqio(css); ++ ++ bfqg = bfqio_lookup_group(bgrp, bfqd); ++ if (bfqg != NULL) { ++ /* ++ * All the cgroups in the path from there to the ++ * root must have a bfq_group for bfqd, so we don't ++ * need any more allocations. ++ */ ++ break; ++ } ++ ++ bfqg = kzalloc(sizeof(*bfqg), GFP_ATOMIC); ++ if (bfqg == NULL) ++ goto cleanup; ++ ++ bfq_group_init_entity(bgrp, bfqg); ++ bfqg->my_entity = &bfqg->entity; ++ ++ if (leaf == NULL) { ++ leaf = bfqg; ++ prev = leaf; ++ } else { ++ bfq_group_set_parent(prev, bfqg); ++ /* ++ * Build a list of allocated nodes using the bfqd ++ * filed, that is still unused and will be ++ * initialized only after the node will be ++ * connected. ++ */ ++ prev->bfqd = bfqg; ++ prev = bfqg; ++ } ++ } ++ ++ return leaf; ++ ++cleanup: ++ while (leaf != NULL) { ++ prev = leaf; ++ leaf = leaf->bfqd; ++ kfree(prev); ++ } ++ ++ return NULL; ++} ++ ++/** ++ * bfq_group_chain_link - link an allocated group chain to a cgroup ++ * hierarchy. ++ * @bfqd: the queue descriptor. ++ * @css: the leaf cgroup_subsys_state to start from. ++ * @leaf: the leaf group (to be associated to @cgroup). ++ * ++ * Try to link a chain of groups to a cgroup hierarchy, connecting the ++ * nodes bottom-up, so we can be sure that when we find a cgroup in the ++ * hierarchy that already as a group associated to @bfqd all the nodes ++ * in the path to the root cgroup have one too. ++ * ++ * On locking: the queue lock protects the hierarchy (there is a hierarchy ++ * per device) while the bfqio_cgroup lock protects the list of groups ++ * belonging to the same cgroup. ++ */ ++static void bfq_group_chain_link(struct bfq_data *bfqd, ++ struct cgroup_subsys_state *css, ++ struct bfq_group *leaf) ++{ ++ struct bfqio_cgroup *bgrp; ++ struct bfq_group *bfqg, *next, *prev = NULL; ++ unsigned long flags; ++ ++ assert_spin_locked(bfqd->queue->queue_lock); ++ ++ for (; css != NULL && leaf != NULL; css = css->parent) { ++ bgrp = css_to_bfqio(css); ++ next = leaf->bfqd; ++ ++ bfqg = bfqio_lookup_group(bgrp, bfqd); ++ BUG_ON(bfqg != NULL); ++ ++ spin_lock_irqsave(&bgrp->lock, flags); ++ ++ rcu_assign_pointer(leaf->bfqd, bfqd); ++ hlist_add_head_rcu(&leaf->group_node, &bgrp->group_data); ++ hlist_add_head(&leaf->bfqd_node, &bfqd->group_list); ++ ++ spin_unlock_irqrestore(&bgrp->lock, flags); ++ ++ prev = leaf; ++ leaf = next; ++ } ++ ++ BUG_ON(css == NULL && leaf != NULL); ++ if (css != NULL && prev != NULL) { ++ bgrp = css_to_bfqio(css); ++ bfqg = bfqio_lookup_group(bgrp, bfqd); ++ bfq_group_set_parent(prev, bfqg); ++ } ++} ++ ++/** ++ * bfq_find_alloc_group - return the group associated to @bfqd in @cgroup. ++ * @bfqd: queue descriptor. ++ * @cgroup: cgroup being searched for. ++ * ++ * Return a group associated to @bfqd in @cgroup, allocating one if ++ * necessary. When a group is returned all the cgroups in the path ++ * to the root have a group associated to @bfqd. ++ * ++ * If the allocation fails, return the root group: this breaks guarantees ++ * but is a safe fallback. If this loss becomes a problem it can be ++ * mitigated using the equivalent weight (given by the product of the ++ * weights of the groups in the path from @group to the root) in the ++ * root scheduler. ++ * ++ * We allocate all the missing nodes in the path from the leaf cgroup ++ * to the root and we connect the nodes only after all the allocations ++ * have been successful. ++ */ ++static struct bfq_group *bfq_find_alloc_group(struct bfq_data *bfqd, ++ struct cgroup_subsys_state *css) ++{ ++ struct bfqio_cgroup *bgrp = css_to_bfqio(css); ++ struct bfq_group *bfqg; ++ ++ bfqg = bfqio_lookup_group(bgrp, bfqd); ++ if (bfqg != NULL) ++ return bfqg; ++ ++ bfqg = bfq_group_chain_alloc(bfqd, css); ++ if (bfqg != NULL) ++ bfq_group_chain_link(bfqd, css, bfqg); ++ else ++ bfqg = bfqd->root_group; ++ ++ return bfqg; ++} ++ ++/** ++ * bfq_bfqq_move - migrate @bfqq to @bfqg. ++ * @bfqd: queue descriptor. ++ * @bfqq: the queue to move. ++ * @entity: @bfqq's entity. ++ * @bfqg: the group to move to. ++ * ++ * Move @bfqq to @bfqg, deactivating it from its old group and reactivating ++ * it on the new one. Avoid putting the entity on the old group idle tree. ++ * ++ * Must be called under the queue lock; the cgroup owning @bfqg must ++ * not disappear (by now this just means that we are called under ++ * rcu_read_lock()). ++ */ ++static void bfq_bfqq_move(struct bfq_data *bfqd, struct bfq_queue *bfqq, ++ struct bfq_entity *entity, struct bfq_group *bfqg) ++{ ++ int busy, resume; ++ ++ busy = bfq_bfqq_busy(bfqq); ++ resume = !RB_EMPTY_ROOT(&bfqq->sort_list); ++ ++ BUG_ON(resume && !entity->on_st); ++ BUG_ON(busy && !resume && entity->on_st && ++ bfqq != bfqd->in_service_queue); ++ ++ if (busy) { ++ BUG_ON(atomic_read(&bfqq->ref) < 2); ++ ++ if (!resume) ++ bfq_del_bfqq_busy(bfqd, bfqq, 0); ++ else ++ bfq_deactivate_bfqq(bfqd, bfqq, 0); ++ } else if (entity->on_st) ++ bfq_put_idle_entity(bfq_entity_service_tree(entity), entity); ++ ++ /* ++ * Here we use a reference to bfqg. We don't need a refcounter ++ * as the cgroup reference will not be dropped, so that its ++ * destroy() callback will not be invoked. ++ */ ++ entity->parent = bfqg->my_entity; ++ entity->sched_data = &bfqg->sched_data; ++ ++ if (busy && resume) ++ bfq_activate_bfqq(bfqd, bfqq); ++ ++ if (bfqd->in_service_queue == NULL && !bfqd->rq_in_driver) ++ bfq_schedule_dispatch(bfqd); ++} ++ ++/** ++ * __bfq_bic_change_cgroup - move @bic to @cgroup. ++ * @bfqd: the queue descriptor. ++ * @bic: the bic to move. ++ * @cgroup: the cgroup to move to. ++ * ++ * Move bic to cgroup, assuming that bfqd->queue is locked; the caller ++ * has to make sure that the reference to cgroup is valid across the call. ++ * ++ * NOTE: an alternative approach might have been to store the current ++ * cgroup in bfqq and getting a reference to it, reducing the lookup ++ * time here, at the price of slightly more complex code. ++ */ ++static struct bfq_group *__bfq_bic_change_cgroup(struct bfq_data *bfqd, ++ struct bfq_io_cq *bic, ++ struct cgroup_subsys_state *css) ++{ ++ struct bfq_queue *async_bfqq = bic_to_bfqq(bic, 0); ++ struct bfq_queue *sync_bfqq = bic_to_bfqq(bic, 1); ++ struct bfq_entity *entity; ++ struct bfq_group *bfqg; ++ struct bfqio_cgroup *bgrp; ++ ++ bgrp = css_to_bfqio(css); ++ ++ bfqg = bfq_find_alloc_group(bfqd, css); ++ if (async_bfqq != NULL) { ++ entity = &async_bfqq->entity; ++ ++ if (entity->sched_data != &bfqg->sched_data) { ++ bic_set_bfqq(bic, NULL, 0); ++ bfq_log_bfqq(bfqd, async_bfqq, ++ "bic_change_group: %p %d", ++ async_bfqq, atomic_read(&async_bfqq->ref)); ++ bfq_put_queue(async_bfqq); ++ } ++ } ++ ++ if (sync_bfqq != NULL) { ++ entity = &sync_bfqq->entity; ++ if (entity->sched_data != &bfqg->sched_data) ++ bfq_bfqq_move(bfqd, sync_bfqq, entity, bfqg); ++ } ++ ++ return bfqg; ++} ++ ++/** ++ * bfq_bic_change_cgroup - move @bic to @cgroup. ++ * @bic: the bic being migrated. ++ * @cgroup: the destination cgroup. ++ * ++ * When the task owning @bic is moved to @cgroup, @bic is immediately ++ * moved into its new parent group. ++ */ ++static void bfq_bic_change_cgroup(struct bfq_io_cq *bic, ++ struct cgroup_subsys_state *css) ++{ ++ struct bfq_data *bfqd; ++ unsigned long uninitialized_var(flags); ++ ++ bfqd = bfq_get_bfqd_locked(&(bic->icq.q->elevator->elevator_data), ++ &flags); ++ if (bfqd != NULL) { ++ __bfq_bic_change_cgroup(bfqd, bic, css); ++ bfq_put_bfqd_unlock(bfqd, &flags); ++ } ++} ++ ++/** ++ * bfq_bic_update_cgroup - update the cgroup of @bic. ++ * @bic: the @bic to update. ++ * ++ * Make sure that @bic is enqueued in the cgroup of the current task. ++ * We need this in addition to moving bics during the cgroup attach ++ * phase because the task owning @bic could be at its first disk ++ * access or we may end up in the root cgroup as the result of a ++ * memory allocation failure and here we try to move to the right ++ * group. ++ * ++ * Must be called under the queue lock. It is safe to use the returned ++ * value even after the rcu_read_unlock() as the migration/destruction ++ * paths act under the queue lock too. IOW it is impossible to race with ++ * group migration/destruction and end up with an invalid group as: ++ * a) here cgroup has not yet been destroyed, nor its destroy callback ++ * has started execution, as current holds a reference to it, ++ * b) if it is destroyed after rcu_read_unlock() [after current is ++ * migrated to a different cgroup] its attach() callback will have ++ * taken care of remove all the references to the old cgroup data. ++ */ ++static struct bfq_group *bfq_bic_update_cgroup(struct bfq_io_cq *bic) ++{ ++ struct bfq_data *bfqd = bic_to_bfqd(bic); ++ struct bfq_group *bfqg; ++ struct cgroup_subsys_state *css; ++ ++ BUG_ON(bfqd == NULL); ++ ++ rcu_read_lock(); ++ css = task_css(current, bfqio_cgrp_id); ++ bfqg = __bfq_bic_change_cgroup(bfqd, bic, css); ++ rcu_read_unlock(); ++ ++ return bfqg; ++} ++ ++/** ++ * bfq_flush_idle_tree - deactivate any entity on the idle tree of @st. ++ * @st: the service tree being flushed. ++ */ ++static inline void bfq_flush_idle_tree(struct bfq_service_tree *st) ++{ ++ struct bfq_entity *entity = st->first_idle; ++ ++ for (; entity != NULL; entity = st->first_idle) ++ __bfq_deactivate_entity(entity, 0); ++} ++ ++/** ++ * bfq_reparent_leaf_entity - move leaf entity to the root_group. ++ * @bfqd: the device data structure with the root group. ++ * @entity: the entity to move. ++ */ ++static inline void bfq_reparent_leaf_entity(struct bfq_data *bfqd, ++ struct bfq_entity *entity) ++{ ++ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); ++ ++ BUG_ON(bfqq == NULL); ++ bfq_bfqq_move(bfqd, bfqq, entity, bfqd->root_group); ++ return; ++} ++ ++/** ++ * bfq_reparent_active_entities - move to the root group all active ++ * entities. ++ * @bfqd: the device data structure with the root group. ++ * @bfqg: the group to move from. ++ * @st: the service tree with the entities. ++ * ++ * Needs queue_lock to be taken and reference to be valid over the call. ++ */ ++static inline void bfq_reparent_active_entities(struct bfq_data *bfqd, ++ struct bfq_group *bfqg, ++ struct bfq_service_tree *st) ++{ ++ struct rb_root *active = &st->active; ++ struct bfq_entity *entity = NULL; ++ ++ if (!RB_EMPTY_ROOT(&st->active)) ++ entity = bfq_entity_of(rb_first(active)); ++ ++ for (; entity != NULL; entity = bfq_entity_of(rb_first(active))) ++ bfq_reparent_leaf_entity(bfqd, entity); ++ ++ if (bfqg->sched_data.in_service_entity != NULL) ++ bfq_reparent_leaf_entity(bfqd, ++ bfqg->sched_data.in_service_entity); ++ ++ return; ++} ++ ++/** ++ * bfq_destroy_group - destroy @bfqg. ++ * @bgrp: the bfqio_cgroup containing @bfqg. ++ * @bfqg: the group being destroyed. ++ * ++ * Destroy @bfqg, making sure that it is not referenced from its parent. ++ */ ++static void bfq_destroy_group(struct bfqio_cgroup *bgrp, struct bfq_group *bfqg) ++{ ++ struct bfq_data *bfqd; ++ struct bfq_service_tree *st; ++ struct bfq_entity *entity = bfqg->my_entity; ++ unsigned long uninitialized_var(flags); ++ int i; ++ ++ hlist_del(&bfqg->group_node); ++ ++ /* ++ * Empty all service_trees belonging to this group before ++ * deactivating the group itself. ++ */ ++ for (i = 0; i < BFQ_IOPRIO_CLASSES; i++) { ++ st = bfqg->sched_data.service_tree + i; ++ ++ /* ++ * The idle tree may still contain bfq_queues belonging ++ * to exited task because they never migrated to a different ++ * cgroup from the one being destroyed now. No one else ++ * can access them so it's safe to act without any lock. ++ */ ++ bfq_flush_idle_tree(st); ++ ++ /* ++ * It may happen that some queues are still active ++ * (busy) upon group destruction (if the corresponding ++ * processes have been forced to terminate). We move ++ * all the leaf entities corresponding to these queues ++ * to the root_group. ++ * Also, it may happen that the group has an entity ++ * in service, which is disconnected from the active ++ * tree: it must be moved, too. ++ * There is no need to put the sync queues, as the ++ * scheduler has taken no reference. ++ */ ++ bfqd = bfq_get_bfqd_locked(&bfqg->bfqd, &flags); ++ if (bfqd != NULL) { ++ bfq_reparent_active_entities(bfqd, bfqg, st); ++ bfq_put_bfqd_unlock(bfqd, &flags); ++ } ++ BUG_ON(!RB_EMPTY_ROOT(&st->active)); ++ BUG_ON(!RB_EMPTY_ROOT(&st->idle)); ++ } ++ BUG_ON(bfqg->sched_data.next_in_service != NULL); ++ BUG_ON(bfqg->sched_data.in_service_entity != NULL); ++ ++ /* ++ * We may race with device destruction, take extra care when ++ * dereferencing bfqg->bfqd. ++ */ ++ bfqd = bfq_get_bfqd_locked(&bfqg->bfqd, &flags); ++ if (bfqd != NULL) { ++ hlist_del(&bfqg->bfqd_node); ++ __bfq_deactivate_entity(entity, 0); ++ bfq_put_async_queues(bfqd, bfqg); ++ bfq_put_bfqd_unlock(bfqd, &flags); ++ } ++ BUG_ON(entity->tree != NULL); ++ ++ /* ++ * No need to defer the kfree() to the end of the RCU grace ++ * period: we are called from the destroy() callback of our ++ * cgroup, so we can be sure that no one is a) still using ++ * this cgroup or b) doing lookups in it. ++ */ ++ kfree(bfqg); ++} ++ ++static void bfq_end_wr_async(struct bfq_data *bfqd) ++{ ++ struct hlist_node *tmp; ++ struct bfq_group *bfqg; ++ ++ hlist_for_each_entry_safe(bfqg, tmp, &bfqd->group_list, bfqd_node) ++ bfq_end_wr_async_queues(bfqd, bfqg); ++ bfq_end_wr_async_queues(bfqd, bfqd->root_group); ++} ++ ++/** ++ * bfq_disconnect_groups - disconnect @bfqd from all its groups. ++ * @bfqd: the device descriptor being exited. ++ * ++ * When the device exits we just make sure that no lookup can return ++ * the now unused group structures. They will be deallocated on cgroup ++ * destruction. ++ */ ++static void bfq_disconnect_groups(struct bfq_data *bfqd) ++{ ++ struct hlist_node *tmp; ++ struct bfq_group *bfqg; ++ ++ bfq_log(bfqd, "disconnect_groups beginning"); ++ hlist_for_each_entry_safe(bfqg, tmp, &bfqd->group_list, bfqd_node) { ++ hlist_del(&bfqg->bfqd_node); ++ ++ __bfq_deactivate_entity(bfqg->my_entity, 0); ++ ++ /* ++ * Don't remove from the group hash, just set an ++ * invalid key. No lookups can race with the ++ * assignment as bfqd is being destroyed; this ++ * implies also that new elements cannot be added ++ * to the list. ++ */ ++ rcu_assign_pointer(bfqg->bfqd, NULL); ++ ++ bfq_log(bfqd, "disconnect_groups: put async for group %p", ++ bfqg); ++ bfq_put_async_queues(bfqd, bfqg); ++ } ++} ++ ++static inline void bfq_free_root_group(struct bfq_data *bfqd) ++{ ++ struct bfqio_cgroup *bgrp = &bfqio_root_cgroup; ++ struct bfq_group *bfqg = bfqd->root_group; ++ ++ bfq_put_async_queues(bfqd, bfqg); ++ ++ spin_lock_irq(&bgrp->lock); ++ hlist_del_rcu(&bfqg->group_node); ++ spin_unlock_irq(&bgrp->lock); ++ ++ /* ++ * No need to synchronize_rcu() here: since the device is gone ++ * there cannot be any read-side access to its root_group. ++ */ ++ kfree(bfqg); ++} ++ ++static struct bfq_group *bfq_alloc_root_group(struct bfq_data *bfqd, int node) ++{ ++ struct bfq_group *bfqg; ++ struct bfqio_cgroup *bgrp; ++ int i; ++ ++ bfqg = kzalloc_node(sizeof(*bfqg), GFP_KERNEL, node); ++ if (bfqg == NULL) ++ return NULL; ++ ++ bfqg->entity.parent = NULL; ++ for (i = 0; i < BFQ_IOPRIO_CLASSES; i++) ++ bfqg->sched_data.service_tree[i] = BFQ_SERVICE_TREE_INIT; ++ ++ bgrp = &bfqio_root_cgroup; ++ spin_lock_irq(&bgrp->lock); ++ rcu_assign_pointer(bfqg->bfqd, bfqd); ++ hlist_add_head_rcu(&bfqg->group_node, &bgrp->group_data); ++ spin_unlock_irq(&bgrp->lock); ++ ++ return bfqg; ++} ++ ++#define SHOW_FUNCTION(__VAR) \ ++static u64 bfqio_cgroup_##__VAR##_read(struct cgroup_subsys_state *css, \ ++ struct cftype *cftype) \ ++{ \ ++ struct bfqio_cgroup *bgrp = css_to_bfqio(css); \ ++ u64 ret = -ENODEV; \ ++ \ ++ mutex_lock(&bfqio_mutex); \ ++ if (bfqio_is_removed(bgrp)) \ ++ goto out_unlock; \ ++ \ ++ spin_lock_irq(&bgrp->lock); \ ++ ret = bgrp->__VAR; \ ++ spin_unlock_irq(&bgrp->lock); \ ++ \ ++out_unlock: \ ++ mutex_unlock(&bfqio_mutex); \ ++ return ret; \ ++} ++ ++SHOW_FUNCTION(weight); ++SHOW_FUNCTION(ioprio); ++SHOW_FUNCTION(ioprio_class); ++#undef SHOW_FUNCTION ++ ++#define STORE_FUNCTION(__VAR, __MIN, __MAX) \ ++static int bfqio_cgroup_##__VAR##_write(struct cgroup_subsys_state *css,\ ++ struct cftype *cftype, \ ++ u64 val) \ ++{ \ ++ struct bfqio_cgroup *bgrp = css_to_bfqio(css); \ ++ struct bfq_group *bfqg; \ ++ int ret = -EINVAL; \ ++ \ ++ if (val < (__MIN) || val > (__MAX)) \ ++ return ret; \ ++ \ ++ ret = -ENODEV; \ ++ mutex_lock(&bfqio_mutex); \ ++ if (bfqio_is_removed(bgrp)) \ ++ goto out_unlock; \ ++ ret = 0; \ ++ \ ++ spin_lock_irq(&bgrp->lock); \ ++ bgrp->__VAR = (unsigned short)val; \ ++ hlist_for_each_entry(bfqg, &bgrp->group_data, group_node) { \ ++ /* \ ++ * Setting the ioprio_changed flag of the entity \ ++ * to 1 with new_##__VAR == ##__VAR would re-set \ ++ * the value of the weight to its ioprio mapping. \ ++ * Set the flag only if necessary. \ ++ */ \ ++ if ((unsigned short)val != bfqg->entity.new_##__VAR) { \ ++ bfqg->entity.new_##__VAR = (unsigned short)val; \ ++ /* \ ++ * Make sure that the above new value has been \ ++ * stored in bfqg->entity.new_##__VAR before \ ++ * setting the ioprio_changed flag. In fact, \ ++ * this flag may be read asynchronously (in \ ++ * critical sections protected by a different \ ++ * lock than that held here), and finding this \ ++ * flag set may cause the execution of the code \ ++ * for updating parameters whose value may \ ++ * depend also on bfqg->entity.new_##__VAR (in \ ++ * __bfq_entity_update_weight_prio). \ ++ * This barrier makes sure that the new value \ ++ * of bfqg->entity.new_##__VAR is correctly \ ++ * seen in that code. \ ++ */ \ ++ smp_wmb(); \ ++ bfqg->entity.ioprio_changed = 1; \ ++ } \ ++ } \ ++ spin_unlock_irq(&bgrp->lock); \ ++ \ ++out_unlock: \ ++ mutex_unlock(&bfqio_mutex); \ ++ return ret; \ ++} ++ ++STORE_FUNCTION(weight, BFQ_MIN_WEIGHT, BFQ_MAX_WEIGHT); ++STORE_FUNCTION(ioprio, 0, IOPRIO_BE_NR - 1); ++STORE_FUNCTION(ioprio_class, IOPRIO_CLASS_RT, IOPRIO_CLASS_IDLE); ++#undef STORE_FUNCTION ++ ++static struct cftype bfqio_files[] = { ++ { ++ .name = "weight", ++ .read_u64 = bfqio_cgroup_weight_read, ++ .write_u64 = bfqio_cgroup_weight_write, ++ }, ++ { ++ .name = "ioprio", ++ .read_u64 = bfqio_cgroup_ioprio_read, ++ .write_u64 = bfqio_cgroup_ioprio_write, ++ }, ++ { ++ .name = "ioprio_class", ++ .read_u64 = bfqio_cgroup_ioprio_class_read, ++ .write_u64 = bfqio_cgroup_ioprio_class_write, ++ }, ++ { }, /* terminate */ ++}; ++ ++static struct cgroup_subsys_state *bfqio_create(struct cgroup_subsys_state ++ *parent_css) ++{ ++ struct bfqio_cgroup *bgrp; ++ ++ if (parent_css != NULL) { ++ bgrp = kzalloc(sizeof(*bgrp), GFP_KERNEL); ++ if (bgrp == NULL) ++ return ERR_PTR(-ENOMEM); ++ } else ++ bgrp = &bfqio_root_cgroup; ++ ++ spin_lock_init(&bgrp->lock); ++ INIT_HLIST_HEAD(&bgrp->group_data); ++ bgrp->ioprio = BFQ_DEFAULT_GRP_IOPRIO; ++ bgrp->ioprio_class = BFQ_DEFAULT_GRP_CLASS; ++ ++ return &bgrp->css; ++} ++ ++/* ++ * We cannot support shared io contexts, as we have no means to support ++ * two tasks with the same ioc in two different groups without major rework ++ * of the main bic/bfqq data structures. By now we allow a task to change ++ * its cgroup only if it's the only owner of its ioc; the drawback of this ++ * behavior is that a group containing a task that forked using CLONE_IO ++ * will not be destroyed until the tasks sharing the ioc die. ++ */ ++static int bfqio_can_attach(struct cgroup_subsys_state *css, ++ struct cgroup_taskset *tset) ++{ ++ struct task_struct *task; ++ struct io_context *ioc; ++ int ret = 0; ++ ++ cgroup_taskset_for_each(task, tset) { ++ /* ++ * task_lock() is needed to avoid races with ++ * exit_io_context() ++ */ ++ task_lock(task); ++ ioc = task->io_context; ++ if (ioc != NULL && atomic_read(&ioc->nr_tasks) > 1) ++ /* ++ * ioc == NULL means that the task is either too ++ * young or exiting: if it has still no ioc the ++ * ioc can't be shared, if the task is exiting the ++ * attach will fail anyway, no matter what we ++ * return here. ++ */ ++ ret = -EINVAL; ++ task_unlock(task); ++ if (ret) ++ break; ++ } ++ ++ return ret; ++} ++ ++static void bfqio_attach(struct cgroup_subsys_state *css, ++ struct cgroup_taskset *tset) ++{ ++ struct task_struct *task; ++ struct io_context *ioc; ++ struct io_cq *icq; ++ ++ /* ++ * IMPORTANT NOTE: The move of more than one process at a time to a ++ * new group has not yet been tested. ++ */ ++ cgroup_taskset_for_each(task, tset) { ++ ioc = get_task_io_context(task, GFP_ATOMIC, NUMA_NO_NODE); ++ if (ioc) { ++ /* ++ * Handle cgroup change here. ++ */ ++ rcu_read_lock(); ++ hlist_for_each_entry_rcu(icq, &ioc->icq_list, ioc_node) ++ if (!strncmp( ++ icq->q->elevator->type->elevator_name, ++ "bfq", ELV_NAME_MAX)) ++ bfq_bic_change_cgroup(icq_to_bic(icq), ++ css); ++ rcu_read_unlock(); ++ put_io_context(ioc); ++ } ++ } ++} ++ ++static void bfqio_destroy(struct cgroup_subsys_state *css) ++{ ++ struct bfqio_cgroup *bgrp = css_to_bfqio(css); ++ struct hlist_node *tmp; ++ struct bfq_group *bfqg; ++ ++ /* ++ * Since we are destroying the cgroup, there are no more tasks ++ * referencing it, and all the RCU grace periods that may have ++ * referenced it are ended (as the destruction of the parent ++ * cgroup is RCU-safe); bgrp->group_data will not be accessed by ++ * anything else and we don't need any synchronization. ++ */ ++ hlist_for_each_entry_safe(bfqg, tmp, &bgrp->group_data, group_node) ++ bfq_destroy_group(bgrp, bfqg); ++ ++ BUG_ON(!hlist_empty(&bgrp->group_data)); ++ ++ kfree(bgrp); ++} ++ ++static int bfqio_css_online(struct cgroup_subsys_state *css) ++{ ++ struct bfqio_cgroup *bgrp = css_to_bfqio(css); ++ ++ mutex_lock(&bfqio_mutex); ++ bgrp->online = true; ++ mutex_unlock(&bfqio_mutex); ++ ++ return 0; ++} ++ ++static void bfqio_css_offline(struct cgroup_subsys_state *css) ++{ ++ struct bfqio_cgroup *bgrp = css_to_bfqio(css); ++ ++ mutex_lock(&bfqio_mutex); ++ bgrp->online = false; ++ mutex_unlock(&bfqio_mutex); ++} ++ ++struct cgroup_subsys bfqio_cgrp_subsys = { ++ .css_alloc = bfqio_create, ++ .css_online = bfqio_css_online, ++ .css_offline = bfqio_css_offline, ++ .can_attach = bfqio_can_attach, ++ .attach = bfqio_attach, ++ .css_free = bfqio_destroy, ++ .legacy_cftypes = bfqio_files, ++}; ++#else ++static inline void bfq_init_entity(struct bfq_entity *entity, ++ struct bfq_group *bfqg) ++{ ++ entity->weight = entity->new_weight; ++ entity->orig_weight = entity->new_weight; ++ entity->ioprio = entity->new_ioprio; ++ entity->ioprio_class = entity->new_ioprio_class; ++ entity->sched_data = &bfqg->sched_data; ++} ++ ++static inline struct bfq_group * ++bfq_bic_update_cgroup(struct bfq_io_cq *bic) ++{ ++ struct bfq_data *bfqd = bic_to_bfqd(bic); ++ return bfqd->root_group; ++} ++ ++static inline void bfq_bfqq_move(struct bfq_data *bfqd, ++ struct bfq_queue *bfqq, ++ struct bfq_entity *entity, ++ struct bfq_group *bfqg) ++{ ++} ++ ++static void bfq_end_wr_async(struct bfq_data *bfqd) ++{ ++ bfq_end_wr_async_queues(bfqd, bfqd->root_group); ++} ++ ++static inline void bfq_disconnect_groups(struct bfq_data *bfqd) ++{ ++ bfq_put_async_queues(bfqd, bfqd->root_group); ++} ++ ++static inline void bfq_free_root_group(struct bfq_data *bfqd) ++{ ++ kfree(bfqd->root_group); ++} ++ ++static struct bfq_group *bfq_alloc_root_group(struct bfq_data *bfqd, int node) ++{ ++ struct bfq_group *bfqg; ++ int i; ++ ++ bfqg = kmalloc_node(sizeof(*bfqg), GFP_KERNEL | __GFP_ZERO, node); ++ if (bfqg == NULL) ++ return NULL; ++ ++ for (i = 0; i < BFQ_IOPRIO_CLASSES; i++) ++ bfqg->sched_data.service_tree[i] = BFQ_SERVICE_TREE_INIT; ++ ++ return bfqg; ++} ++#endif +diff --git a/block/bfq-ioc.c b/block/bfq-ioc.c +new file mode 100644 +index 0000000..7f6b000 +--- /dev/null ++++ b/block/bfq-ioc.c +@@ -0,0 +1,36 @@ ++/* ++ * BFQ: I/O context handling. ++ * ++ * Based on ideas and code from CFQ: ++ * Copyright (C) 2003 Jens Axboe ++ * ++ * Copyright (C) 2008 Fabio Checconi ++ * Paolo Valente ++ * ++ * Copyright (C) 2010 Paolo Valente ++ */ ++ ++/** ++ * icq_to_bic - convert iocontext queue structure to bfq_io_cq. ++ * @icq: the iocontext queue. ++ */ ++static inline struct bfq_io_cq *icq_to_bic(struct io_cq *icq) ++{ ++ /* bic->icq is the first member, %NULL will convert to %NULL */ ++ return container_of(icq, struct bfq_io_cq, icq); ++} ++ ++/** ++ * bfq_bic_lookup - search into @ioc a bic associated to @bfqd. ++ * @bfqd: the lookup key. ++ * @ioc: the io_context of the process doing I/O. ++ * ++ * Queue lock must be held. ++ */ ++static inline struct bfq_io_cq *bfq_bic_lookup(struct bfq_data *bfqd, ++ struct io_context *ioc) ++{ ++ if (ioc) ++ return icq_to_bic(ioc_lookup_icq(ioc, bfqd->queue)); ++ return NULL; ++} +diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c +new file mode 100644 +index 0000000..97ee934 +--- /dev/null ++++ b/block/bfq-iosched.c +@@ -0,0 +1,3902 @@ ++/* ++ * Budget Fair Queueing (BFQ) disk scheduler. ++ * ++ * Based on ideas and code from CFQ: ++ * Copyright (C) 2003 Jens Axboe ++ * ++ * Copyright (C) 2008 Fabio Checconi ++ * Paolo Valente ++ * ++ * Copyright (C) 2010 Paolo Valente ++ * ++ * Licensed under the GPL-2 as detailed in the accompanying COPYING.BFQ ++ * file. ++ * ++ * BFQ is a proportional-share storage-I/O scheduling algorithm based on ++ * the slice-by-slice service scheme of CFQ. But BFQ assigns budgets, ++ * measured in number of sectors, to processes instead of time slices. The ++ * device is not granted to the in-service process for a given time slice, ++ * but until it has exhausted its assigned budget. This change from the time ++ * to the service domain allows BFQ to distribute the device throughput ++ * among processes as desired, without any distortion due to ZBR, workload ++ * fluctuations or other factors. BFQ uses an ad hoc internal scheduler, ++ * called B-WF2Q+, to schedule processes according to their budgets. More ++ * precisely, BFQ schedules queues associated to processes. Thanks to the ++ * accurate policy of B-WF2Q+, BFQ can afford to assign high budgets to ++ * I/O-bound processes issuing sequential requests (to boost the ++ * throughput), and yet guarantee a low latency to interactive and soft ++ * real-time applications. ++ * ++ * BFQ is described in [1], where also a reference to the initial, more ++ * theoretical paper on BFQ can be found. The interested reader can find ++ * in the latter paper full details on the main algorithm, as well as ++ * formulas of the guarantees and formal proofs of all the properties. ++ * With respect to the version of BFQ presented in these papers, this ++ * implementation adds a few more heuristics, such as the one that ++ * guarantees a low latency to soft real-time applications, and a ++ * hierarchical extension based on H-WF2Q+. ++ * ++ * B-WF2Q+ is based on WF2Q+, that is described in [2], together with ++ * H-WF2Q+, while the augmented tree used to implement B-WF2Q+ with O(log N) ++ * complexity derives from the one introduced with EEVDF in [3]. ++ * ++ * [1] P. Valente and M. Andreolini, ``Improving Application Responsiveness ++ * with the BFQ Disk I/O Scheduler'', ++ * Proceedings of the 5th Annual International Systems and Storage ++ * Conference (SYSTOR '12), June 2012. ++ * ++ * http://algogroup.unimo.it/people/paolo/disk_sched/bf1-v1-suite-results.pdf ++ * ++ * [2] Jon C.R. Bennett and H. Zhang, ``Hierarchical Packet Fair Queueing ++ * Algorithms,'' IEEE/ACM Transactions on Networking, 5(5):675-689, ++ * Oct 1997. ++ * ++ * http://www.cs.cmu.edu/~hzhang/papers/TON-97-Oct.ps.gz ++ * ++ * [3] I. Stoica and H. Abdel-Wahab, ``Earliest Eligible Virtual Deadline ++ * First: A Flexible and Accurate Mechanism for Proportional Share ++ * Resource Allocation,'' technical report. ++ * ++ * http://www.cs.berkeley.edu/~istoica/papers/eevdf-tr-95.pdf ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "bfq.h" ++#include "blk.h" ++ ++/* Max number of dispatches in one round of service. */ ++static const int bfq_quantum = 4; ++ ++/* Expiration time of sync (0) and async (1) requests, in jiffies. */ ++static const int bfq_fifo_expire[2] = { HZ / 4, HZ / 8 }; ++ ++/* Maximum backwards seek, in KiB. */ ++static const int bfq_back_max = 16 * 1024; ++ ++/* Penalty of a backwards seek, in number of sectors. */ ++static const int bfq_back_penalty = 2; ++ ++/* Idling period duration, in jiffies. */ ++static int bfq_slice_idle = HZ / 125; ++ ++/* Default maximum budget values, in sectors and number of requests. */ ++static const int bfq_default_max_budget = 16 * 1024; ++static const int bfq_max_budget_async_rq = 4; ++ ++/* ++ * Async to sync throughput distribution is controlled as follows: ++ * when an async request is served, the entity is charged the number ++ * of sectors of the request, multiplied by the factor below ++ */ ++static const int bfq_async_charge_factor = 10; ++ ++/* Default timeout values, in jiffies, approximating CFQ defaults. */ ++static const int bfq_timeout_sync = HZ / 8; ++static int bfq_timeout_async = HZ / 25; ++ ++struct kmem_cache *bfq_pool; ++ ++/* Below this threshold (in ms), we consider thinktime immediate. */ ++#define BFQ_MIN_TT 2 ++ ++/* hw_tag detection: parallel requests threshold and min samples needed. */ ++#define BFQ_HW_QUEUE_THRESHOLD 4 ++#define BFQ_HW_QUEUE_SAMPLES 32 ++ ++#define BFQQ_SEEK_THR (sector_t)(8 * 1024) ++#define BFQQ_SEEKY(bfqq) ((bfqq)->seek_mean > BFQQ_SEEK_THR) ++ ++/* Min samples used for peak rate estimation (for autotuning). */ ++#define BFQ_PEAK_RATE_SAMPLES 32 ++ ++/* Shift used for peak rate fixed precision calculations. */ ++#define BFQ_RATE_SHIFT 16 ++ ++/* ++ * By default, BFQ computes the duration of the weight raising for ++ * interactive applications automatically, using the following formula: ++ * duration = (R / r) * T, where r is the peak rate of the device, and ++ * R and T are two reference parameters. ++ * In particular, R is the peak rate of the reference device (see below), ++ * and T is a reference time: given the systems that are likely to be ++ * installed on the reference device according to its speed class, T is ++ * about the maximum time needed, under BFQ and while reading two files in ++ * parallel, to load typical large applications on these systems. ++ * In practice, the slower/faster the device at hand is, the more/less it ++ * takes to load applications with respect to the reference device. ++ * Accordingly, the longer/shorter BFQ grants weight raising to interactive ++ * applications. ++ * ++ * BFQ uses four different reference pairs (R, T), depending on: ++ * . whether the device is rotational or non-rotational; ++ * . whether the device is slow, such as old or portable HDDs, as well as ++ * SD cards, or fast, such as newer HDDs and SSDs. ++ * ++ * The device's speed class is dynamically (re)detected in ++ * bfq_update_peak_rate() every time the estimated peak rate is updated. ++ * ++ * In the following definitions, R_slow[0]/R_fast[0] and T_slow[0]/T_fast[0] ++ * are the reference values for a slow/fast rotational device, whereas ++ * R_slow[1]/R_fast[1] and T_slow[1]/T_fast[1] are the reference values for ++ * a slow/fast non-rotational device. Finally, device_speed_thresh are the ++ * thresholds used to switch between speed classes. ++ * Both the reference peak rates and the thresholds are measured in ++ * sectors/usec, left-shifted by BFQ_RATE_SHIFT. ++ */ ++static int R_slow[2] = {1536, 10752}; ++static int R_fast[2] = {17415, 34791}; ++/* ++ * To improve readability, a conversion function is used to initialize the ++ * following arrays, which entails that they can be initialized only in a ++ * function. ++ */ ++static int T_slow[2]; ++static int T_fast[2]; ++static int device_speed_thresh[2]; ++ ++#define BFQ_SERVICE_TREE_INIT ((struct bfq_service_tree) \ ++ { RB_ROOT, RB_ROOT, NULL, NULL, 0, 0 }) ++ ++#define RQ_BIC(rq) ((struct bfq_io_cq *) (rq)->elv.priv[0]) ++#define RQ_BFQQ(rq) ((rq)->elv.priv[1]) ++ ++static inline void bfq_schedule_dispatch(struct bfq_data *bfqd); ++ ++#include "bfq-ioc.c" ++#include "bfq-sched.c" ++#include "bfq-cgroup.c" ++ ++#define bfq_class_idle(bfqq) ((bfqq)->entity.ioprio_class ==\ ++ IOPRIO_CLASS_IDLE) ++#define bfq_class_rt(bfqq) ((bfqq)->entity.ioprio_class ==\ ++ IOPRIO_CLASS_RT) ++ ++#define bfq_sample_valid(samples) ((samples) > 80) ++ ++/* ++ * We regard a request as SYNC, if either it's a read or has the SYNC bit ++ * set (in which case it could also be a direct WRITE). ++ */ ++static inline int bfq_bio_sync(struct bio *bio) ++{ ++ if (bio_data_dir(bio) == READ || (bio->bi_rw & REQ_SYNC)) ++ return 1; ++ ++ return 0; ++} ++ ++/* ++ * Scheduler run of queue, if there are requests pending and no one in the ++ * driver that will restart queueing. ++ */ ++static inline void bfq_schedule_dispatch(struct bfq_data *bfqd) ++{ ++ if (bfqd->queued != 0) { ++ bfq_log(bfqd, "schedule dispatch"); ++ kblockd_schedule_work(&bfqd->unplug_work); ++ } ++} ++ ++/* ++ * Lifted from AS - choose which of rq1 and rq2 that is best served now. ++ * We choose the request that is closesr to the head right now. Distance ++ * behind the head is penalized and only allowed to a certain extent. ++ */ ++static struct request *bfq_choose_req(struct bfq_data *bfqd, ++ struct request *rq1, ++ struct request *rq2, ++ sector_t last) ++{ ++ sector_t s1, s2, d1 = 0, d2 = 0; ++ unsigned long back_max; ++#define BFQ_RQ1_WRAP 0x01 /* request 1 wraps */ ++#define BFQ_RQ2_WRAP 0x02 /* request 2 wraps */ ++ unsigned wrap = 0; /* bit mask: requests behind the disk head? */ ++ ++ if (rq1 == NULL || rq1 == rq2) ++ return rq2; ++ if (rq2 == NULL) ++ return rq1; ++ ++ if (rq_is_sync(rq1) && !rq_is_sync(rq2)) ++ return rq1; ++ else if (rq_is_sync(rq2) && !rq_is_sync(rq1)) ++ return rq2; ++ if ((rq1->cmd_flags & REQ_META) && !(rq2->cmd_flags & REQ_META)) ++ return rq1; ++ else if ((rq2->cmd_flags & REQ_META) && !(rq1->cmd_flags & REQ_META)) ++ return rq2; ++ ++ s1 = blk_rq_pos(rq1); ++ s2 = blk_rq_pos(rq2); ++ ++ /* ++ * By definition, 1KiB is 2 sectors. ++ */ ++ back_max = bfqd->bfq_back_max * 2; ++ ++ /* ++ * Strict one way elevator _except_ in the case where we allow ++ * short backward seeks which are biased as twice the cost of a ++ * similar forward seek. ++ */ ++ if (s1 >= last) ++ d1 = s1 - last; ++ else if (s1 + back_max >= last) ++ d1 = (last - s1) * bfqd->bfq_back_penalty; ++ else ++ wrap |= BFQ_RQ1_WRAP; ++ ++ if (s2 >= last) ++ d2 = s2 - last; ++ else if (s2 + back_max >= last) ++ d2 = (last - s2) * bfqd->bfq_back_penalty; ++ else ++ wrap |= BFQ_RQ2_WRAP; ++ ++ /* Found required data */ ++ ++ /* ++ * By doing switch() on the bit mask "wrap" we avoid having to ++ * check two variables for all permutations: --> faster! ++ */ ++ switch (wrap) { ++ case 0: /* common case for CFQ: rq1 and rq2 not wrapped */ ++ if (d1 < d2) ++ return rq1; ++ else if (d2 < d1) ++ return rq2; ++ else { ++ if (s1 >= s2) ++ return rq1; ++ else ++ return rq2; ++ } ++ ++ case BFQ_RQ2_WRAP: ++ return rq1; ++ case BFQ_RQ1_WRAP: ++ return rq2; ++ case (BFQ_RQ1_WRAP|BFQ_RQ2_WRAP): /* both rqs wrapped */ ++ default: ++ /* ++ * Since both rqs are wrapped, ++ * start with the one that's further behind head ++ * (--> only *one* back seek required), ++ * since back seek takes more time than forward. ++ */ ++ if (s1 <= s2) ++ return rq1; ++ else ++ return rq2; ++ } ++} ++ ++static struct bfq_queue * ++bfq_rq_pos_tree_lookup(struct bfq_data *bfqd, struct rb_root *root, ++ sector_t sector, struct rb_node **ret_parent, ++ struct rb_node ***rb_link) ++{ ++ struct rb_node **p, *parent; ++ struct bfq_queue *bfqq = NULL; ++ ++ parent = NULL; ++ p = &root->rb_node; ++ while (*p) { ++ struct rb_node **n; ++ ++ parent = *p; ++ bfqq = rb_entry(parent, struct bfq_queue, pos_node); ++ ++ /* ++ * Sort strictly based on sector. Smallest to the left, ++ * largest to the right. ++ */ ++ if (sector > blk_rq_pos(bfqq->next_rq)) ++ n = &(*p)->rb_right; ++ else if (sector < blk_rq_pos(bfqq->next_rq)) ++ n = &(*p)->rb_left; ++ else ++ break; ++ p = n; ++ bfqq = NULL; ++ } ++ ++ *ret_parent = parent; ++ if (rb_link) ++ *rb_link = p; ++ ++ bfq_log(bfqd, "rq_pos_tree_lookup %llu: returning %d", ++ (long long unsigned)sector, ++ bfqq != NULL ? bfqq->pid : 0); ++ ++ return bfqq; ++} ++ ++static void bfq_rq_pos_tree_add(struct bfq_data *bfqd, struct bfq_queue *bfqq) ++{ ++ struct rb_node **p, *parent; ++ struct bfq_queue *__bfqq; ++ ++ if (bfqq->pos_root != NULL) { ++ rb_erase(&bfqq->pos_node, bfqq->pos_root); ++ bfqq->pos_root = NULL; ++ } ++ ++ if (bfq_class_idle(bfqq)) ++ return; ++ if (!bfqq->next_rq) ++ return; ++ ++ bfqq->pos_root = &bfqd->rq_pos_tree; ++ __bfqq = bfq_rq_pos_tree_lookup(bfqd, bfqq->pos_root, ++ blk_rq_pos(bfqq->next_rq), &parent, &p); ++ if (__bfqq == NULL) { ++ rb_link_node(&bfqq->pos_node, parent, p); ++ rb_insert_color(&bfqq->pos_node, bfqq->pos_root); ++ } else ++ bfqq->pos_root = NULL; ++} ++ ++/* ++ * Tell whether there are active queues or groups with differentiated weights. ++ */ ++static inline bool bfq_differentiated_weights(struct bfq_data *bfqd) ++{ ++ BUG_ON(!bfqd->hw_tag); ++ /* ++ * For weights to differ, at least one of the trees must contain ++ * at least two nodes. ++ */ ++ return (!RB_EMPTY_ROOT(&bfqd->queue_weights_tree) && ++ (bfqd->queue_weights_tree.rb_node->rb_left || ++ bfqd->queue_weights_tree.rb_node->rb_right) ++#ifdef CONFIG_CGROUP_BFQIO ++ ) || ++ (!RB_EMPTY_ROOT(&bfqd->group_weights_tree) && ++ (bfqd->group_weights_tree.rb_node->rb_left || ++ bfqd->group_weights_tree.rb_node->rb_right) ++#endif ++ ); ++} ++ ++/* ++ * If the weight-counter tree passed as input contains no counter for ++ * the weight of the input entity, then add that counter; otherwise just ++ * increment the existing counter. ++ * ++ * Note that weight-counter trees contain few nodes in mostly symmetric ++ * scenarios. For example, if all queues have the same weight, then the ++ * weight-counter tree for the queues may contain at most one node. ++ * This holds even if low_latency is on, because weight-raised queues ++ * are not inserted in the tree. ++ * In most scenarios, the rate at which nodes are created/destroyed ++ * should be low too. ++ */ ++static void bfq_weights_tree_add(struct bfq_data *bfqd, ++ struct bfq_entity *entity, ++ struct rb_root *root) ++{ ++ struct rb_node **new = &(root->rb_node), *parent = NULL; ++ ++ /* ++ * Do not insert if: ++ * - the device does not support queueing; ++ * - the entity is already associated with a counter, which happens if: ++ * 1) the entity is associated with a queue, 2) a request arrival ++ * has caused the queue to become both non-weight-raised, and hence ++ * change its weight, and backlogged; in this respect, each ++ * of the two events causes an invocation of this function, ++ * 3) this is the invocation of this function caused by the second ++ * event. This second invocation is actually useless, and we handle ++ * this fact by exiting immediately. More efficient or clearer ++ * solutions might possibly be adopted. ++ */ ++ if (!bfqd->hw_tag || entity->weight_counter) ++ return; ++ ++ while (*new) { ++ struct bfq_weight_counter *__counter = container_of(*new, ++ struct bfq_weight_counter, ++ weights_node); ++ parent = *new; ++ ++ if (entity->weight == __counter->weight) { ++ entity->weight_counter = __counter; ++ goto inc_counter; ++ } ++ if (entity->weight < __counter->weight) ++ new = &((*new)->rb_left); ++ else ++ new = &((*new)->rb_right); ++ } ++ ++ entity->weight_counter = kzalloc(sizeof(struct bfq_weight_counter), ++ GFP_ATOMIC); ++ entity->weight_counter->weight = entity->weight; ++ rb_link_node(&entity->weight_counter->weights_node, parent, new); ++ rb_insert_color(&entity->weight_counter->weights_node, root); ++ ++inc_counter: ++ entity->weight_counter->num_active++; ++} ++ ++/* ++ * Decrement the weight counter associated with the entity, and, if the ++ * counter reaches 0, remove the counter from the tree. ++ * See the comments to the function bfq_weights_tree_add() for considerations ++ * about overhead. ++ */ ++static void bfq_weights_tree_remove(struct bfq_data *bfqd, ++ struct bfq_entity *entity, ++ struct rb_root *root) ++{ ++ /* ++ * Check whether the entity is actually associated with a counter. ++ * In fact, the device may not be considered NCQ-capable for a while, ++ * which implies that no insertion in the weight trees is performed, ++ * after which the device may start to be deemed NCQ-capable, and hence ++ * this function may start to be invoked. This may cause the function ++ * to be invoked for entities that are not associated with any counter. ++ */ ++ if (!entity->weight_counter) ++ return; ++ ++ BUG_ON(RB_EMPTY_ROOT(root)); ++ BUG_ON(entity->weight_counter->weight != entity->weight); ++ ++ BUG_ON(!entity->weight_counter->num_active); ++ entity->weight_counter->num_active--; ++ if (entity->weight_counter->num_active > 0) ++ goto reset_entity_pointer; ++ ++ rb_erase(&entity->weight_counter->weights_node, root); ++ kfree(entity->weight_counter); ++ ++reset_entity_pointer: ++ entity->weight_counter = NULL; ++} ++ ++static struct request *bfq_find_next_rq(struct bfq_data *bfqd, ++ struct bfq_queue *bfqq, ++ struct request *last) ++{ ++ struct rb_node *rbnext = rb_next(&last->rb_node); ++ struct rb_node *rbprev = rb_prev(&last->rb_node); ++ struct request *next = NULL, *prev = NULL; ++ ++ BUG_ON(RB_EMPTY_NODE(&last->rb_node)); ++ ++ if (rbprev != NULL) ++ prev = rb_entry_rq(rbprev); ++ ++ if (rbnext != NULL) ++ next = rb_entry_rq(rbnext); ++ else { ++ rbnext = rb_first(&bfqq->sort_list); ++ if (rbnext && rbnext != &last->rb_node) ++ next = rb_entry_rq(rbnext); ++ } ++ ++ return bfq_choose_req(bfqd, next, prev, blk_rq_pos(last)); ++} ++ ++/* see the definition of bfq_async_charge_factor for details */ ++static inline unsigned long bfq_serv_to_charge(struct request *rq, ++ struct bfq_queue *bfqq) ++{ ++ return blk_rq_sectors(rq) * ++ (1 + ((!bfq_bfqq_sync(bfqq)) * (bfqq->wr_coeff == 1) * ++ bfq_async_charge_factor)); ++} ++ ++/** ++ * bfq_updated_next_req - update the queue after a new next_rq selection. ++ * @bfqd: the device data the queue belongs to. ++ * @bfqq: the queue to update. ++ * ++ * If the first request of a queue changes we make sure that the queue ++ * has enough budget to serve at least its first request (if the ++ * request has grown). We do this because if the queue has not enough ++ * budget for its first request, it has to go through two dispatch ++ * rounds to actually get it dispatched. ++ */ ++static void bfq_updated_next_req(struct bfq_data *bfqd, ++ struct bfq_queue *bfqq) ++{ ++ struct bfq_entity *entity = &bfqq->entity; ++ struct bfq_service_tree *st = bfq_entity_service_tree(entity); ++ struct request *next_rq = bfqq->next_rq; ++ unsigned long new_budget; ++ ++ if (next_rq == NULL) ++ return; ++ ++ if (bfqq == bfqd->in_service_queue) ++ /* ++ * In order not to break guarantees, budgets cannot be ++ * changed after an entity has been selected. ++ */ ++ return; ++ ++ BUG_ON(entity->tree != &st->active); ++ BUG_ON(entity == entity->sched_data->in_service_entity); ++ ++ new_budget = max_t(unsigned long, bfqq->max_budget, ++ bfq_serv_to_charge(next_rq, bfqq)); ++ if (entity->budget != new_budget) { ++ entity->budget = new_budget; ++ bfq_log_bfqq(bfqd, bfqq, "updated next rq: new budget %lu", ++ new_budget); ++ bfq_activate_bfqq(bfqd, bfqq); ++ } ++} ++ ++static inline unsigned int bfq_wr_duration(struct bfq_data *bfqd) ++{ ++ u64 dur; ++ ++ if (bfqd->bfq_wr_max_time > 0) ++ return bfqd->bfq_wr_max_time; ++ ++ dur = bfqd->RT_prod; ++ do_div(dur, bfqd->peak_rate); ++ ++ return dur; ++} ++ ++/* Empty burst list and add just bfqq (see comments to bfq_handle_burst) */ ++static inline void bfq_reset_burst_list(struct bfq_data *bfqd, ++ struct bfq_queue *bfqq) ++{ ++ struct bfq_queue *item; ++ struct hlist_node *n; ++ ++ hlist_for_each_entry_safe(item, n, &bfqd->burst_list, burst_list_node) ++ hlist_del_init(&item->burst_list_node); ++ hlist_add_head(&bfqq->burst_list_node, &bfqd->burst_list); ++ bfqd->burst_size = 1; ++} ++ ++/* Add bfqq to the list of queues in current burst (see bfq_handle_burst) */ ++static void bfq_add_to_burst(struct bfq_data *bfqd, struct bfq_queue *bfqq) ++{ ++ /* Increment burst size to take into account also bfqq */ ++ bfqd->burst_size++; ++ ++ if (bfqd->burst_size == bfqd->bfq_large_burst_thresh) { ++ struct bfq_queue *pos, *bfqq_item; ++ struct hlist_node *n; ++ ++ /* ++ * Enough queues have been activated shortly after each ++ * other to consider this burst as large. ++ */ ++ bfqd->large_burst = true; ++ ++ /* ++ * We can now mark all queues in the burst list as ++ * belonging to a large burst. ++ */ ++ hlist_for_each_entry(bfqq_item, &bfqd->burst_list, ++ burst_list_node) ++ bfq_mark_bfqq_in_large_burst(bfqq_item); ++ bfq_mark_bfqq_in_large_burst(bfqq); ++ ++ /* ++ * From now on, and until the current burst finishes, any ++ * new queue being activated shortly after the last queue ++ * was inserted in the burst can be immediately marked as ++ * belonging to a large burst. So the burst list is not ++ * needed any more. Remove it. ++ */ ++ hlist_for_each_entry_safe(pos, n, &bfqd->burst_list, ++ burst_list_node) ++ hlist_del_init(&pos->burst_list_node); ++ } else /* burst not yet large: add bfqq to the burst list */ ++ hlist_add_head(&bfqq->burst_list_node, &bfqd->burst_list); ++} ++ ++/* ++ * If many queues happen to become active shortly after each other, then, ++ * to help the processes associated to these queues get their job done as ++ * soon as possible, it is usually better to not grant either weight-raising ++ * or device idling to these queues. In this comment we describe, firstly, ++ * the reasons why this fact holds, and, secondly, the next function, which ++ * implements the main steps needed to properly mark these queues so that ++ * they can then be treated in a different way. ++ * ++ * As for the terminology, we say that a queue becomes active, i.e., ++ * switches from idle to backlogged, either when it is created (as a ++ * consequence of the arrival of an I/O request), or, if already existing, ++ * when a new request for the queue arrives while the queue is idle. ++ * Bursts of activations, i.e., activations of different queues occurring ++ * shortly after each other, are typically caused by services or applications ++ * that spawn or reactivate many parallel threads/processes. Examples are ++ * systemd during boot or git grep. ++ * ++ * These services or applications benefit mostly from a high throughput: ++ * the quicker the requests of the activated queues are cumulatively served, ++ * the sooner the target job of these queues gets completed. As a consequence, ++ * weight-raising any of these queues, which also implies idling the device ++ * for it, is almost always counterproductive: in most cases it just lowers ++ * throughput. ++ * ++ * On the other hand, a burst of activations may be also caused by the start ++ * of an application that does not consist in a lot of parallel I/O-bound ++ * threads. In fact, with a complex application, the burst may be just a ++ * consequence of the fact that several processes need to be executed to ++ * start-up the application. To start an application as quickly as possible, ++ * the best thing to do is to privilege the I/O related to the application ++ * with respect to all other I/O. Therefore, the best strategy to start as ++ * quickly as possible an application that causes a burst of activations is ++ * to weight-raise all the queues activated during the burst. This is the ++ * exact opposite of the best strategy for the other type of bursts. ++ * ++ * In the end, to take the best action for each of the two cases, the two ++ * types of bursts need to be distinguished. Fortunately, this seems ++ * relatively easy to do, by looking at the sizes of the bursts. In ++ * particular, we found a threshold such that bursts with a larger size ++ * than that threshold are apparently caused only by services or commands ++ * such as systemd or git grep. For brevity, hereafter we call just 'large' ++ * these bursts. BFQ *does not* weight-raise queues whose activations occur ++ * in a large burst. In addition, for each of these queues BFQ performs or ++ * does not perform idling depending on which choice boosts the throughput ++ * most. The exact choice depends on the device and request pattern at ++ * hand. ++ * ++ * Turning back to the next function, it implements all the steps needed ++ * to detect the occurrence of a large burst and to properly mark all the ++ * queues belonging to it (so that they can then be treated in a different ++ * way). This goal is achieved by maintaining a special "burst list" that ++ * holds, temporarily, the queues that belong to the burst in progress. The ++ * list is then used to mark these queues as belonging to a large burst if ++ * the burst does become large. The main steps are the following. ++ * ++ * . when the very first queue is activated, the queue is inserted into the ++ * list (as it could be the first queue in a possible burst) ++ * ++ * . if the current burst has not yet become large, and a queue Q that does ++ * not yet belong to the burst is activated shortly after the last time ++ * at which a new queue entered the burst list, then the function appends ++ * Q to the burst list ++ * ++ * . if, as a consequence of the previous step, the burst size reaches ++ * the large-burst threshold, then ++ * ++ * . all the queues in the burst list are marked as belonging to a ++ * large burst ++ * ++ * . the burst list is deleted; in fact, the burst list already served ++ * its purpose (keeping temporarily track of the queues in a burst, ++ * so as to be able to mark them as belonging to a large burst in the ++ * previous sub-step), and now is not needed any more ++ * ++ * . the device enters a large-burst mode ++ * ++ * . if a queue Q that does not belong to the burst is activated while ++ * the device is in large-burst mode and shortly after the last time ++ * at which a queue either entered the burst list or was marked as ++ * belonging to the current large burst, then Q is immediately marked ++ * as belonging to a large burst. ++ * ++ * . if a queue Q that does not belong to the burst is activated a while ++ * later, i.e., not shortly after, than the last time at which a queue ++ * either entered the burst list or was marked as belonging to the ++ * current large burst, then the current burst is deemed as finished and: ++ * ++ * . the large-burst mode is reset if set ++ * ++ * . the burst list is emptied ++ * ++ * . Q is inserted in the burst list, as Q may be the first queue ++ * in a possible new burst (then the burst list contains just Q ++ * after this step). ++ */ ++static void bfq_handle_burst(struct bfq_data *bfqd, struct bfq_queue *bfqq, ++ bool idle_for_long_time) ++{ ++ /* ++ * If bfqq happened to be activated in a burst, but has been idle ++ * for at least as long as an interactive queue, then we assume ++ * that, in the overall I/O initiated in the burst, the I/O ++ * associated to bfqq is finished. So bfqq does not need to be ++ * treated as a queue belonging to a burst anymore. Accordingly, ++ * we reset bfqq's in_large_burst flag if set, and remove bfqq ++ * from the burst list if it's there. We do not decrement instead ++ * burst_size, because the fact that bfqq does not need to belong ++ * to the burst list any more does not invalidate the fact that ++ * bfqq may have been activated during the current burst. ++ */ ++ if (idle_for_long_time) { ++ hlist_del_init(&bfqq->burst_list_node); ++ bfq_clear_bfqq_in_large_burst(bfqq); ++ } ++ ++ /* ++ * If bfqq is already in the burst list or is part of a large ++ * burst, then there is nothing else to do. ++ */ ++ if (!hlist_unhashed(&bfqq->burst_list_node) || ++ bfq_bfqq_in_large_burst(bfqq)) ++ return; ++ ++ /* ++ * If bfqq's activation happens late enough, then the current ++ * burst is finished, and related data structures must be reset. ++ * ++ * In this respect, consider the special case where bfqq is the very ++ * first queue being activated. In this case, last_ins_in_burst is ++ * not yet significant when we get here. But it is easy to verify ++ * that, whether or not the following condition is true, bfqq will ++ * end up being inserted into the burst list. In particular the ++ * list will happen to contain only bfqq. And this is exactly what ++ * has to happen, as bfqq may be the first queue in a possible ++ * burst. ++ */ ++ if (time_is_before_jiffies(bfqd->last_ins_in_burst + ++ bfqd->bfq_burst_interval)) { ++ bfqd->large_burst = false; ++ bfq_reset_burst_list(bfqd, bfqq); ++ return; ++ } ++ ++ /* ++ * If we get here, then bfqq is being activated shortly after the ++ * last queue. So, if the current burst is also large, we can mark ++ * bfqq as belonging to this large burst immediately. ++ */ ++ if (bfqd->large_burst) { ++ bfq_mark_bfqq_in_large_burst(bfqq); ++ return; ++ } ++ ++ /* ++ * If we get here, then a large-burst state has not yet been ++ * reached, but bfqq is being activated shortly after the last ++ * queue. Then we add bfqq to the burst. ++ */ ++ bfq_add_to_burst(bfqd, bfqq); ++} ++ ++static void bfq_add_request(struct request *rq) ++{ ++ struct bfq_queue *bfqq = RQ_BFQQ(rq); ++ struct bfq_entity *entity = &bfqq->entity; ++ struct bfq_data *bfqd = bfqq->bfqd; ++ struct request *next_rq, *prev; ++ unsigned long old_wr_coeff = bfqq->wr_coeff; ++ bool interactive = false; ++ ++ bfq_log_bfqq(bfqd, bfqq, "add_request %d", rq_is_sync(rq)); ++ bfqq->queued[rq_is_sync(rq)]++; ++ bfqd->queued++; ++ ++ elv_rb_add(&bfqq->sort_list, rq); ++ ++ /* ++ * Check if this request is a better next-serve candidate. ++ */ ++ prev = bfqq->next_rq; ++ next_rq = bfq_choose_req(bfqd, bfqq->next_rq, rq, bfqd->last_position); ++ BUG_ON(next_rq == NULL); ++ bfqq->next_rq = next_rq; ++ ++ /* ++ * Adjust priority tree position, if next_rq changes. ++ */ ++ if (prev != bfqq->next_rq) ++ bfq_rq_pos_tree_add(bfqd, bfqq); ++ ++ if (!bfq_bfqq_busy(bfqq)) { ++ bool soft_rt, ++ idle_for_long_time = time_is_before_jiffies( ++ bfqq->budget_timeout + ++ bfqd->bfq_wr_min_idle_time); ++ ++ if (bfq_bfqq_sync(bfqq)) { ++ bool already_in_burst = ++ !hlist_unhashed(&bfqq->burst_list_node) || ++ bfq_bfqq_in_large_burst(bfqq); ++ bfq_handle_burst(bfqd, bfqq, idle_for_long_time); ++ /* ++ * If bfqq was not already in the current burst, ++ * then, at this point, bfqq either has been ++ * added to the current burst or has caused the ++ * current burst to terminate. In particular, in ++ * the second case, bfqq has become the first ++ * queue in a possible new burst. ++ * In both cases last_ins_in_burst needs to be ++ * moved forward. ++ */ ++ if (!already_in_burst) ++ bfqd->last_ins_in_burst = jiffies; ++ } ++ ++ soft_rt = bfqd->bfq_wr_max_softrt_rate > 0 && ++ !bfq_bfqq_in_large_burst(bfqq) && ++ time_is_before_jiffies(bfqq->soft_rt_next_start); ++ interactive = !bfq_bfqq_in_large_burst(bfqq) && ++ idle_for_long_time; ++ entity->budget = max_t(unsigned long, bfqq->max_budget, ++ bfq_serv_to_charge(next_rq, bfqq)); ++ ++ if (!bfq_bfqq_IO_bound(bfqq)) { ++ if (time_before(jiffies, ++ RQ_BIC(rq)->ttime.last_end_request + ++ bfqd->bfq_slice_idle)) { ++ bfqq->requests_within_timer++; ++ if (bfqq->requests_within_timer >= ++ bfqd->bfq_requests_within_timer) ++ bfq_mark_bfqq_IO_bound(bfqq); ++ } else ++ bfqq->requests_within_timer = 0; ++ } ++ ++ if (!bfqd->low_latency) ++ goto add_bfqq_busy; ++ ++ /* ++ * If the queue is not being boosted and has been idle ++ * for enough time, start a weight-raising period ++ */ ++ if (old_wr_coeff == 1 && (interactive || soft_rt)) { ++ bfqq->wr_coeff = bfqd->bfq_wr_coeff; ++ if (interactive) ++ bfqq->wr_cur_max_time = bfq_wr_duration(bfqd); ++ else ++ bfqq->wr_cur_max_time = ++ bfqd->bfq_wr_rt_max_time; ++ bfq_log_bfqq(bfqd, bfqq, ++ "wrais starting at %lu, rais_max_time %u", ++ jiffies, ++ jiffies_to_msecs(bfqq->wr_cur_max_time)); ++ } else if (old_wr_coeff > 1) { ++ if (interactive) ++ bfqq->wr_cur_max_time = bfq_wr_duration(bfqd); ++ else if (bfq_bfqq_in_large_burst(bfqq) || ++ (bfqq->wr_cur_max_time == ++ bfqd->bfq_wr_rt_max_time && ++ !soft_rt)) { ++ bfqq->wr_coeff = 1; ++ bfq_log_bfqq(bfqd, bfqq, ++ "wrais ending at %lu, rais_max_time %u", ++ jiffies, ++ jiffies_to_msecs(bfqq-> ++ wr_cur_max_time)); ++ } else if (time_before( ++ bfqq->last_wr_start_finish + ++ bfqq->wr_cur_max_time, ++ jiffies + ++ bfqd->bfq_wr_rt_max_time) && ++ soft_rt) { ++ /* ++ * ++ * The remaining weight-raising time is lower ++ * than bfqd->bfq_wr_rt_max_time, which ++ * means that the application is enjoying ++ * weight raising either because deemed soft- ++ * rt in the near past, or because deemed ++ * interactive a long ago. In both cases, ++ * resetting now the current remaining weight- ++ * raising time for the application to the ++ * weight-raising duration for soft rt ++ * applications would not cause any latency ++ * increase for the application (as the new ++ * duration would be higher than the remaining ++ * time). ++ * ++ * In addition, the application is now meeting ++ * the requirements for being deemed soft rt. ++ * In the end we can correctly and safely ++ * (re)charge the weight-raising duration for ++ * the application with the weight-raising ++ * duration for soft rt applications. ++ * ++ * In particular, doing this recharge now, i.e., ++ * before the weight-raising period for the ++ * application finishes, reduces the probability ++ * of the following negative scenario: ++ * 1) the weight of a soft rt application is ++ * raised at startup (as for any newly ++ * created application), ++ * 2) since the application is not interactive, ++ * at a certain time weight-raising is ++ * stopped for the application, ++ * 3) at that time the application happens to ++ * still have pending requests, and hence ++ * is destined to not have a chance to be ++ * deemed soft rt before these requests are ++ * completed (see the comments to the ++ * function bfq_bfqq_softrt_next_start() ++ * for details on soft rt detection), ++ * 4) these pending requests experience a high ++ * latency because the application is not ++ * weight-raised while they are pending. ++ */ ++ bfqq->last_wr_start_finish = jiffies; ++ bfqq->wr_cur_max_time = ++ bfqd->bfq_wr_rt_max_time; ++ } ++ } ++ if (old_wr_coeff != bfqq->wr_coeff) ++ entity->ioprio_changed = 1; ++add_bfqq_busy: ++ bfqq->last_idle_bklogged = jiffies; ++ bfqq->service_from_backlogged = 0; ++ bfq_clear_bfqq_softrt_update(bfqq); ++ bfq_add_bfqq_busy(bfqd, bfqq); ++ } else { ++ if (bfqd->low_latency && old_wr_coeff == 1 && !rq_is_sync(rq) && ++ time_is_before_jiffies( ++ bfqq->last_wr_start_finish + ++ bfqd->bfq_wr_min_inter_arr_async)) { ++ bfqq->wr_coeff = bfqd->bfq_wr_coeff; ++ bfqq->wr_cur_max_time = bfq_wr_duration(bfqd); ++ ++ bfqd->wr_busy_queues++; ++ entity->ioprio_changed = 1; ++ bfq_log_bfqq(bfqd, bfqq, ++ "non-idle wrais starting at %lu, rais_max_time %u", ++ jiffies, ++ jiffies_to_msecs(bfqq->wr_cur_max_time)); ++ } ++ if (prev != bfqq->next_rq) ++ bfq_updated_next_req(bfqd, bfqq); ++ } ++ ++ if (bfqd->low_latency && ++ (old_wr_coeff == 1 || bfqq->wr_coeff == 1 || interactive)) ++ bfqq->last_wr_start_finish = jiffies; ++} ++ ++static struct request *bfq_find_rq_fmerge(struct bfq_data *bfqd, ++ struct bio *bio) ++{ ++ struct task_struct *tsk = current; ++ struct bfq_io_cq *bic; ++ struct bfq_queue *bfqq; ++ ++ bic = bfq_bic_lookup(bfqd, tsk->io_context); ++ if (bic == NULL) ++ return NULL; ++ ++ bfqq = bic_to_bfqq(bic, bfq_bio_sync(bio)); ++ if (bfqq != NULL) ++ return elv_rb_find(&bfqq->sort_list, bio_end_sector(bio)); ++ ++ return NULL; ++} ++ ++static void bfq_activate_request(struct request_queue *q, struct request *rq) ++{ ++ struct bfq_data *bfqd = q->elevator->elevator_data; ++ ++ bfqd->rq_in_driver++; ++ bfqd->last_position = blk_rq_pos(rq) + blk_rq_sectors(rq); ++ bfq_log(bfqd, "activate_request: new bfqd->last_position %llu", ++ (long long unsigned)bfqd->last_position); ++} ++ ++static inline void bfq_deactivate_request(struct request_queue *q, ++ struct request *rq) ++{ ++ struct bfq_data *bfqd = q->elevator->elevator_data; ++ ++ BUG_ON(bfqd->rq_in_driver == 0); ++ bfqd->rq_in_driver--; ++} ++ ++static void bfq_remove_request(struct request *rq) ++{ ++ struct bfq_queue *bfqq = RQ_BFQQ(rq); ++ struct bfq_data *bfqd = bfqq->bfqd; ++ const int sync = rq_is_sync(rq); ++ ++ if (bfqq->next_rq == rq) { ++ bfqq->next_rq = bfq_find_next_rq(bfqd, bfqq, rq); ++ bfq_updated_next_req(bfqd, bfqq); ++ } ++ ++ list_del_init(&rq->queuelist); ++ BUG_ON(bfqq->queued[sync] == 0); ++ bfqq->queued[sync]--; ++ bfqd->queued--; ++ elv_rb_del(&bfqq->sort_list, rq); ++ ++ if (RB_EMPTY_ROOT(&bfqq->sort_list)) { ++ if (bfq_bfqq_busy(bfqq) && bfqq != bfqd->in_service_queue) ++ bfq_del_bfqq_busy(bfqd, bfqq, 1); ++ /* ++ * Remove queue from request-position tree as it is empty. ++ */ ++ if (bfqq->pos_root != NULL) { ++ rb_erase(&bfqq->pos_node, bfqq->pos_root); ++ bfqq->pos_root = NULL; ++ } ++ } ++ ++ if (rq->cmd_flags & REQ_META) { ++ BUG_ON(bfqq->meta_pending == 0); ++ bfqq->meta_pending--; ++ } ++} ++ ++static int bfq_merge(struct request_queue *q, struct request **req, ++ struct bio *bio) ++{ ++ struct bfq_data *bfqd = q->elevator->elevator_data; ++ struct request *__rq; ++ ++ __rq = bfq_find_rq_fmerge(bfqd, bio); ++ if (__rq != NULL && elv_rq_merge_ok(__rq, bio)) { ++ *req = __rq; ++ return ELEVATOR_FRONT_MERGE; ++ } ++ ++ return ELEVATOR_NO_MERGE; ++} ++ ++static void bfq_merged_request(struct request_queue *q, struct request *req, ++ int type) ++{ ++ if (type == ELEVATOR_FRONT_MERGE && ++ rb_prev(&req->rb_node) && ++ blk_rq_pos(req) < ++ blk_rq_pos(container_of(rb_prev(&req->rb_node), ++ struct request, rb_node))) { ++ struct bfq_queue *bfqq = RQ_BFQQ(req); ++ struct bfq_data *bfqd = bfqq->bfqd; ++ struct request *prev, *next_rq; ++ ++ /* Reposition request in its sort_list */ ++ elv_rb_del(&bfqq->sort_list, req); ++ elv_rb_add(&bfqq->sort_list, req); ++ /* Choose next request to be served for bfqq */ ++ prev = bfqq->next_rq; ++ next_rq = bfq_choose_req(bfqd, bfqq->next_rq, req, ++ bfqd->last_position); ++ BUG_ON(next_rq == NULL); ++ bfqq->next_rq = next_rq; ++ /* ++ * If next_rq changes, update both the queue's budget to ++ * fit the new request and the queue's position in its ++ * rq_pos_tree. ++ */ ++ if (prev != bfqq->next_rq) { ++ bfq_updated_next_req(bfqd, bfqq); ++ bfq_rq_pos_tree_add(bfqd, bfqq); ++ } ++ } ++} ++ ++static void bfq_merged_requests(struct request_queue *q, struct request *rq, ++ struct request *next) ++{ ++ struct bfq_queue *bfqq = RQ_BFQQ(rq); ++ ++ /* ++ * Reposition in fifo if next is older than rq. ++ */ ++ if (!list_empty(&rq->queuelist) && !list_empty(&next->queuelist) && ++ time_before(next->fifo_time, rq->fifo_time)) { ++ list_move(&rq->queuelist, &next->queuelist); ++ rq->fifo_time = next->fifo_time; ++ } ++ ++ if (bfqq->next_rq == next) ++ bfqq->next_rq = rq; ++ ++ bfq_remove_request(next); ++} ++ ++/* Must be called with bfqq != NULL */ ++static inline void bfq_bfqq_end_wr(struct bfq_queue *bfqq) ++{ ++ BUG_ON(bfqq == NULL); ++ if (bfq_bfqq_busy(bfqq)) ++ bfqq->bfqd->wr_busy_queues--; ++ bfqq->wr_coeff = 1; ++ bfqq->wr_cur_max_time = 0; ++ /* Trigger a weight change on the next activation of the queue */ ++ bfqq->entity.ioprio_changed = 1; ++} ++ ++static void bfq_end_wr_async_queues(struct bfq_data *bfqd, ++ struct bfq_group *bfqg) ++{ ++ int i, j; ++ ++ for (i = 0; i < 2; i++) ++ for (j = 0; j < IOPRIO_BE_NR; j++) ++ if (bfqg->async_bfqq[i][j] != NULL) ++ bfq_bfqq_end_wr(bfqg->async_bfqq[i][j]); ++ if (bfqg->async_idle_bfqq != NULL) ++ bfq_bfqq_end_wr(bfqg->async_idle_bfqq); ++} ++ ++static void bfq_end_wr(struct bfq_data *bfqd) ++{ ++ struct bfq_queue *bfqq; ++ ++ spin_lock_irq(bfqd->queue->queue_lock); ++ ++ list_for_each_entry(bfqq, &bfqd->active_list, bfqq_list) ++ bfq_bfqq_end_wr(bfqq); ++ list_for_each_entry(bfqq, &bfqd->idle_list, bfqq_list) ++ bfq_bfqq_end_wr(bfqq); ++ bfq_end_wr_async(bfqd); ++ ++ spin_unlock_irq(bfqd->queue->queue_lock); ++} ++ ++static int bfq_allow_merge(struct request_queue *q, struct request *rq, ++ struct bio *bio) ++{ ++ struct bfq_data *bfqd = q->elevator->elevator_data; ++ struct bfq_io_cq *bic; ++ struct bfq_queue *bfqq; ++ ++ /* ++ * Disallow merge of a sync bio into an async request. ++ */ ++ if (bfq_bio_sync(bio) && !rq_is_sync(rq)) ++ return 0; ++ ++ /* ++ * Lookup the bfqq that this bio will be queued with. Allow ++ * merge only if rq is queued there. ++ * Queue lock is held here. ++ */ ++ bic = bfq_bic_lookup(bfqd, current->io_context); ++ if (bic == NULL) ++ return 0; ++ ++ bfqq = bic_to_bfqq(bic, bfq_bio_sync(bio)); ++ return bfqq == RQ_BFQQ(rq); ++} ++ ++static void __bfq_set_in_service_queue(struct bfq_data *bfqd, ++ struct bfq_queue *bfqq) ++{ ++ if (bfqq != NULL) { ++ bfq_mark_bfqq_must_alloc(bfqq); ++ bfq_mark_bfqq_budget_new(bfqq); ++ bfq_clear_bfqq_fifo_expire(bfqq); ++ ++ bfqd->budgets_assigned = (bfqd->budgets_assigned*7 + 256) / 8; ++ ++ bfq_log_bfqq(bfqd, bfqq, ++ "set_in_service_queue, cur-budget = %lu", ++ bfqq->entity.budget); ++ } ++ ++ bfqd->in_service_queue = bfqq; ++} ++ ++/* ++ * Get and set a new queue for service. ++ */ ++static struct bfq_queue *bfq_set_in_service_queue(struct bfq_data *bfqd, ++ struct bfq_queue *bfqq) ++{ ++ if (!bfqq) ++ bfqq = bfq_get_next_queue(bfqd); ++ else ++ bfq_get_next_queue_forced(bfqd, bfqq); ++ ++ __bfq_set_in_service_queue(bfqd, bfqq); ++ return bfqq; ++} ++ ++static inline sector_t bfq_dist_from_last(struct bfq_data *bfqd, ++ struct request *rq) ++{ ++ if (blk_rq_pos(rq) >= bfqd->last_position) ++ return blk_rq_pos(rq) - bfqd->last_position; ++ else ++ return bfqd->last_position - blk_rq_pos(rq); ++} ++ ++/* ++ * Return true if bfqq has no request pending and rq is close enough to ++ * bfqd->last_position, or if rq is closer to bfqd->last_position than ++ * bfqq->next_rq ++ */ ++static inline int bfq_rq_close(struct bfq_data *bfqd, struct request *rq) ++{ ++ return bfq_dist_from_last(bfqd, rq) <= BFQQ_SEEK_THR; ++} ++ ++static struct bfq_queue *bfqq_close(struct bfq_data *bfqd) ++{ ++ struct rb_root *root = &bfqd->rq_pos_tree; ++ struct rb_node *parent, *node; ++ struct bfq_queue *__bfqq; ++ sector_t sector = bfqd->last_position; ++ ++ if (RB_EMPTY_ROOT(root)) ++ return NULL; ++ ++ /* ++ * First, if we find a request starting at the end of the last ++ * request, choose it. ++ */ ++ __bfqq = bfq_rq_pos_tree_lookup(bfqd, root, sector, &parent, NULL); ++ if (__bfqq != NULL) ++ return __bfqq; ++ ++ /* ++ * If the exact sector wasn't found, the parent of the NULL leaf ++ * will contain the closest sector (rq_pos_tree sorted by ++ * next_request position). ++ */ ++ __bfqq = rb_entry(parent, struct bfq_queue, pos_node); ++ if (bfq_rq_close(bfqd, __bfqq->next_rq)) ++ return __bfqq; ++ ++ if (blk_rq_pos(__bfqq->next_rq) < sector) ++ node = rb_next(&__bfqq->pos_node); ++ else ++ node = rb_prev(&__bfqq->pos_node); ++ if (node == NULL) ++ return NULL; ++ ++ __bfqq = rb_entry(node, struct bfq_queue, pos_node); ++ if (bfq_rq_close(bfqd, __bfqq->next_rq)) ++ return __bfqq; ++ ++ return NULL; ++} ++ ++/* ++ * bfqd - obvious ++ * cur_bfqq - passed in so that we don't decide that the current queue ++ * is closely cooperating with itself. ++ * ++ * We are assuming that cur_bfqq has dispatched at least one request, ++ * and that bfqd->last_position reflects a position on the disk associated ++ * with the I/O issued by cur_bfqq. ++ */ ++static struct bfq_queue *bfq_close_cooperator(struct bfq_data *bfqd, ++ struct bfq_queue *cur_bfqq) ++{ ++ struct bfq_queue *bfqq; ++ ++ if (bfq_class_idle(cur_bfqq)) ++ return NULL; ++ if (!bfq_bfqq_sync(cur_bfqq)) ++ return NULL; ++ if (BFQQ_SEEKY(cur_bfqq)) ++ return NULL; ++ ++ /* If device has only one backlogged bfq_queue, don't search. */ ++ if (bfqd->busy_queues == 1) ++ return NULL; ++ ++ /* ++ * We should notice if some of the queues are cooperating, e.g. ++ * working closely on the same area of the disk. In that case, ++ * we can group them together and don't waste time idling. ++ */ ++ bfqq = bfqq_close(bfqd); ++ if (bfqq == NULL || bfqq == cur_bfqq) ++ return NULL; ++ ++ /* ++ * Do not merge queues from different bfq_groups. ++ */ ++ if (bfqq->entity.parent != cur_bfqq->entity.parent) ++ return NULL; ++ ++ /* ++ * It only makes sense to merge sync queues. ++ */ ++ if (!bfq_bfqq_sync(bfqq)) ++ return NULL; ++ if (BFQQ_SEEKY(bfqq)) ++ return NULL; ++ ++ /* ++ * Do not merge queues of different priority classes. ++ */ ++ if (bfq_class_rt(bfqq) != bfq_class_rt(cur_bfqq)) ++ return NULL; ++ ++ return bfqq; ++} ++ ++/* ++ * If enough samples have been computed, return the current max budget ++ * stored in bfqd, which is dynamically updated according to the ++ * estimated disk peak rate; otherwise return the default max budget ++ */ ++static inline unsigned long bfq_max_budget(struct bfq_data *bfqd) ++{ ++ if (bfqd->budgets_assigned < 194) ++ return bfq_default_max_budget; ++ else ++ return bfqd->bfq_max_budget; ++} ++ ++/* ++ * Return min budget, which is a fraction of the current or default ++ * max budget (trying with 1/32) ++ */ ++static inline unsigned long bfq_min_budget(struct bfq_data *bfqd) ++{ ++ if (bfqd->budgets_assigned < 194) ++ return bfq_default_max_budget / 32; ++ else ++ return bfqd->bfq_max_budget / 32; ++} ++ ++static void bfq_arm_slice_timer(struct bfq_data *bfqd) ++{ ++ struct bfq_queue *bfqq = bfqd->in_service_queue; ++ struct bfq_io_cq *bic; ++ unsigned long sl; ++ ++ BUG_ON(!RB_EMPTY_ROOT(&bfqq->sort_list)); ++ ++ /* Processes have exited, don't wait. */ ++ bic = bfqd->in_service_bic; ++ if (bic == NULL || atomic_read(&bic->icq.ioc->active_ref) == 0) ++ return; ++ ++ bfq_mark_bfqq_wait_request(bfqq); ++ ++ /* ++ * We don't want to idle for seeks, but we do want to allow ++ * fair distribution of slice time for a process doing back-to-back ++ * seeks. So allow a little bit of time for him to submit a new rq. ++ * ++ * To prevent processes with (partly) seeky workloads from ++ * being too ill-treated, grant them a small fraction of the ++ * assigned budget before reducing the waiting time to ++ * BFQ_MIN_TT. This happened to help reduce latency. ++ */ ++ sl = bfqd->bfq_slice_idle; ++ /* ++ * Unless the queue is being weight-raised, grant only minimum idle ++ * time if the queue either has been seeky for long enough or has ++ * already proved to be constantly seeky. ++ */ ++ if (bfq_sample_valid(bfqq->seek_samples) && ++ ((BFQQ_SEEKY(bfqq) && bfqq->entity.service > ++ bfq_max_budget(bfqq->bfqd) / 8) || ++ bfq_bfqq_constantly_seeky(bfqq)) && bfqq->wr_coeff == 1) ++ sl = min(sl, msecs_to_jiffies(BFQ_MIN_TT)); ++ else if (bfqq->wr_coeff > 1) ++ sl = sl * 3; ++ bfqd->last_idling_start = ktime_get(); ++ mod_timer(&bfqd->idle_slice_timer, jiffies + sl); ++ bfq_log(bfqd, "arm idle: %u/%u ms", ++ jiffies_to_msecs(sl), jiffies_to_msecs(bfqd->bfq_slice_idle)); ++} ++ ++/* ++ * Set the maximum time for the in-service queue to consume its ++ * budget. This prevents seeky processes from lowering the disk ++ * throughput (always guaranteed with a time slice scheme as in CFQ). ++ */ ++static void bfq_set_budget_timeout(struct bfq_data *bfqd) ++{ ++ struct bfq_queue *bfqq = bfqd->in_service_queue; ++ unsigned int timeout_coeff; ++ if (bfqq->wr_cur_max_time == bfqd->bfq_wr_rt_max_time) ++ timeout_coeff = 1; ++ else ++ timeout_coeff = bfqq->entity.weight / bfqq->entity.orig_weight; ++ ++ bfqd->last_budget_start = ktime_get(); ++ ++ bfq_clear_bfqq_budget_new(bfqq); ++ bfqq->budget_timeout = jiffies + ++ bfqd->bfq_timeout[bfq_bfqq_sync(bfqq)] * timeout_coeff; ++ ++ bfq_log_bfqq(bfqd, bfqq, "set budget_timeout %u", ++ jiffies_to_msecs(bfqd->bfq_timeout[bfq_bfqq_sync(bfqq)] * ++ timeout_coeff)); ++} ++ ++/* ++ * Move request from internal lists to the request queue dispatch list. ++ */ ++static void bfq_dispatch_insert(struct request_queue *q, struct request *rq) ++{ ++ struct bfq_data *bfqd = q->elevator->elevator_data; ++ struct bfq_queue *bfqq = RQ_BFQQ(rq); ++ ++ /* ++ * For consistency, the next instruction should have been executed ++ * after removing the request from the queue and dispatching it. ++ * We execute instead this instruction before bfq_remove_request() ++ * (and hence introduce a temporary inconsistency), for efficiency. ++ * In fact, in a forced_dispatch, this prevents two counters related ++ * to bfqq->dispatched to risk to be uselessly decremented if bfqq ++ * is not in service, and then to be incremented again after ++ * incrementing bfqq->dispatched. ++ */ ++ bfqq->dispatched++; ++ bfq_remove_request(rq); ++ elv_dispatch_sort(q, rq); ++ ++ if (bfq_bfqq_sync(bfqq)) ++ bfqd->sync_flight++; ++} ++ ++/* ++ * Return expired entry, or NULL to just start from scratch in rbtree. ++ */ ++static struct request *bfq_check_fifo(struct bfq_queue *bfqq) ++{ ++ struct request *rq = NULL; ++ ++ if (bfq_bfqq_fifo_expire(bfqq)) ++ return NULL; ++ ++ bfq_mark_bfqq_fifo_expire(bfqq); ++ ++ if (list_empty(&bfqq->fifo)) ++ return NULL; ++ ++ rq = rq_entry_fifo(bfqq->fifo.next); ++ ++ if (time_before(jiffies, rq->fifo_time)) ++ return NULL; ++ ++ return rq; ++} ++ ++/* Must be called with the queue_lock held. */ ++static int bfqq_process_refs(struct bfq_queue *bfqq) ++{ ++ int process_refs, io_refs; ++ ++ io_refs = bfqq->allocated[READ] + bfqq->allocated[WRITE]; ++ process_refs = atomic_read(&bfqq->ref) - io_refs - bfqq->entity.on_st; ++ BUG_ON(process_refs < 0); ++ return process_refs; ++} ++ ++static void bfq_setup_merge(struct bfq_queue *bfqq, struct bfq_queue *new_bfqq) ++{ ++ int process_refs, new_process_refs; ++ struct bfq_queue *__bfqq; ++ ++ /* ++ * If there are no process references on the new_bfqq, then it is ++ * unsafe to follow the ->new_bfqq chain as other bfqq's in the chain ++ * may have dropped their last reference (not just their last process ++ * reference). ++ */ ++ if (!bfqq_process_refs(new_bfqq)) ++ return; ++ ++ /* Avoid a circular list and skip interim queue merges. */ ++ while ((__bfqq = new_bfqq->new_bfqq)) { ++ if (__bfqq == bfqq) ++ return; ++ new_bfqq = __bfqq; ++ } ++ ++ process_refs = bfqq_process_refs(bfqq); ++ new_process_refs = bfqq_process_refs(new_bfqq); ++ /* ++ * If the process for the bfqq has gone away, there is no ++ * sense in merging the queues. ++ */ ++ if (process_refs == 0 || new_process_refs == 0) ++ return; ++ ++ /* ++ * Merge in the direction of the lesser amount of work. ++ */ ++ if (new_process_refs >= process_refs) { ++ bfqq->new_bfqq = new_bfqq; ++ atomic_add(process_refs, &new_bfqq->ref); ++ } else { ++ new_bfqq->new_bfqq = bfqq; ++ atomic_add(new_process_refs, &bfqq->ref); ++ } ++ bfq_log_bfqq(bfqq->bfqd, bfqq, "scheduling merge with queue %d", ++ new_bfqq->pid); ++} ++ ++static inline unsigned long bfq_bfqq_budget_left(struct bfq_queue *bfqq) ++{ ++ struct bfq_entity *entity = &bfqq->entity; ++ return entity->budget - entity->service; ++} ++ ++static void __bfq_bfqq_expire(struct bfq_data *bfqd, struct bfq_queue *bfqq) ++{ ++ BUG_ON(bfqq != bfqd->in_service_queue); ++ ++ __bfq_bfqd_reset_in_service(bfqd); ++ ++ /* ++ * If this bfqq is shared between multiple processes, check ++ * to make sure that those processes are still issuing I/Os ++ * within the mean seek distance. If not, it may be time to ++ * break the queues apart again. ++ */ ++ if (bfq_bfqq_coop(bfqq) && BFQQ_SEEKY(bfqq)) ++ bfq_mark_bfqq_split_coop(bfqq); ++ ++ if (RB_EMPTY_ROOT(&bfqq->sort_list)) { ++ /* ++ * Overloading budget_timeout field to store the time ++ * at which the queue remains with no backlog; used by ++ * the weight-raising mechanism. ++ */ ++ bfqq->budget_timeout = jiffies; ++ bfq_del_bfqq_busy(bfqd, bfqq, 1); ++ } else { ++ bfq_activate_bfqq(bfqd, bfqq); ++ /* ++ * Resort priority tree of potential close cooperators. ++ */ ++ bfq_rq_pos_tree_add(bfqd, bfqq); ++ } ++} ++ ++/** ++ * __bfq_bfqq_recalc_budget - try to adapt the budget to the @bfqq behavior. ++ * @bfqd: device data. ++ * @bfqq: queue to update. ++ * @reason: reason for expiration. ++ * ++ * Handle the feedback on @bfqq budget. See the body for detailed ++ * comments. ++ */ ++static void __bfq_bfqq_recalc_budget(struct bfq_data *bfqd, ++ struct bfq_queue *bfqq, ++ enum bfqq_expiration reason) ++{ ++ struct request *next_rq; ++ unsigned long budget, min_budget; ++ ++ budget = bfqq->max_budget; ++ min_budget = bfq_min_budget(bfqd); ++ ++ BUG_ON(bfqq != bfqd->in_service_queue); ++ ++ bfq_log_bfqq(bfqd, bfqq, "recalc_budg: last budg %lu, budg left %lu", ++ bfqq->entity.budget, bfq_bfqq_budget_left(bfqq)); ++ bfq_log_bfqq(bfqd, bfqq, "recalc_budg: last max_budg %lu, min budg %lu", ++ budget, bfq_min_budget(bfqd)); ++ bfq_log_bfqq(bfqd, bfqq, "recalc_budg: sync %d, seeky %d", ++ bfq_bfqq_sync(bfqq), BFQQ_SEEKY(bfqd->in_service_queue)); ++ ++ if (bfq_bfqq_sync(bfqq)) { ++ switch (reason) { ++ /* ++ * Caveat: in all the following cases we trade latency ++ * for throughput. ++ */ ++ case BFQ_BFQQ_TOO_IDLE: ++ /* ++ * This is the only case where we may reduce ++ * the budget: if there is no request of the ++ * process still waiting for completion, then ++ * we assume (tentatively) that the timer has ++ * expired because the batch of requests of ++ * the process could have been served with a ++ * smaller budget. Hence, betting that ++ * process will behave in the same way when it ++ * becomes backlogged again, we reduce its ++ * next budget. As long as we guess right, ++ * this budget cut reduces the latency ++ * experienced by the process. ++ * ++ * However, if there are still outstanding ++ * requests, then the process may have not yet ++ * issued its next request just because it is ++ * still waiting for the completion of some of ++ * the still outstanding ones. So in this ++ * subcase we do not reduce its budget, on the ++ * contrary we increase it to possibly boost ++ * the throughput, as discussed in the ++ * comments to the BUDGET_TIMEOUT case. ++ */ ++ if (bfqq->dispatched > 0) /* still outstanding reqs */ ++ budget = min(budget * 2, bfqd->bfq_max_budget); ++ else { ++ if (budget > 5 * min_budget) ++ budget -= 4 * min_budget; ++ else ++ budget = min_budget; ++ } ++ break; ++ case BFQ_BFQQ_BUDGET_TIMEOUT: ++ /* ++ * We double the budget here because: 1) it ++ * gives the chance to boost the throughput if ++ * this is not a seeky process (which may have ++ * bumped into this timeout because of, e.g., ++ * ZBR), 2) together with charge_full_budget ++ * it helps give seeky processes higher ++ * timestamps, and hence be served less ++ * frequently. ++ */ ++ budget = min(budget * 2, bfqd->bfq_max_budget); ++ break; ++ case BFQ_BFQQ_BUDGET_EXHAUSTED: ++ /* ++ * The process still has backlog, and did not ++ * let either the budget timeout or the disk ++ * idling timeout expire. Hence it is not ++ * seeky, has a short thinktime and may be ++ * happy with a higher budget too. So ++ * definitely increase the budget of this good ++ * candidate to boost the disk throughput. ++ */ ++ budget = min(budget * 4, bfqd->bfq_max_budget); ++ break; ++ case BFQ_BFQQ_NO_MORE_REQUESTS: ++ /* ++ * Leave the budget unchanged. ++ */ ++ default: ++ return; ++ } ++ } else /* async queue */ ++ /* async queues get always the maximum possible budget ++ * (their ability to dispatch is limited by ++ * @bfqd->bfq_max_budget_async_rq). ++ */ ++ budget = bfqd->bfq_max_budget; ++ ++ bfqq->max_budget = budget; ++ ++ if (bfqd->budgets_assigned >= 194 && bfqd->bfq_user_max_budget == 0 && ++ bfqq->max_budget > bfqd->bfq_max_budget) ++ bfqq->max_budget = bfqd->bfq_max_budget; ++ ++ /* ++ * Make sure that we have enough budget for the next request. ++ * Since the finish time of the bfqq must be kept in sync with ++ * the budget, be sure to call __bfq_bfqq_expire() after the ++ * update. ++ */ ++ next_rq = bfqq->next_rq; ++ if (next_rq != NULL) ++ bfqq->entity.budget = max_t(unsigned long, bfqq->max_budget, ++ bfq_serv_to_charge(next_rq, bfqq)); ++ else ++ bfqq->entity.budget = bfqq->max_budget; ++ ++ bfq_log_bfqq(bfqd, bfqq, "head sect: %u, new budget %lu", ++ next_rq != NULL ? blk_rq_sectors(next_rq) : 0, ++ bfqq->entity.budget); ++} ++ ++static unsigned long bfq_calc_max_budget(u64 peak_rate, u64 timeout) ++{ ++ unsigned long max_budget; ++ ++ /* ++ * The max_budget calculated when autotuning is equal to the ++ * amount of sectors transfered in timeout_sync at the ++ * estimated peak rate. ++ */ ++ max_budget = (unsigned long)(peak_rate * 1000 * ++ timeout >> BFQ_RATE_SHIFT); ++ ++ return max_budget; ++} ++ ++/* ++ * In addition to updating the peak rate, checks whether the process ++ * is "slow", and returns 1 if so. This slow flag is used, in addition ++ * to the budget timeout, to reduce the amount of service provided to ++ * seeky processes, and hence reduce their chances to lower the ++ * throughput. See the code for more details. ++ */ ++static int bfq_update_peak_rate(struct bfq_data *bfqd, struct bfq_queue *bfqq, ++ int compensate, enum bfqq_expiration reason) ++{ ++ u64 bw, usecs, expected, timeout; ++ ktime_t delta; ++ int update = 0; ++ ++ if (!bfq_bfqq_sync(bfqq) || bfq_bfqq_budget_new(bfqq)) ++ return 0; ++ ++ if (compensate) ++ delta = bfqd->last_idling_start; ++ else ++ delta = ktime_get(); ++ delta = ktime_sub(delta, bfqd->last_budget_start); ++ usecs = ktime_to_us(delta); ++ ++ /* Don't trust short/unrealistic values. */ ++ if (usecs < 100 || usecs >= LONG_MAX) ++ return 0; ++ ++ /* ++ * Calculate the bandwidth for the last slice. We use a 64 bit ++ * value to store the peak rate, in sectors per usec in fixed ++ * point math. We do so to have enough precision in the estimate ++ * and to avoid overflows. ++ */ ++ bw = (u64)bfqq->entity.service << BFQ_RATE_SHIFT; ++ do_div(bw, (unsigned long)usecs); ++ ++ timeout = jiffies_to_msecs(bfqd->bfq_timeout[BLK_RW_SYNC]); ++ ++ /* ++ * Use only long (> 20ms) intervals to filter out spikes for ++ * the peak rate estimation. ++ */ ++ if (usecs > 20000) { ++ if (bw > bfqd->peak_rate || ++ (!BFQQ_SEEKY(bfqq) && ++ reason == BFQ_BFQQ_BUDGET_TIMEOUT)) { ++ bfq_log(bfqd, "measured bw =%llu", bw); ++ /* ++ * To smooth oscillations use a low-pass filter with ++ * alpha=7/8, i.e., ++ * new_rate = (7/8) * old_rate + (1/8) * bw ++ */ ++ do_div(bw, 8); ++ if (bw == 0) ++ return 0; ++ bfqd->peak_rate *= 7; ++ do_div(bfqd->peak_rate, 8); ++ bfqd->peak_rate += bw; ++ update = 1; ++ bfq_log(bfqd, "new peak_rate=%llu", bfqd->peak_rate); ++ } ++ ++ update |= bfqd->peak_rate_samples == BFQ_PEAK_RATE_SAMPLES - 1; ++ ++ if (bfqd->peak_rate_samples < BFQ_PEAK_RATE_SAMPLES) ++ bfqd->peak_rate_samples++; ++ ++ if (bfqd->peak_rate_samples == BFQ_PEAK_RATE_SAMPLES && ++ update) { ++ int dev_type = blk_queue_nonrot(bfqd->queue); ++ if (bfqd->bfq_user_max_budget == 0) { ++ bfqd->bfq_max_budget = ++ bfq_calc_max_budget(bfqd->peak_rate, ++ timeout); ++ bfq_log(bfqd, "new max_budget=%lu", ++ bfqd->bfq_max_budget); ++ } ++ if (bfqd->device_speed == BFQ_BFQD_FAST && ++ bfqd->peak_rate < device_speed_thresh[dev_type]) { ++ bfqd->device_speed = BFQ_BFQD_SLOW; ++ bfqd->RT_prod = R_slow[dev_type] * ++ T_slow[dev_type]; ++ } else if (bfqd->device_speed == BFQ_BFQD_SLOW && ++ bfqd->peak_rate > device_speed_thresh[dev_type]) { ++ bfqd->device_speed = BFQ_BFQD_FAST; ++ bfqd->RT_prod = R_fast[dev_type] * ++ T_fast[dev_type]; ++ } ++ } ++ } ++ ++ /* ++ * If the process has been served for a too short time ++ * interval to let its possible sequential accesses prevail on ++ * the initial seek time needed to move the disk head on the ++ * first sector it requested, then give the process a chance ++ * and for the moment return false. ++ */ ++ if (bfqq->entity.budget <= bfq_max_budget(bfqd) / 8) ++ return 0; ++ ++ /* ++ * A process is considered ``slow'' (i.e., seeky, so that we ++ * cannot treat it fairly in the service domain, as it would ++ * slow down too much the other processes) if, when a slice ++ * ends for whatever reason, it has received service at a ++ * rate that would not be high enough to complete the budget ++ * before the budget timeout expiration. ++ */ ++ expected = bw * 1000 * timeout >> BFQ_RATE_SHIFT; ++ ++ /* ++ * Caveat: processes doing IO in the slower disk zones will ++ * tend to be slow(er) even if not seeky. And the estimated ++ * peak rate will actually be an average over the disk ++ * surface. Hence, to not be too harsh with unlucky processes, ++ * we keep a budget/3 margin of safety before declaring a ++ * process slow. ++ */ ++ return expected > (4 * bfqq->entity.budget) / 3; ++} ++ ++/* ++ * To be deemed as soft real-time, an application must meet two ++ * requirements. First, the application must not require an average ++ * bandwidth higher than the approximate bandwidth required to playback or ++ * record a compressed high-definition video. ++ * The next function is invoked on the completion of the last request of a ++ * batch, to compute the next-start time instant, soft_rt_next_start, such ++ * that, if the next request of the application does not arrive before ++ * soft_rt_next_start, then the above requirement on the bandwidth is met. ++ * ++ * The second requirement is that the request pattern of the application is ++ * isochronous, i.e., that, after issuing a request or a batch of requests, ++ * the application stops issuing new requests until all its pending requests ++ * have been completed. After that, the application may issue a new batch, ++ * and so on. ++ * For this reason the next function is invoked to compute ++ * soft_rt_next_start only for applications that meet this requirement, ++ * whereas soft_rt_next_start is set to infinity for applications that do ++ * not. ++ * ++ * Unfortunately, even a greedy application may happen to behave in an ++ * isochronous way if the CPU load is high. In fact, the application may ++ * stop issuing requests while the CPUs are busy serving other processes, ++ * then restart, then stop again for a while, and so on. In addition, if ++ * the disk achieves a low enough throughput with the request pattern ++ * issued by the application (e.g., because the request pattern is random ++ * and/or the device is slow), then the application may meet the above ++ * bandwidth requirement too. To prevent such a greedy application to be ++ * deemed as soft real-time, a further rule is used in the computation of ++ * soft_rt_next_start: soft_rt_next_start must be higher than the current ++ * time plus the maximum time for which the arrival of a request is waited ++ * for when a sync queue becomes idle, namely bfqd->bfq_slice_idle. ++ * This filters out greedy applications, as the latter issue instead their ++ * next request as soon as possible after the last one has been completed ++ * (in contrast, when a batch of requests is completed, a soft real-time ++ * application spends some time processing data). ++ * ++ * Unfortunately, the last filter may easily generate false positives if ++ * only bfqd->bfq_slice_idle is used as a reference time interval and one ++ * or both the following cases occur: ++ * 1) HZ is so low that the duration of a jiffy is comparable to or higher ++ * than bfqd->bfq_slice_idle. This happens, e.g., on slow devices with ++ * HZ=100. ++ * 2) jiffies, instead of increasing at a constant rate, may stop increasing ++ * for a while, then suddenly 'jump' by several units to recover the lost ++ * increments. This seems to happen, e.g., inside virtual machines. ++ * To address this issue, we do not use as a reference time interval just ++ * bfqd->bfq_slice_idle, but bfqd->bfq_slice_idle plus a few jiffies. In ++ * particular we add the minimum number of jiffies for which the filter ++ * seems to be quite precise also in embedded systems and KVM/QEMU virtual ++ * machines. ++ */ ++static inline unsigned long bfq_bfqq_softrt_next_start(struct bfq_data *bfqd, ++ struct bfq_queue *bfqq) ++{ ++ return max(bfqq->last_idle_bklogged + ++ HZ * bfqq->service_from_backlogged / ++ bfqd->bfq_wr_max_softrt_rate, ++ jiffies + bfqq->bfqd->bfq_slice_idle + 4); ++} ++ ++/* ++ * Return the largest-possible time instant such that, for as long as possible, ++ * the current time will be lower than this time instant according to the macro ++ * time_is_before_jiffies(). ++ */ ++static inline unsigned long bfq_infinity_from_now(unsigned long now) ++{ ++ return now + ULONG_MAX / 2; ++} ++ ++/** ++ * bfq_bfqq_expire - expire a queue. ++ * @bfqd: device owning the queue. ++ * @bfqq: the queue to expire. ++ * @compensate: if true, compensate for the time spent idling. ++ * @reason: the reason causing the expiration. ++ * ++ * ++ * If the process associated to the queue is slow (i.e., seeky), or in ++ * case of budget timeout, or, finally, if it is async, we ++ * artificially charge it an entire budget (independently of the ++ * actual service it received). As a consequence, the queue will get ++ * higher timestamps than the correct ones upon reactivation, and ++ * hence it will be rescheduled as if it had received more service ++ * than what it actually received. In the end, this class of processes ++ * will receive less service in proportion to how slowly they consume ++ * their budgets (and hence how seriously they tend to lower the ++ * throughput). ++ * ++ * In contrast, when a queue expires because it has been idling for ++ * too much or because it exhausted its budget, we do not touch the ++ * amount of service it has received. Hence when the queue will be ++ * reactivated and its timestamps updated, the latter will be in sync ++ * with the actual service received by the queue until expiration. ++ * ++ * Charging a full budget to the first type of queues and the exact ++ * service to the others has the effect of using the WF2Q+ policy to ++ * schedule the former on a timeslice basis, without violating the ++ * service domain guarantees of the latter. ++ */ ++static void bfq_bfqq_expire(struct bfq_data *bfqd, ++ struct bfq_queue *bfqq, ++ int compensate, ++ enum bfqq_expiration reason) ++{ ++ int slow; ++ BUG_ON(bfqq != bfqd->in_service_queue); ++ ++ /* Update disk peak rate for autotuning and check whether the ++ * process is slow (see bfq_update_peak_rate). ++ */ ++ slow = bfq_update_peak_rate(bfqd, bfqq, compensate, reason); ++ ++ /* ++ * As above explained, 'punish' slow (i.e., seeky), timed-out ++ * and async queues, to favor sequential sync workloads. ++ * ++ * Processes doing I/O in the slower disk zones will tend to be ++ * slow(er) even if not seeky. Hence, since the estimated peak ++ * rate is actually an average over the disk surface, these ++ * processes may timeout just for bad luck. To avoid punishing ++ * them we do not charge a full budget to a process that ++ * succeeded in consuming at least 2/3 of its budget. ++ */ ++ if (slow || (reason == BFQ_BFQQ_BUDGET_TIMEOUT && ++ bfq_bfqq_budget_left(bfqq) >= bfqq->entity.budget / 3)) ++ bfq_bfqq_charge_full_budget(bfqq); ++ ++ bfqq->service_from_backlogged += bfqq->entity.service; ++ ++ if (BFQQ_SEEKY(bfqq) && reason == BFQ_BFQQ_BUDGET_TIMEOUT && ++ !bfq_bfqq_constantly_seeky(bfqq)) { ++ bfq_mark_bfqq_constantly_seeky(bfqq); ++ if (!blk_queue_nonrot(bfqd->queue)) ++ bfqd->const_seeky_busy_in_flight_queues++; ++ } ++ ++ if (reason == BFQ_BFQQ_TOO_IDLE && ++ bfqq->entity.service <= 2 * bfqq->entity.budget / 10 ) ++ bfq_clear_bfqq_IO_bound(bfqq); ++ ++ if (bfqd->low_latency && bfqq->wr_coeff == 1) ++ bfqq->last_wr_start_finish = jiffies; ++ ++ if (bfqd->low_latency && bfqd->bfq_wr_max_softrt_rate > 0 && ++ RB_EMPTY_ROOT(&bfqq->sort_list)) { ++ /* ++ * If we get here, and there are no outstanding requests, ++ * then the request pattern is isochronous (see the comments ++ * to the function bfq_bfqq_softrt_next_start()). Hence we ++ * can compute soft_rt_next_start. If, instead, the queue ++ * still has outstanding requests, then we have to wait ++ * for the completion of all the outstanding requests to ++ * discover whether the request pattern is actually ++ * isochronous. ++ */ ++ if (bfqq->dispatched == 0) ++ bfqq->soft_rt_next_start = ++ bfq_bfqq_softrt_next_start(bfqd, bfqq); ++ else { ++ /* ++ * The application is still waiting for the ++ * completion of one or more requests: ++ * prevent it from possibly being incorrectly ++ * deemed as soft real-time by setting its ++ * soft_rt_next_start to infinity. In fact, ++ * without this assignment, the application ++ * would be incorrectly deemed as soft ++ * real-time if: ++ * 1) it issued a new request before the ++ * completion of all its in-flight ++ * requests, and ++ * 2) at that time, its soft_rt_next_start ++ * happened to be in the past. ++ */ ++ bfqq->soft_rt_next_start = ++ bfq_infinity_from_now(jiffies); ++ /* ++ * Schedule an update of soft_rt_next_start to when ++ * the task may be discovered to be isochronous. ++ */ ++ bfq_mark_bfqq_softrt_update(bfqq); ++ } ++ } ++ ++ bfq_log_bfqq(bfqd, bfqq, ++ "expire (%d, slow %d, num_disp %d, idle_win %d)", reason, ++ slow, bfqq->dispatched, bfq_bfqq_idle_window(bfqq)); ++ ++ /* ++ * Increase, decrease or leave budget unchanged according to ++ * reason. ++ */ ++ __bfq_bfqq_recalc_budget(bfqd, bfqq, reason); ++ __bfq_bfqq_expire(bfqd, bfqq); ++} ++ ++/* ++ * Budget timeout is not implemented through a dedicated timer, but ++ * just checked on request arrivals and completions, as well as on ++ * idle timer expirations. ++ */ ++static int bfq_bfqq_budget_timeout(struct bfq_queue *bfqq) ++{ ++ if (bfq_bfqq_budget_new(bfqq) || ++ time_before(jiffies, bfqq->budget_timeout)) ++ return 0; ++ return 1; ++} ++ ++/* ++ * If we expire a queue that is waiting for the arrival of a new ++ * request, we may prevent the fictitious timestamp back-shifting that ++ * allows the guarantees of the queue to be preserved (see [1] for ++ * this tricky aspect). Hence we return true only if this condition ++ * does not hold, or if the queue is slow enough to deserve only to be ++ * kicked off for preserving a high throughput. ++*/ ++static inline int bfq_may_expire_for_budg_timeout(struct bfq_queue *bfqq) ++{ ++ bfq_log_bfqq(bfqq->bfqd, bfqq, ++ "may_budget_timeout: wait_request %d left %d timeout %d", ++ bfq_bfqq_wait_request(bfqq), ++ bfq_bfqq_budget_left(bfqq) >= bfqq->entity.budget / 3, ++ bfq_bfqq_budget_timeout(bfqq)); ++ ++ return (!bfq_bfqq_wait_request(bfqq) || ++ bfq_bfqq_budget_left(bfqq) >= bfqq->entity.budget / 3) ++ && ++ bfq_bfqq_budget_timeout(bfqq); ++} ++ ++/* ++ * Device idling is allowed only for the queues for which this function ++ * returns true. For this reason, the return value of this function plays a ++ * critical role for both throughput boosting and service guarantees. The ++ * return value is computed through a logical expression. In this rather ++ * long comment, we try to briefly describe all the details and motivations ++ * behind the components of this logical expression. ++ * ++ * First, the expression is false if bfqq is not sync, or if: bfqq happened ++ * to become active during a large burst of queue activations, and the ++ * pattern of requests bfqq contains boosts the throughput if bfqq is ++ * expired. In fact, queues that became active during a large burst benefit ++ * only from throughput, as discussed in the comments to bfq_handle_burst. ++ * In this respect, expiring bfqq certainly boosts the throughput on NCQ- ++ * capable flash-based devices, whereas, on rotational devices, it boosts ++ * the throughput only if bfqq contains random requests. ++ * ++ * On the opposite end, if (a) bfqq is sync, (b) the above burst-related ++ * condition does not hold, and (c) bfqq is being weight-raised, then the ++ * expression always evaluates to true, as device idling is instrumental ++ * for preserving low-latency guarantees (see [1]). If, instead, conditions ++ * (a) and (b) do hold, but (c) does not, then the expression evaluates to ++ * true only if: (1) bfqq is I/O-bound and has a non-null idle window, and ++ * (2) at least one of the following two conditions holds. ++ * The first condition is that the device is not performing NCQ, because ++ * idling the device most certainly boosts the throughput if this condition ++ * holds and bfqq is I/O-bound and has been granted a non-null idle window. ++ * The second compound condition is made of the logical AND of two components. ++ * ++ * The first component is true only if there is no weight-raised busy ++ * queue. This guarantees that the device is not idled for a sync non- ++ * weight-raised queue when there are busy weight-raised queues. The former ++ * is then expired immediately if empty. Combined with the timestamping ++ * rules of BFQ (see [1] for details), this causes sync non-weight-raised ++ * queues to get a lower number of requests served, and hence to ask for a ++ * lower number of requests from the request pool, before the busy weight- ++ * raised queues get served again. ++ * ++ * This is beneficial for the processes associated with weight-raised ++ * queues, when the request pool is saturated (e.g., in the presence of ++ * write hogs). In fact, if the processes associated with the other queues ++ * ask for requests at a lower rate, then weight-raised processes have a ++ * higher probability to get a request from the pool immediately (or at ++ * least soon) when they need one. Hence they have a higher probability to ++ * actually get a fraction of the disk throughput proportional to their ++ * high weight. This is especially true with NCQ-capable drives, which ++ * enqueue several requests in advance and further reorder internally- ++ * queued requests. ++ * ++ * In the end, mistreating non-weight-raised queues when there are busy ++ * weight-raised queues seems to mitigate starvation problems in the ++ * presence of heavy write workloads and NCQ, and hence to guarantee a ++ * higher application and system responsiveness in these hostile scenarios. ++ * ++ * If the first component of the compound condition is instead true, i.e., ++ * there is no weight-raised busy queue, then the second component of the ++ * compound condition takes into account service-guarantee and throughput ++ * issues related to NCQ (recall that the compound condition is evaluated ++ * only if the device is detected as supporting NCQ). ++ * ++ * As for service guarantees, allowing the drive to enqueue more than one ++ * request at a time, and hence delegating de facto final scheduling ++ * decisions to the drive's internal scheduler, causes loss of control on ++ * the actual request service order. In this respect, when the drive is ++ * allowed to enqueue more than one request at a time, the service ++ * distribution enforced by the drive's internal scheduler is likely to ++ * coincide with the desired device-throughput distribution only in the ++ * following, perfectly symmetric, scenario: ++ * 1) all active queues have the same weight, ++ * 2) all active groups at the same level in the groups tree have the same ++ * weight, ++ * 3) all active groups at the same level in the groups tree have the same ++ * number of children. ++ * ++ * Even in such a scenario, sequential I/O may still receive a preferential ++ * treatment, but this is not likely to be a big issue with flash-based ++ * devices, because of their non-dramatic loss of throughput with random ++ * I/O. Things do differ with HDDs, for which additional care is taken, as ++ * explained after completing the discussion for flash-based devices. ++ * ++ * Unfortunately, keeping the necessary state for evaluating exactly the ++ * above symmetry conditions would be quite complex and time-consuming. ++ * Therefore BFQ evaluates instead the following stronger sub-conditions, ++ * for which it is much easier to maintain the needed state: ++ * 1) all active queues have the same weight, ++ * 2) all active groups have the same weight, ++ * 3) all active groups have at most one active child each. ++ * In particular, the last two conditions are always true if hierarchical ++ * support and the cgroups interface are not enabled, hence no state needs ++ * to be maintained in this case. ++ * ++ * According to the above considerations, the second component of the ++ * compound condition evaluates to true if any of the above symmetry ++ * sub-condition does not hold, or the device is not flash-based. Therefore, ++ * if also the first component is true, then idling is allowed for a sync ++ * queue. These are the only sub-conditions considered if the device is ++ * flash-based, as, for such a device, it is sensible to force idling only ++ * for service-guarantee issues. In fact, as for throughput, idling ++ * NCQ-capable flash-based devices would not boost the throughput even ++ * with sequential I/O; rather it would lower the throughput in proportion ++ * to how fast the device is. In the end, (only) if all the three ++ * sub-conditions hold and the device is flash-based, the compound ++ * condition evaluates to false and therefore no idling is performed. ++ * ++ * As already said, things change with a rotational device, where idling ++ * boosts the throughput with sequential I/O (even with NCQ). Hence, for ++ * such a device the second component of the compound condition evaluates ++ * to true also if the following additional sub-condition does not hold: ++ * the queue is constantly seeky. Unfortunately, this different behavior ++ * with respect to flash-based devices causes an additional asymmetry: if ++ * some sync queues enjoy idling and some other sync queues do not, then ++ * the latter get a low share of the device throughput, simply because the ++ * former get many requests served after being set as in service, whereas ++ * the latter do not. As a consequence, to guarantee the desired throughput ++ * distribution, on HDDs the compound expression evaluates to true (and ++ * hence device idling is performed) also if the following last symmetry ++ * condition does not hold: no other queue is benefiting from idling. Also ++ * this last condition is actually replaced with a simpler-to-maintain and ++ * stronger condition: there is no busy queue which is not constantly seeky ++ * (and hence may also benefit from idling). ++ * ++ * To sum up, when all the required symmetry and throughput-boosting ++ * sub-conditions hold, the second component of the compound condition ++ * evaluates to false, and hence no idling is performed. This helps to ++ * keep the drives' internal queues full on NCQ-capable devices, and hence ++ * to boost the throughput, without causing 'almost' any loss of service ++ * guarantees. The 'almost' follows from the fact that, if the internal ++ * queue of one such device is filled while all the sub-conditions hold, ++ * but at some point in time some sub-condition stops to hold, then it may ++ * become impossible to let requests be served in the new desired order ++ * until all the requests already queued in the device have been served. ++ */ ++static inline bool bfq_bfqq_must_not_expire(struct bfq_queue *bfqq) ++{ ++ struct bfq_data *bfqd = bfqq->bfqd; ++#ifdef CONFIG_CGROUP_BFQIO ++#define symmetric_scenario (!bfqd->active_numerous_groups && \ ++ !bfq_differentiated_weights(bfqd)) ++#else ++#define symmetric_scenario (!bfq_differentiated_weights(bfqd)) ++#endif ++#define cond_for_seeky_on_ncq_hdd (bfq_bfqq_constantly_seeky(bfqq) && \ ++ bfqd->busy_in_flight_queues == \ ++ bfqd->const_seeky_busy_in_flight_queues) ++ ++#define cond_for_expiring_in_burst (bfq_bfqq_in_large_burst(bfqq) && \ ++ bfqd->hw_tag && \ ++ (blk_queue_nonrot(bfqd->queue) || \ ++ bfq_bfqq_constantly_seeky(bfqq))) ++ ++/* ++ * Condition for expiring a non-weight-raised queue (and hence not idling ++ * the device). ++ */ ++#define cond_for_expiring_non_wr (bfqd->hw_tag && \ ++ (bfqd->wr_busy_queues > 0 || \ ++ (symmetric_scenario && \ ++ (blk_queue_nonrot(bfqd->queue) || \ ++ cond_for_seeky_on_ncq_hdd)))) ++ ++ return bfq_bfqq_sync(bfqq) && ++ !cond_for_expiring_in_burst && ++ (bfqq->wr_coeff > 1 || ++ (bfq_bfqq_IO_bound(bfqq) && bfq_bfqq_idle_window(bfqq) && ++ !cond_for_expiring_non_wr) ++ ); ++} ++ ++/* ++ * If the in-service queue is empty but sync, and the function ++ * bfq_bfqq_must_not_expire returns true, then: ++ * 1) the queue must remain in service and cannot be expired, and ++ * 2) the disk must be idled to wait for the possible arrival of a new ++ * request for the queue. ++ * See the comments to the function bfq_bfqq_must_not_expire for the reasons ++ * why performing device idling is the best choice to boost the throughput ++ * and preserve service guarantees when bfq_bfqq_must_not_expire itself ++ * returns true. ++ */ ++static inline bool bfq_bfqq_must_idle(struct bfq_queue *bfqq) ++{ ++ struct bfq_data *bfqd = bfqq->bfqd; ++ ++ return RB_EMPTY_ROOT(&bfqq->sort_list) && bfqd->bfq_slice_idle != 0 && ++ bfq_bfqq_must_not_expire(bfqq); ++} ++ ++/* ++ * Select a queue for service. If we have a current queue in service, ++ * check whether to continue servicing it, or retrieve and set a new one. ++ */ ++static struct bfq_queue *bfq_select_queue(struct bfq_data *bfqd) ++{ ++ struct bfq_queue *bfqq, *new_bfqq = NULL; ++ struct request *next_rq; ++ enum bfqq_expiration reason = BFQ_BFQQ_BUDGET_TIMEOUT; ++ ++ bfqq = bfqd->in_service_queue; ++ if (bfqq == NULL) ++ goto new_queue; ++ ++ bfq_log_bfqq(bfqd, bfqq, "select_queue: already in-service queue"); ++ ++ /* ++ * If another queue has a request waiting within our mean seek ++ * distance, let it run. The expire code will check for close ++ * cooperators and put the close queue at the front of the ++ * service tree. If possible, merge the expiring queue with the ++ * new bfqq. ++ */ ++ new_bfqq = bfq_close_cooperator(bfqd, bfqq); ++ if (new_bfqq != NULL && bfqq->new_bfqq == NULL) ++ bfq_setup_merge(bfqq, new_bfqq); ++ ++ if (bfq_may_expire_for_budg_timeout(bfqq) && ++ !timer_pending(&bfqd->idle_slice_timer) && ++ !bfq_bfqq_must_idle(bfqq)) ++ goto expire; ++ ++ next_rq = bfqq->next_rq; ++ /* ++ * If bfqq has requests queued and it has enough budget left to ++ * serve them, keep the queue, otherwise expire it. ++ */ ++ if (next_rq != NULL) { ++ if (bfq_serv_to_charge(next_rq, bfqq) > ++ bfq_bfqq_budget_left(bfqq)) { ++ reason = BFQ_BFQQ_BUDGET_EXHAUSTED; ++ goto expire; ++ } else { ++ /* ++ * The idle timer may be pending because we may ++ * not disable disk idling even when a new request ++ * arrives. ++ */ ++ if (timer_pending(&bfqd->idle_slice_timer)) { ++ /* ++ * If we get here: 1) at least a new request ++ * has arrived but we have not disabled the ++ * timer because the request was too small, ++ * 2) then the block layer has unplugged ++ * the device, causing the dispatch to be ++ * invoked. ++ * ++ * Since the device is unplugged, now the ++ * requests are probably large enough to ++ * provide a reasonable throughput. ++ * So we disable idling. ++ */ ++ bfq_clear_bfqq_wait_request(bfqq); ++ del_timer(&bfqd->idle_slice_timer); ++ } ++ if (new_bfqq == NULL) ++ goto keep_queue; ++ else ++ goto expire; ++ } ++ } ++ ++ /* ++ * No requests pending. If the in-service queue still has requests ++ * in flight (possibly waiting for a completion) or is idling for a ++ * new request, then keep it. ++ */ ++ if (new_bfqq == NULL && (timer_pending(&bfqd->idle_slice_timer) || ++ (bfqq->dispatched != 0 && bfq_bfqq_must_not_expire(bfqq)))) { ++ bfqq = NULL; ++ goto keep_queue; ++ } else if (new_bfqq != NULL && timer_pending(&bfqd->idle_slice_timer)) { ++ /* ++ * Expiring the queue because there is a close cooperator, ++ * cancel timer. ++ */ ++ bfq_clear_bfqq_wait_request(bfqq); ++ del_timer(&bfqd->idle_slice_timer); ++ } ++ ++ reason = BFQ_BFQQ_NO_MORE_REQUESTS; ++expire: ++ bfq_bfqq_expire(bfqd, bfqq, 0, reason); ++new_queue: ++ bfqq = bfq_set_in_service_queue(bfqd, new_bfqq); ++ bfq_log(bfqd, "select_queue: new queue %d returned", ++ bfqq != NULL ? bfqq->pid : 0); ++keep_queue: ++ return bfqq; ++} ++ ++static void bfq_update_wr_data(struct bfq_data *bfqd, ++ struct bfq_queue *bfqq) ++{ ++ if (bfqq->wr_coeff > 1) { /* queue is being boosted */ ++ struct bfq_entity *entity = &bfqq->entity; ++ ++ bfq_log_bfqq(bfqd, bfqq, ++ "raising period dur %u/%u msec, old coeff %u, w %d(%d)", ++ jiffies_to_msecs(jiffies - ++ bfqq->last_wr_start_finish), ++ jiffies_to_msecs(bfqq->wr_cur_max_time), ++ bfqq->wr_coeff, ++ bfqq->entity.weight, bfqq->entity.orig_weight); ++ ++ BUG_ON(bfqq != bfqd->in_service_queue && entity->weight != ++ entity->orig_weight * bfqq->wr_coeff); ++ if (entity->ioprio_changed) ++ bfq_log_bfqq(bfqd, bfqq, "WARN: pending prio change"); ++ /* ++ * If the queue was activated in a burst, or ++ * too much time has elapsed from the beginning ++ * of this weight-raising, then end weight raising. ++ */ ++ if (bfq_bfqq_in_large_burst(bfqq) || ++ time_is_before_jiffies(bfqq->last_wr_start_finish + ++ bfqq->wr_cur_max_time)) { ++ bfqq->last_wr_start_finish = jiffies; ++ bfq_log_bfqq(bfqd, bfqq, ++ "wrais ending at %lu, rais_max_time %u", ++ bfqq->last_wr_start_finish, ++ jiffies_to_msecs(bfqq->wr_cur_max_time)); ++ bfq_bfqq_end_wr(bfqq); ++ __bfq_entity_update_weight_prio( ++ bfq_entity_service_tree(entity), ++ entity); ++ } ++ } ++} ++ ++/* ++ * Dispatch one request from bfqq, moving it to the request queue ++ * dispatch list. ++ */ ++static int bfq_dispatch_request(struct bfq_data *bfqd, ++ struct bfq_queue *bfqq) ++{ ++ int dispatched = 0; ++ struct request *rq; ++ unsigned long service_to_charge; ++ ++ BUG_ON(RB_EMPTY_ROOT(&bfqq->sort_list)); ++ ++ /* Follow expired path, else get first next available. */ ++ rq = bfq_check_fifo(bfqq); ++ if (rq == NULL) ++ rq = bfqq->next_rq; ++ service_to_charge = bfq_serv_to_charge(rq, bfqq); ++ ++ if (service_to_charge > bfq_bfqq_budget_left(bfqq)) { ++ /* ++ * This may happen if the next rq is chosen in fifo order ++ * instead of sector order. The budget is properly ++ * dimensioned to be always sufficient to serve the next ++ * request only if it is chosen in sector order. The reason ++ * is that it would be quite inefficient and little useful ++ * to always make sure that the budget is large enough to ++ * serve even the possible next rq in fifo order. ++ * In fact, requests are seldom served in fifo order. ++ * ++ * Expire the queue for budget exhaustion, and make sure ++ * that the next act_budget is enough to serve the next ++ * request, even if it comes from the fifo expired path. ++ */ ++ bfqq->next_rq = rq; ++ /* ++ * Since this dispatch is failed, make sure that ++ * a new one will be performed ++ */ ++ if (!bfqd->rq_in_driver) ++ bfq_schedule_dispatch(bfqd); ++ goto expire; ++ } ++ ++ /* Finally, insert request into driver dispatch list. */ ++ bfq_bfqq_served(bfqq, service_to_charge); ++ bfq_dispatch_insert(bfqd->queue, rq); ++ ++ bfq_update_wr_data(bfqd, bfqq); ++ ++ bfq_log_bfqq(bfqd, bfqq, ++ "dispatched %u sec req (%llu), budg left %lu", ++ blk_rq_sectors(rq), ++ (long long unsigned)blk_rq_pos(rq), ++ bfq_bfqq_budget_left(bfqq)); ++ ++ dispatched++; ++ ++ if (bfqd->in_service_bic == NULL) { ++ atomic_long_inc(&RQ_BIC(rq)->icq.ioc->refcount); ++ bfqd->in_service_bic = RQ_BIC(rq); ++ } ++ ++ if (bfqd->busy_queues > 1 && ((!bfq_bfqq_sync(bfqq) && ++ dispatched >= bfqd->bfq_max_budget_async_rq) || ++ bfq_class_idle(bfqq))) ++ goto expire; ++ ++ return dispatched; ++ ++expire: ++ bfq_bfqq_expire(bfqd, bfqq, 0, BFQ_BFQQ_BUDGET_EXHAUSTED); ++ return dispatched; ++} ++ ++static int __bfq_forced_dispatch_bfqq(struct bfq_queue *bfqq) ++{ ++ int dispatched = 0; ++ ++ while (bfqq->next_rq != NULL) { ++ bfq_dispatch_insert(bfqq->bfqd->queue, bfqq->next_rq); ++ dispatched++; ++ } ++ ++ BUG_ON(!list_empty(&bfqq->fifo)); ++ return dispatched; ++} ++ ++/* ++ * Drain our current requests. ++ * Used for barriers and when switching io schedulers on-the-fly. ++ */ ++static int bfq_forced_dispatch(struct bfq_data *bfqd) ++{ ++ struct bfq_queue *bfqq, *n; ++ struct bfq_service_tree *st; ++ int dispatched = 0; ++ ++ bfqq = bfqd->in_service_queue; ++ if (bfqq != NULL) ++ __bfq_bfqq_expire(bfqd, bfqq); ++ ++ /* ++ * Loop through classes, and be careful to leave the scheduler ++ * in a consistent state, as feedback mechanisms and vtime ++ * updates cannot be disabled during the process. ++ */ ++ list_for_each_entry_safe(bfqq, n, &bfqd->active_list, bfqq_list) { ++ st = bfq_entity_service_tree(&bfqq->entity); ++ ++ dispatched += __bfq_forced_dispatch_bfqq(bfqq); ++ bfqq->max_budget = bfq_max_budget(bfqd); ++ ++ bfq_forget_idle(st); ++ } ++ ++ BUG_ON(bfqd->busy_queues != 0); ++ ++ return dispatched; ++} ++ ++static int bfq_dispatch_requests(struct request_queue *q, int force) ++{ ++ struct bfq_data *bfqd = q->elevator->elevator_data; ++ struct bfq_queue *bfqq; ++ int max_dispatch; ++ ++ bfq_log(bfqd, "dispatch requests: %d busy queues", bfqd->busy_queues); ++ if (bfqd->busy_queues == 0) ++ return 0; ++ ++ if (unlikely(force)) ++ return bfq_forced_dispatch(bfqd); ++ ++ bfqq = bfq_select_queue(bfqd); ++ if (bfqq == NULL) ++ return 0; ++ ++ max_dispatch = bfqd->bfq_quantum; ++ if (bfq_class_idle(bfqq)) ++ max_dispatch = 1; ++ ++ if (!bfq_bfqq_sync(bfqq)) ++ max_dispatch = bfqd->bfq_max_budget_async_rq; ++ ++ if (bfqq->dispatched >= max_dispatch) { ++ if (bfqd->busy_queues > 1) ++ return 0; ++ if (bfqq->dispatched >= 4 * max_dispatch) ++ return 0; ++ } ++ ++ if (bfqd->sync_flight != 0 && !bfq_bfqq_sync(bfqq)) ++ return 0; ++ ++ bfq_clear_bfqq_wait_request(bfqq); ++ BUG_ON(timer_pending(&bfqd->idle_slice_timer)); ++ ++ if (!bfq_dispatch_request(bfqd, bfqq)) ++ return 0; ++ ++ bfq_log_bfqq(bfqd, bfqq, "dispatched one request of %d (max_disp %d)", ++ bfqq->pid, max_dispatch); ++ ++ return 1; ++} ++ ++/* ++ * Task holds one reference to the queue, dropped when task exits. Each rq ++ * in-flight on this queue also holds a reference, dropped when rq is freed. ++ * ++ * Queue lock must be held here. ++ */ ++static void bfq_put_queue(struct bfq_queue *bfqq) ++{ ++ struct bfq_data *bfqd = bfqq->bfqd; ++ ++ BUG_ON(atomic_read(&bfqq->ref) <= 0); ++ ++ bfq_log_bfqq(bfqd, bfqq, "put_queue: %p %d", bfqq, ++ atomic_read(&bfqq->ref)); ++ if (!atomic_dec_and_test(&bfqq->ref)) ++ return; ++ ++ BUG_ON(rb_first(&bfqq->sort_list) != NULL); ++ BUG_ON(bfqq->allocated[READ] + bfqq->allocated[WRITE] != 0); ++ BUG_ON(bfqq->entity.tree != NULL); ++ BUG_ON(bfq_bfqq_busy(bfqq)); ++ BUG_ON(bfqd->in_service_queue == bfqq); ++ ++ if (bfq_bfqq_sync(bfqq)) ++ /* ++ * The fact that this queue is being destroyed does not ++ * invalidate the fact that this queue may have been ++ * activated during the current burst. As a consequence, ++ * although the queue does not exist anymore, and hence ++ * needs to be removed from the burst list if there, ++ * the burst size has not to be decremented. ++ */ ++ hlist_del_init(&bfqq->burst_list_node); ++ ++ bfq_log_bfqq(bfqd, bfqq, "put_queue: %p freed", bfqq); ++ ++ kmem_cache_free(bfq_pool, bfqq); ++} ++ ++static void bfq_put_cooperator(struct bfq_queue *bfqq) ++{ ++ struct bfq_queue *__bfqq, *next; ++ ++ /* ++ * If this queue was scheduled to merge with another queue, be ++ * sure to drop the reference taken on that queue (and others in ++ * the merge chain). See bfq_setup_merge and bfq_merge_bfqqs. ++ */ ++ __bfqq = bfqq->new_bfqq; ++ while (__bfqq) { ++ if (__bfqq == bfqq) ++ break; ++ next = __bfqq->new_bfqq; ++ bfq_put_queue(__bfqq); ++ __bfqq = next; ++ } ++} ++ ++static void bfq_exit_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq) ++{ ++ if (bfqq == bfqd->in_service_queue) { ++ __bfq_bfqq_expire(bfqd, bfqq); ++ bfq_schedule_dispatch(bfqd); ++ } ++ ++ bfq_log_bfqq(bfqd, bfqq, "exit_bfqq: %p, %d", bfqq, ++ atomic_read(&bfqq->ref)); ++ ++ bfq_put_cooperator(bfqq); ++ ++ bfq_put_queue(bfqq); ++} ++ ++static inline void bfq_init_icq(struct io_cq *icq) ++{ ++ struct bfq_io_cq *bic = icq_to_bic(icq); ++ ++ bic->ttime.last_end_request = jiffies; ++} ++ ++static void bfq_exit_icq(struct io_cq *icq) ++{ ++ struct bfq_io_cq *bic = icq_to_bic(icq); ++ struct bfq_data *bfqd = bic_to_bfqd(bic); ++ ++ if (bic->bfqq[BLK_RW_ASYNC]) { ++ bfq_exit_bfqq(bfqd, bic->bfqq[BLK_RW_ASYNC]); ++ bic->bfqq[BLK_RW_ASYNC] = NULL; ++ } ++ ++ if (bic->bfqq[BLK_RW_SYNC]) { ++ bfq_exit_bfqq(bfqd, bic->bfqq[BLK_RW_SYNC]); ++ bic->bfqq[BLK_RW_SYNC] = NULL; ++ } ++} ++ ++/* ++ * Update the entity prio values; note that the new values will not ++ * be used until the next (re)activation. ++ */ ++static void bfq_init_prio_data(struct bfq_queue *bfqq, struct bfq_io_cq *bic) ++{ ++ struct task_struct *tsk = current; ++ int ioprio_class; ++ ++ if (!bfq_bfqq_prio_changed(bfqq)) ++ return; ++ ++ ioprio_class = IOPRIO_PRIO_CLASS(bic->ioprio); ++ switch (ioprio_class) { ++ default: ++ dev_err(bfqq->bfqd->queue->backing_dev_info.dev, ++ "bfq: bad prio class %d\n", ioprio_class); ++ case IOPRIO_CLASS_NONE: ++ /* ++ * No prio set, inherit CPU scheduling settings. ++ */ ++ bfqq->entity.new_ioprio = task_nice_ioprio(tsk); ++ bfqq->entity.new_ioprio_class = task_nice_ioclass(tsk); ++ break; ++ case IOPRIO_CLASS_RT: ++ bfqq->entity.new_ioprio = IOPRIO_PRIO_DATA(bic->ioprio); ++ bfqq->entity.new_ioprio_class = IOPRIO_CLASS_RT; ++ break; ++ case IOPRIO_CLASS_BE: ++ bfqq->entity.new_ioprio = IOPRIO_PRIO_DATA(bic->ioprio); ++ bfqq->entity.new_ioprio_class = IOPRIO_CLASS_BE; ++ break; ++ case IOPRIO_CLASS_IDLE: ++ bfqq->entity.new_ioprio_class = IOPRIO_CLASS_IDLE; ++ bfqq->entity.new_ioprio = 7; ++ bfq_clear_bfqq_idle_window(bfqq); ++ break; ++ } ++ ++ if (bfqq->entity.new_ioprio < 0 || ++ bfqq->entity.new_ioprio >= IOPRIO_BE_NR) { ++ printk(KERN_CRIT "bfq_init_prio_data: new_ioprio %d\n", ++ bfqq->entity.new_ioprio); ++ BUG(); ++ } ++ ++ bfqq->entity.ioprio_changed = 1; ++ ++ bfq_clear_bfqq_prio_changed(bfqq); ++} ++ ++static void bfq_changed_ioprio(struct bfq_io_cq *bic) ++{ ++ struct bfq_data *bfqd; ++ struct bfq_queue *bfqq, *new_bfqq; ++ struct bfq_group *bfqg; ++ unsigned long uninitialized_var(flags); ++ int ioprio = bic->icq.ioc->ioprio; ++ ++ bfqd = bfq_get_bfqd_locked(&(bic->icq.q->elevator->elevator_data), ++ &flags); ++ /* ++ * This condition may trigger on a newly created bic, be sure to ++ * drop the lock before returning. ++ */ ++ if (unlikely(bfqd == NULL) || likely(bic->ioprio == ioprio)) ++ goto out; ++ ++ bfqq = bic->bfqq[BLK_RW_ASYNC]; ++ if (bfqq != NULL) { ++ bfqg = container_of(bfqq->entity.sched_data, struct bfq_group, ++ sched_data); ++ new_bfqq = bfq_get_queue(bfqd, bfqg, BLK_RW_ASYNC, bic, ++ GFP_ATOMIC); ++ if (new_bfqq != NULL) { ++ bic->bfqq[BLK_RW_ASYNC] = new_bfqq; ++ bfq_log_bfqq(bfqd, bfqq, ++ "changed_ioprio: bfqq %p %d", ++ bfqq, atomic_read(&bfqq->ref)); ++ bfq_put_queue(bfqq); ++ } ++ } ++ ++ bfqq = bic->bfqq[BLK_RW_SYNC]; ++ if (bfqq != NULL) ++ bfq_mark_bfqq_prio_changed(bfqq); ++ ++ bic->ioprio = ioprio; ++ ++out: ++ bfq_put_bfqd_unlock(bfqd, &flags); ++} ++ ++static void bfq_init_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq, ++ pid_t pid, int is_sync) ++{ ++ RB_CLEAR_NODE(&bfqq->entity.rb_node); ++ INIT_LIST_HEAD(&bfqq->fifo); ++ INIT_HLIST_NODE(&bfqq->burst_list_node); ++ ++ atomic_set(&bfqq->ref, 0); ++ bfqq->bfqd = bfqd; ++ ++ bfq_mark_bfqq_prio_changed(bfqq); ++ ++ if (is_sync) { ++ if (!bfq_class_idle(bfqq)) ++ bfq_mark_bfqq_idle_window(bfqq); ++ bfq_mark_bfqq_sync(bfqq); ++ } ++ bfq_mark_bfqq_IO_bound(bfqq); ++ ++ /* Tentative initial value to trade off between thr and lat */ ++ bfqq->max_budget = (2 * bfq_max_budget(bfqd)) / 3; ++ bfqq->pid = pid; ++ ++ bfqq->wr_coeff = 1; ++ bfqq->last_wr_start_finish = 0; ++ /* ++ * Set to the value for which bfqq will not be deemed as ++ * soft rt when it becomes backlogged. ++ */ ++ bfqq->soft_rt_next_start = bfq_infinity_from_now(jiffies); ++} ++ ++static struct bfq_queue *bfq_find_alloc_queue(struct bfq_data *bfqd, ++ struct bfq_group *bfqg, ++ int is_sync, ++ struct bfq_io_cq *bic, ++ gfp_t gfp_mask) ++{ ++ struct bfq_queue *bfqq, *new_bfqq = NULL; ++ ++retry: ++ /* bic always exists here */ ++ bfqq = bic_to_bfqq(bic, is_sync); ++ ++ /* ++ * Always try a new alloc if we fall back to the OOM bfqq ++ * originally, since it should just be a temporary situation. ++ */ ++ if (bfqq == NULL || bfqq == &bfqd->oom_bfqq) { ++ bfqq = NULL; ++ if (new_bfqq != NULL) { ++ bfqq = new_bfqq; ++ new_bfqq = NULL; ++ } else if (gfp_mask & __GFP_WAIT) { ++ spin_unlock_irq(bfqd->queue->queue_lock); ++ new_bfqq = kmem_cache_alloc_node(bfq_pool, ++ gfp_mask | __GFP_ZERO, ++ bfqd->queue->node); ++ spin_lock_irq(bfqd->queue->queue_lock); ++ if (new_bfqq != NULL) ++ goto retry; ++ } else { ++ bfqq = kmem_cache_alloc_node(bfq_pool, ++ gfp_mask | __GFP_ZERO, ++ bfqd->queue->node); ++ } ++ ++ if (bfqq != NULL) { ++ bfq_init_bfqq(bfqd, bfqq, current->pid, is_sync); ++ bfq_init_prio_data(bfqq, bic); ++ bfq_init_entity(&bfqq->entity, bfqg); ++ bfq_log_bfqq(bfqd, bfqq, "allocated"); ++ } else { ++ bfqq = &bfqd->oom_bfqq; ++ bfq_log_bfqq(bfqd, bfqq, "using oom bfqq"); ++ } ++ } ++ ++ if (new_bfqq != NULL) ++ kmem_cache_free(bfq_pool, new_bfqq); ++ ++ return bfqq; ++} ++ ++static struct bfq_queue **bfq_async_queue_prio(struct bfq_data *bfqd, ++ struct bfq_group *bfqg, ++ int ioprio_class, int ioprio) ++{ ++ switch (ioprio_class) { ++ case IOPRIO_CLASS_RT: ++ return &bfqg->async_bfqq[0][ioprio]; ++ case IOPRIO_CLASS_NONE: ++ ioprio = IOPRIO_NORM; ++ /* fall through */ ++ case IOPRIO_CLASS_BE: ++ return &bfqg->async_bfqq[1][ioprio]; ++ case IOPRIO_CLASS_IDLE: ++ return &bfqg->async_idle_bfqq; ++ default: ++ BUG(); ++ } ++} ++ ++static struct bfq_queue *bfq_get_queue(struct bfq_data *bfqd, ++ struct bfq_group *bfqg, int is_sync, ++ struct bfq_io_cq *bic, gfp_t gfp_mask) ++{ ++ const int ioprio = IOPRIO_PRIO_DATA(bic->ioprio); ++ const int ioprio_class = IOPRIO_PRIO_CLASS(bic->ioprio); ++ struct bfq_queue **async_bfqq = NULL; ++ struct bfq_queue *bfqq = NULL; ++ ++ if (!is_sync) { ++ async_bfqq = bfq_async_queue_prio(bfqd, bfqg, ioprio_class, ++ ioprio); ++ bfqq = *async_bfqq; ++ } ++ ++ if (bfqq == NULL) ++ bfqq = bfq_find_alloc_queue(bfqd, bfqg, is_sync, bic, gfp_mask); ++ ++ /* ++ * Pin the queue now that it's allocated, scheduler exit will ++ * prune it. ++ */ ++ if (!is_sync && *async_bfqq == NULL) { ++ atomic_inc(&bfqq->ref); ++ bfq_log_bfqq(bfqd, bfqq, "get_queue, bfqq not in async: %p, %d", ++ bfqq, atomic_read(&bfqq->ref)); ++ *async_bfqq = bfqq; ++ } ++ ++ atomic_inc(&bfqq->ref); ++ bfq_log_bfqq(bfqd, bfqq, "get_queue, at end: %p, %d", bfqq, ++ atomic_read(&bfqq->ref)); ++ return bfqq; ++} ++ ++static void bfq_update_io_thinktime(struct bfq_data *bfqd, ++ struct bfq_io_cq *bic) ++{ ++ unsigned long elapsed = jiffies - bic->ttime.last_end_request; ++ unsigned long ttime = min(elapsed, 2UL * bfqd->bfq_slice_idle); ++ ++ bic->ttime.ttime_samples = (7*bic->ttime.ttime_samples + 256) / 8; ++ bic->ttime.ttime_total = (7*bic->ttime.ttime_total + 256*ttime) / 8; ++ bic->ttime.ttime_mean = (bic->ttime.ttime_total + 128) / ++ bic->ttime.ttime_samples; ++} ++ ++static void bfq_update_io_seektime(struct bfq_data *bfqd, ++ struct bfq_queue *bfqq, ++ struct request *rq) ++{ ++ sector_t sdist; ++ u64 total; ++ ++ if (bfqq->last_request_pos < blk_rq_pos(rq)) ++ sdist = blk_rq_pos(rq) - bfqq->last_request_pos; ++ else ++ sdist = bfqq->last_request_pos - blk_rq_pos(rq); ++ ++ /* ++ * Don't allow the seek distance to get too large from the ++ * odd fragment, pagein, etc. ++ */ ++ if (bfqq->seek_samples == 0) /* first request, not really a seek */ ++ sdist = 0; ++ else if (bfqq->seek_samples <= 60) /* second & third seek */ ++ sdist = min(sdist, (bfqq->seek_mean * 4) + 2*1024*1024); ++ else ++ sdist = min(sdist, (bfqq->seek_mean * 4) + 2*1024*64); ++ ++ bfqq->seek_samples = (7*bfqq->seek_samples + 256) / 8; ++ bfqq->seek_total = (7*bfqq->seek_total + (u64)256*sdist) / 8; ++ total = bfqq->seek_total + (bfqq->seek_samples/2); ++ do_div(total, bfqq->seek_samples); ++ bfqq->seek_mean = (sector_t)total; ++ ++ bfq_log_bfqq(bfqd, bfqq, "dist=%llu mean=%llu", (u64)sdist, ++ (u64)bfqq->seek_mean); ++} ++ ++/* ++ * Disable idle window if the process thinks too long or seeks so much that ++ * it doesn't matter. ++ */ ++static void bfq_update_idle_window(struct bfq_data *bfqd, ++ struct bfq_queue *bfqq, ++ struct bfq_io_cq *bic) ++{ ++ int enable_idle; ++ ++ /* Don't idle for async or idle io prio class. */ ++ if (!bfq_bfqq_sync(bfqq) || bfq_class_idle(bfqq)) ++ return; ++ ++ enable_idle = bfq_bfqq_idle_window(bfqq); ++ ++ if (atomic_read(&bic->icq.ioc->active_ref) == 0 || ++ bfqd->bfq_slice_idle == 0 || ++ (bfqd->hw_tag && BFQQ_SEEKY(bfqq) && ++ bfqq->wr_coeff == 1)) ++ enable_idle = 0; ++ else if (bfq_sample_valid(bic->ttime.ttime_samples)) { ++ if (bic->ttime.ttime_mean > bfqd->bfq_slice_idle && ++ bfqq->wr_coeff == 1) ++ enable_idle = 0; ++ else ++ enable_idle = 1; ++ } ++ bfq_log_bfqq(bfqd, bfqq, "update_idle_window: enable_idle %d", ++ enable_idle); ++ ++ if (enable_idle) ++ bfq_mark_bfqq_idle_window(bfqq); ++ else ++ bfq_clear_bfqq_idle_window(bfqq); ++} ++ ++/* ++ * Called when a new fs request (rq) is added to bfqq. Check if there's ++ * something we should do about it. ++ */ ++static void bfq_rq_enqueued(struct bfq_data *bfqd, struct bfq_queue *bfqq, ++ struct request *rq) ++{ ++ struct bfq_io_cq *bic = RQ_BIC(rq); ++ ++ if (rq->cmd_flags & REQ_META) ++ bfqq->meta_pending++; ++ ++ bfq_update_io_thinktime(bfqd, bic); ++ bfq_update_io_seektime(bfqd, bfqq, rq); ++ if (!BFQQ_SEEKY(bfqq) && bfq_bfqq_constantly_seeky(bfqq)) { ++ bfq_clear_bfqq_constantly_seeky(bfqq); ++ if (!blk_queue_nonrot(bfqd->queue)) { ++ BUG_ON(!bfqd->const_seeky_busy_in_flight_queues); ++ bfqd->const_seeky_busy_in_flight_queues--; ++ } ++ } ++ if (bfqq->entity.service > bfq_max_budget(bfqd) / 8 || ++ !BFQQ_SEEKY(bfqq)) ++ bfq_update_idle_window(bfqd, bfqq, bic); ++ ++ bfq_log_bfqq(bfqd, bfqq, ++ "rq_enqueued: idle_window=%d (seeky %d, mean %llu)", ++ bfq_bfqq_idle_window(bfqq), BFQQ_SEEKY(bfqq), ++ (long long unsigned)bfqq->seek_mean); ++ ++ bfqq->last_request_pos = blk_rq_pos(rq) + blk_rq_sectors(rq); ++ ++ if (bfqq == bfqd->in_service_queue && bfq_bfqq_wait_request(bfqq)) { ++ int small_req = bfqq->queued[rq_is_sync(rq)] == 1 && ++ blk_rq_sectors(rq) < 32; ++ int budget_timeout = bfq_bfqq_budget_timeout(bfqq); ++ ++ /* ++ * There is just this request queued: if the request ++ * is small and the queue is not to be expired, then ++ * just exit. ++ * ++ * In this way, if the disk is being idled to wait for ++ * a new request from the in-service queue, we avoid ++ * unplugging the device and committing the disk to serve ++ * just a small request. On the contrary, we wait for ++ * the block layer to decide when to unplug the device: ++ * hopefully, new requests will be merged to this one ++ * quickly, then the device will be unplugged and ++ * larger requests will be dispatched. ++ */ ++ if (small_req && !budget_timeout) ++ return; ++ ++ /* ++ * A large enough request arrived, or the queue is to ++ * be expired: in both cases disk idling is to be ++ * stopped, so clear wait_request flag and reset ++ * timer. ++ */ ++ bfq_clear_bfqq_wait_request(bfqq); ++ del_timer(&bfqd->idle_slice_timer); ++ ++ /* ++ * The queue is not empty, because a new request just ++ * arrived. Hence we can safely expire the queue, in ++ * case of budget timeout, without risking that the ++ * timestamps of the queue are not updated correctly. ++ * See [1] for more details. ++ */ ++ if (budget_timeout) ++ bfq_bfqq_expire(bfqd, bfqq, 0, BFQ_BFQQ_BUDGET_TIMEOUT); ++ ++ /* ++ * Let the request rip immediately, or let a new queue be ++ * selected if bfqq has just been expired. ++ */ ++ __blk_run_queue(bfqd->queue); ++ } ++} ++ ++static void bfq_insert_request(struct request_queue *q, struct request *rq) ++{ ++ struct bfq_data *bfqd = q->elevator->elevator_data; ++ struct bfq_queue *bfqq = RQ_BFQQ(rq); ++ ++ assert_spin_locked(bfqd->queue->queue_lock); ++ bfq_init_prio_data(bfqq, RQ_BIC(rq)); ++ ++ bfq_add_request(rq); ++ ++ rq->fifo_time = jiffies + bfqd->bfq_fifo_expire[rq_is_sync(rq)]; ++ list_add_tail(&rq->queuelist, &bfqq->fifo); ++ ++ bfq_rq_enqueued(bfqd, bfqq, rq); ++} ++ ++static void bfq_update_hw_tag(struct bfq_data *bfqd) ++{ ++ bfqd->max_rq_in_driver = max(bfqd->max_rq_in_driver, ++ bfqd->rq_in_driver); ++ ++ if (bfqd->hw_tag == 1) ++ return; ++ ++ /* ++ * This sample is valid if the number of outstanding requests ++ * is large enough to allow a queueing behavior. Note that the ++ * sum is not exact, as it's not taking into account deactivated ++ * requests. ++ */ ++ if (bfqd->rq_in_driver + bfqd->queued < BFQ_HW_QUEUE_THRESHOLD) ++ return; ++ ++ if (bfqd->hw_tag_samples++ < BFQ_HW_QUEUE_SAMPLES) ++ return; ++ ++ bfqd->hw_tag = bfqd->max_rq_in_driver > BFQ_HW_QUEUE_THRESHOLD; ++ bfqd->max_rq_in_driver = 0; ++ bfqd->hw_tag_samples = 0; ++} ++ ++static void bfq_completed_request(struct request_queue *q, struct request *rq) ++{ ++ struct bfq_queue *bfqq = RQ_BFQQ(rq); ++ struct bfq_data *bfqd = bfqq->bfqd; ++ bool sync = bfq_bfqq_sync(bfqq); ++ ++ bfq_log_bfqq(bfqd, bfqq, "completed one req with %u sects left (%d)", ++ blk_rq_sectors(rq), sync); ++ ++ bfq_update_hw_tag(bfqd); ++ ++ BUG_ON(!bfqd->rq_in_driver); ++ BUG_ON(!bfqq->dispatched); ++ bfqd->rq_in_driver--; ++ bfqq->dispatched--; ++ ++ if (!bfqq->dispatched && !bfq_bfqq_busy(bfqq)) { ++ bfq_weights_tree_remove(bfqd, &bfqq->entity, ++ &bfqd->queue_weights_tree); ++ if (!blk_queue_nonrot(bfqd->queue)) { ++ BUG_ON(!bfqd->busy_in_flight_queues); ++ bfqd->busy_in_flight_queues--; ++ if (bfq_bfqq_constantly_seeky(bfqq)) { ++ BUG_ON(!bfqd-> ++ const_seeky_busy_in_flight_queues); ++ bfqd->const_seeky_busy_in_flight_queues--; ++ } ++ } ++ } ++ ++ if (sync) { ++ bfqd->sync_flight--; ++ RQ_BIC(rq)->ttime.last_end_request = jiffies; ++ } ++ ++ /* ++ * If we are waiting to discover whether the request pattern of the ++ * task associated with the queue is actually isochronous, and ++ * both requisites for this condition to hold are satisfied, then ++ * compute soft_rt_next_start (see the comments to the function ++ * bfq_bfqq_softrt_next_start()). ++ */ ++ if (bfq_bfqq_softrt_update(bfqq) && bfqq->dispatched == 0 && ++ RB_EMPTY_ROOT(&bfqq->sort_list)) ++ bfqq->soft_rt_next_start = ++ bfq_bfqq_softrt_next_start(bfqd, bfqq); ++ ++ /* ++ * If this is the in-service queue, check if it needs to be expired, ++ * or if we want to idle in case it has no pending requests. ++ */ ++ if (bfqd->in_service_queue == bfqq) { ++ if (bfq_bfqq_budget_new(bfqq)) ++ bfq_set_budget_timeout(bfqd); ++ ++ if (bfq_bfqq_must_idle(bfqq)) { ++ bfq_arm_slice_timer(bfqd); ++ goto out; ++ } else if (bfq_may_expire_for_budg_timeout(bfqq)) ++ bfq_bfqq_expire(bfqd, bfqq, 0, BFQ_BFQQ_BUDGET_TIMEOUT); ++ else if (RB_EMPTY_ROOT(&bfqq->sort_list) && ++ (bfqq->dispatched == 0 || ++ !bfq_bfqq_must_not_expire(bfqq))) ++ bfq_bfqq_expire(bfqd, bfqq, 0, ++ BFQ_BFQQ_NO_MORE_REQUESTS); ++ } ++ ++ if (!bfqd->rq_in_driver) ++ bfq_schedule_dispatch(bfqd); ++ ++out: ++ return; ++} ++ ++static inline int __bfq_may_queue(struct bfq_queue *bfqq) ++{ ++ if (bfq_bfqq_wait_request(bfqq) && bfq_bfqq_must_alloc(bfqq)) { ++ bfq_clear_bfqq_must_alloc(bfqq); ++ return ELV_MQUEUE_MUST; ++ } ++ ++ return ELV_MQUEUE_MAY; ++} ++ ++static int bfq_may_queue(struct request_queue *q, int rw) ++{ ++ struct bfq_data *bfqd = q->elevator->elevator_data; ++ struct task_struct *tsk = current; ++ struct bfq_io_cq *bic; ++ struct bfq_queue *bfqq; ++ ++ /* ++ * Don't force setup of a queue from here, as a call to may_queue ++ * does not necessarily imply that a request actually will be ++ * queued. So just lookup a possibly existing queue, or return ++ * 'may queue' if that fails. ++ */ ++ bic = bfq_bic_lookup(bfqd, tsk->io_context); ++ if (bic == NULL) ++ return ELV_MQUEUE_MAY; ++ ++ bfqq = bic_to_bfqq(bic, rw_is_sync(rw)); ++ if (bfqq != NULL) { ++ bfq_init_prio_data(bfqq, bic); ++ ++ return __bfq_may_queue(bfqq); ++ } ++ ++ return ELV_MQUEUE_MAY; ++} ++ ++/* ++ * Queue lock held here. ++ */ ++static void bfq_put_request(struct request *rq) ++{ ++ struct bfq_queue *bfqq = RQ_BFQQ(rq); ++ ++ if (bfqq != NULL) { ++ const int rw = rq_data_dir(rq); ++ ++ BUG_ON(!bfqq->allocated[rw]); ++ bfqq->allocated[rw]--; ++ ++ rq->elv.priv[0] = NULL; ++ rq->elv.priv[1] = NULL; ++ ++ bfq_log_bfqq(bfqq->bfqd, bfqq, "put_request %p, %d", ++ bfqq, atomic_read(&bfqq->ref)); ++ bfq_put_queue(bfqq); ++ } ++} ++ ++static struct bfq_queue * ++bfq_merge_bfqqs(struct bfq_data *bfqd, struct bfq_io_cq *bic, ++ struct bfq_queue *bfqq) ++{ ++ bfq_log_bfqq(bfqd, bfqq, "merging with queue %lu", ++ (long unsigned)bfqq->new_bfqq->pid); ++ bic_set_bfqq(bic, bfqq->new_bfqq, 1); ++ bfq_mark_bfqq_coop(bfqq->new_bfqq); ++ bfq_put_queue(bfqq); ++ return bic_to_bfqq(bic, 1); ++} ++ ++/* ++ * Returns NULL if a new bfqq should be allocated, or the old bfqq if this ++ * was the last process referring to said bfqq. ++ */ ++static struct bfq_queue * ++bfq_split_bfqq(struct bfq_io_cq *bic, struct bfq_queue *bfqq) ++{ ++ bfq_log_bfqq(bfqq->bfqd, bfqq, "splitting queue"); ++ if (bfqq_process_refs(bfqq) == 1) { ++ bfqq->pid = current->pid; ++ bfq_clear_bfqq_coop(bfqq); ++ bfq_clear_bfqq_split_coop(bfqq); ++ return bfqq; ++ } ++ ++ bic_set_bfqq(bic, NULL, 1); ++ ++ bfq_put_cooperator(bfqq); ++ ++ bfq_put_queue(bfqq); ++ return NULL; ++} ++ ++/* ++ * Allocate bfq data structures associated with this request. ++ */ ++static int bfq_set_request(struct request_queue *q, struct request *rq, ++ struct bio *bio, gfp_t gfp_mask) ++{ ++ struct bfq_data *bfqd = q->elevator->elevator_data; ++ struct bfq_io_cq *bic = icq_to_bic(rq->elv.icq); ++ const int rw = rq_data_dir(rq); ++ const int is_sync = rq_is_sync(rq); ++ struct bfq_queue *bfqq; ++ struct bfq_group *bfqg; ++ unsigned long flags; ++ ++ might_sleep_if(gfp_mask & __GFP_WAIT); ++ ++ bfq_changed_ioprio(bic); ++ ++ spin_lock_irqsave(q->queue_lock, flags); ++ ++ if (bic == NULL) ++ goto queue_fail; ++ ++ bfqg = bfq_bic_update_cgroup(bic); ++ ++new_queue: ++ bfqq = bic_to_bfqq(bic, is_sync); ++ if (bfqq == NULL || bfqq == &bfqd->oom_bfqq) { ++ bfqq = bfq_get_queue(bfqd, bfqg, is_sync, bic, gfp_mask); ++ bic_set_bfqq(bic, bfqq, is_sync); ++ } else { ++ /* ++ * If the queue was seeky for too long, break it apart. ++ */ ++ if (bfq_bfqq_coop(bfqq) && bfq_bfqq_split_coop(bfqq)) { ++ bfq_log_bfqq(bfqd, bfqq, "breaking apart bfqq"); ++ bfqq = bfq_split_bfqq(bic, bfqq); ++ if (!bfqq) ++ goto new_queue; ++ } ++ ++ /* ++ * Check to see if this queue is scheduled to merge with ++ * another closely cooperating queue. The merging of queues ++ * happens here as it must be done in process context. ++ * The reference on new_bfqq was taken in merge_bfqqs. ++ */ ++ if (bfqq->new_bfqq != NULL) ++ bfqq = bfq_merge_bfqqs(bfqd, bic, bfqq); ++ } ++ ++ bfqq->allocated[rw]++; ++ atomic_inc(&bfqq->ref); ++ bfq_log_bfqq(bfqd, bfqq, "set_request: bfqq %p, %d", bfqq, ++ atomic_read(&bfqq->ref)); ++ ++ rq->elv.priv[0] = bic; ++ rq->elv.priv[1] = bfqq; ++ ++ spin_unlock_irqrestore(q->queue_lock, flags); ++ ++ return 0; ++ ++queue_fail: ++ bfq_schedule_dispatch(bfqd); ++ spin_unlock_irqrestore(q->queue_lock, flags); ++ ++ return 1; ++} ++ ++static void bfq_kick_queue(struct work_struct *work) ++{ ++ struct bfq_data *bfqd = ++ container_of(work, struct bfq_data, unplug_work); ++ struct request_queue *q = bfqd->queue; ++ ++ spin_lock_irq(q->queue_lock); ++ __blk_run_queue(q); ++ spin_unlock_irq(q->queue_lock); ++} ++ ++/* ++ * Handler of the expiration of the timer running if the in-service queue ++ * is idling inside its time slice. ++ */ ++static void bfq_idle_slice_timer(unsigned long data) ++{ ++ struct bfq_data *bfqd = (struct bfq_data *)data; ++ struct bfq_queue *bfqq; ++ unsigned long flags; ++ enum bfqq_expiration reason; ++ ++ spin_lock_irqsave(bfqd->queue->queue_lock, flags); ++ ++ bfqq = bfqd->in_service_queue; ++ /* ++ * Theoretical race here: the in-service queue can be NULL or ++ * different from the queue that was idling if the timer handler ++ * spins on the queue_lock and a new request arrives for the ++ * current queue and there is a full dispatch cycle that changes ++ * the in-service queue. This can hardly happen, but in the worst ++ * case we just expire a queue too early. ++ */ ++ if (bfqq != NULL) { ++ bfq_log_bfqq(bfqd, bfqq, "slice_timer expired"); ++ if (bfq_bfqq_budget_timeout(bfqq)) ++ /* ++ * Also here the queue can be safely expired ++ * for budget timeout without wasting ++ * guarantees ++ */ ++ reason = BFQ_BFQQ_BUDGET_TIMEOUT; ++ else if (bfqq->queued[0] == 0 && bfqq->queued[1] == 0) ++ /* ++ * The queue may not be empty upon timer expiration, ++ * because we may not disable the timer when the ++ * first request of the in-service queue arrives ++ * during disk idling. ++ */ ++ reason = BFQ_BFQQ_TOO_IDLE; ++ else ++ goto schedule_dispatch; ++ ++ bfq_bfqq_expire(bfqd, bfqq, 1, reason); ++ } ++ ++schedule_dispatch: ++ bfq_schedule_dispatch(bfqd); ++ ++ spin_unlock_irqrestore(bfqd->queue->queue_lock, flags); ++} ++ ++static void bfq_shutdown_timer_wq(struct bfq_data *bfqd) ++{ ++ del_timer_sync(&bfqd->idle_slice_timer); ++ cancel_work_sync(&bfqd->unplug_work); ++} ++ ++static inline void __bfq_put_async_bfqq(struct bfq_data *bfqd, ++ struct bfq_queue **bfqq_ptr) ++{ ++ struct bfq_group *root_group = bfqd->root_group; ++ struct bfq_queue *bfqq = *bfqq_ptr; ++ ++ bfq_log(bfqd, "put_async_bfqq: %p", bfqq); ++ if (bfqq != NULL) { ++ bfq_bfqq_move(bfqd, bfqq, &bfqq->entity, root_group); ++ bfq_log_bfqq(bfqd, bfqq, "put_async_bfqq: putting %p, %d", ++ bfqq, atomic_read(&bfqq->ref)); ++ bfq_put_queue(bfqq); ++ *bfqq_ptr = NULL; ++ } ++} ++ ++/* ++ * Release all the bfqg references to its async queues. If we are ++ * deallocating the group these queues may still contain requests, so ++ * we reparent them to the root cgroup (i.e., the only one that will ++ * exist for sure until all the requests on a device are gone). ++ */ ++static void bfq_put_async_queues(struct bfq_data *bfqd, struct bfq_group *bfqg) ++{ ++ int i, j; ++ ++ for (i = 0; i < 2; i++) ++ for (j = 0; j < IOPRIO_BE_NR; j++) ++ __bfq_put_async_bfqq(bfqd, &bfqg->async_bfqq[i][j]); ++ ++ __bfq_put_async_bfqq(bfqd, &bfqg->async_idle_bfqq); ++} ++ ++static void bfq_exit_queue(struct elevator_queue *e) ++{ ++ struct bfq_data *bfqd = e->elevator_data; ++ struct request_queue *q = bfqd->queue; ++ struct bfq_queue *bfqq, *n; ++ ++ bfq_shutdown_timer_wq(bfqd); ++ ++ spin_lock_irq(q->queue_lock); ++ ++ BUG_ON(bfqd->in_service_queue != NULL); ++ list_for_each_entry_safe(bfqq, n, &bfqd->idle_list, bfqq_list) ++ bfq_deactivate_bfqq(bfqd, bfqq, 0); ++ ++ bfq_disconnect_groups(bfqd); ++ spin_unlock_irq(q->queue_lock); ++ ++ bfq_shutdown_timer_wq(bfqd); ++ ++ synchronize_rcu(); ++ ++ BUG_ON(timer_pending(&bfqd->idle_slice_timer)); ++ ++ bfq_free_root_group(bfqd); ++ kfree(bfqd); ++} ++ ++static int bfq_init_queue(struct request_queue *q, struct elevator_type *e) ++{ ++ struct bfq_group *bfqg; ++ struct bfq_data *bfqd; ++ struct elevator_queue *eq; ++ ++ eq = elevator_alloc(q, e); ++ if (eq == NULL) ++ return -ENOMEM; ++ ++ bfqd = kzalloc_node(sizeof(*bfqd), GFP_KERNEL, q->node); ++ if (bfqd == NULL) { ++ kobject_put(&eq->kobj); ++ return -ENOMEM; ++ } ++ eq->elevator_data = bfqd; ++ ++ /* ++ * Our fallback bfqq if bfq_find_alloc_queue() runs into OOM issues. ++ * Grab a permanent reference to it, so that the normal code flow ++ * will not attempt to free it. ++ */ ++ bfq_init_bfqq(bfqd, &bfqd->oom_bfqq, 1, 0); ++ atomic_inc(&bfqd->oom_bfqq.ref); ++ bfqd->oom_bfqq.entity.new_ioprio = BFQ_DEFAULT_QUEUE_IOPRIO; ++ bfqd->oom_bfqq.entity.new_ioprio_class = IOPRIO_CLASS_BE; ++ /* ++ * Trigger weight initialization, according to ioprio, at the ++ * oom_bfqq's first activation. The oom_bfqq's ioprio and ioprio ++ * class won't be changed any more. ++ */ ++ bfqd->oom_bfqq.entity.ioprio_changed = 1; ++ ++ bfqd->queue = q; ++ ++ spin_lock_irq(q->queue_lock); ++ q->elevator = eq; ++ spin_unlock_irq(q->queue_lock); ++ ++ bfqg = bfq_alloc_root_group(bfqd, q->node); ++ if (bfqg == NULL) { ++ kfree(bfqd); ++ kobject_put(&eq->kobj); ++ return -ENOMEM; ++ } ++ ++ bfqd->root_group = bfqg; ++ bfq_init_entity(&bfqd->oom_bfqq.entity, bfqd->root_group); ++#ifdef CONFIG_CGROUP_BFQIO ++ bfqd->active_numerous_groups = 0; ++#endif ++ ++ init_timer(&bfqd->idle_slice_timer); ++ bfqd->idle_slice_timer.function = bfq_idle_slice_timer; ++ bfqd->idle_slice_timer.data = (unsigned long)bfqd; ++ ++ bfqd->rq_pos_tree = RB_ROOT; ++ bfqd->queue_weights_tree = RB_ROOT; ++ bfqd->group_weights_tree = RB_ROOT; ++ ++ INIT_WORK(&bfqd->unplug_work, bfq_kick_queue); ++ ++ INIT_LIST_HEAD(&bfqd->active_list); ++ INIT_LIST_HEAD(&bfqd->idle_list); ++ INIT_HLIST_HEAD(&bfqd->burst_list); ++ ++ bfqd->hw_tag = -1; ++ ++ bfqd->bfq_max_budget = bfq_default_max_budget; ++ ++ bfqd->bfq_quantum = bfq_quantum; ++ bfqd->bfq_fifo_expire[0] = bfq_fifo_expire[0]; ++ bfqd->bfq_fifo_expire[1] = bfq_fifo_expire[1]; ++ bfqd->bfq_back_max = bfq_back_max; ++ bfqd->bfq_back_penalty = bfq_back_penalty; ++ bfqd->bfq_slice_idle = bfq_slice_idle; ++ bfqd->bfq_class_idle_last_service = 0; ++ bfqd->bfq_max_budget_async_rq = bfq_max_budget_async_rq; ++ bfqd->bfq_timeout[BLK_RW_ASYNC] = bfq_timeout_async; ++ bfqd->bfq_timeout[BLK_RW_SYNC] = bfq_timeout_sync; ++ ++ bfqd->bfq_coop_thresh = 2; ++ bfqd->bfq_failed_cooperations = 7000; ++ bfqd->bfq_requests_within_timer = 120; ++ ++ bfqd->bfq_large_burst_thresh = 11; ++ bfqd->bfq_burst_interval = msecs_to_jiffies(500); ++ ++ bfqd->low_latency = true; ++ ++ bfqd->bfq_wr_coeff = 20; ++ bfqd->bfq_wr_rt_max_time = msecs_to_jiffies(300); ++ bfqd->bfq_wr_max_time = 0; ++ bfqd->bfq_wr_min_idle_time = msecs_to_jiffies(2000); ++ bfqd->bfq_wr_min_inter_arr_async = msecs_to_jiffies(500); ++ bfqd->bfq_wr_max_softrt_rate = 7000; /* ++ * Approximate rate required ++ * to playback or record a ++ * high-definition compressed ++ * video. ++ */ ++ bfqd->wr_busy_queues = 0; ++ bfqd->busy_in_flight_queues = 0; ++ bfqd->const_seeky_busy_in_flight_queues = 0; ++ ++ /* ++ * Begin by assuming, optimistically, that the device peak rate is ++ * equal to the highest reference rate. ++ */ ++ bfqd->RT_prod = R_fast[blk_queue_nonrot(bfqd->queue)] * ++ T_fast[blk_queue_nonrot(bfqd->queue)]; ++ bfqd->peak_rate = R_fast[blk_queue_nonrot(bfqd->queue)]; ++ bfqd->device_speed = BFQ_BFQD_FAST; ++ ++ return 0; ++} ++ ++static void bfq_slab_kill(void) ++{ ++ if (bfq_pool != NULL) ++ kmem_cache_destroy(bfq_pool); ++} ++ ++static int __init bfq_slab_setup(void) ++{ ++ bfq_pool = KMEM_CACHE(bfq_queue, 0); ++ if (bfq_pool == NULL) ++ return -ENOMEM; ++ return 0; ++} ++ ++static ssize_t bfq_var_show(unsigned int var, char *page) ++{ ++ return sprintf(page, "%d\n", var); ++} ++ ++static ssize_t bfq_var_store(unsigned long *var, const char *page, ++ size_t count) ++{ ++ unsigned long new_val; ++ int ret = kstrtoul(page, 10, &new_val); ++ ++ if (ret == 0) ++ *var = new_val; ++ ++ return count; ++} ++ ++static ssize_t bfq_wr_max_time_show(struct elevator_queue *e, char *page) ++{ ++ struct bfq_data *bfqd = e->elevator_data; ++ return sprintf(page, "%d\n", bfqd->bfq_wr_max_time > 0 ? ++ jiffies_to_msecs(bfqd->bfq_wr_max_time) : ++ jiffies_to_msecs(bfq_wr_duration(bfqd))); ++} ++ ++static ssize_t bfq_weights_show(struct elevator_queue *e, char *page) ++{ ++ struct bfq_queue *bfqq; ++ struct bfq_data *bfqd = e->elevator_data; ++ ssize_t num_char = 0; ++ ++ num_char += sprintf(page + num_char, "Tot reqs queued %d\n\n", ++ bfqd->queued); ++ ++ spin_lock_irq(bfqd->queue->queue_lock); ++ ++ num_char += sprintf(page + num_char, "Active:\n"); ++ list_for_each_entry(bfqq, &bfqd->active_list, bfqq_list) { ++ num_char += sprintf(page + num_char, ++ "pid%d: weight %hu, nr_queued %d %d, dur %d/%u\n", ++ bfqq->pid, ++ bfqq->entity.weight, ++ bfqq->queued[0], ++ bfqq->queued[1], ++ jiffies_to_msecs(jiffies - bfqq->last_wr_start_finish), ++ jiffies_to_msecs(bfqq->wr_cur_max_time)); ++ } ++ ++ num_char += sprintf(page + num_char, "Idle:\n"); ++ list_for_each_entry(bfqq, &bfqd->idle_list, bfqq_list) { ++ num_char += sprintf(page + num_char, ++ "pid%d: weight %hu, dur %d/%u\n", ++ bfqq->pid, ++ bfqq->entity.weight, ++ jiffies_to_msecs(jiffies - ++ bfqq->last_wr_start_finish), ++ jiffies_to_msecs(bfqq->wr_cur_max_time)); ++ } ++ ++ spin_unlock_irq(bfqd->queue->queue_lock); ++ ++ return num_char; ++} ++ ++#define SHOW_FUNCTION(__FUNC, __VAR, __CONV) \ ++static ssize_t __FUNC(struct elevator_queue *e, char *page) \ ++{ \ ++ struct bfq_data *bfqd = e->elevator_data; \ ++ unsigned int __data = __VAR; \ ++ if (__CONV) \ ++ __data = jiffies_to_msecs(__data); \ ++ return bfq_var_show(__data, (page)); \ ++} ++SHOW_FUNCTION(bfq_quantum_show, bfqd->bfq_quantum, 0); ++SHOW_FUNCTION(bfq_fifo_expire_sync_show, bfqd->bfq_fifo_expire[1], 1); ++SHOW_FUNCTION(bfq_fifo_expire_async_show, bfqd->bfq_fifo_expire[0], 1); ++SHOW_FUNCTION(bfq_back_seek_max_show, bfqd->bfq_back_max, 0); ++SHOW_FUNCTION(bfq_back_seek_penalty_show, bfqd->bfq_back_penalty, 0); ++SHOW_FUNCTION(bfq_slice_idle_show, bfqd->bfq_slice_idle, 1); ++SHOW_FUNCTION(bfq_max_budget_show, bfqd->bfq_user_max_budget, 0); ++SHOW_FUNCTION(bfq_max_budget_async_rq_show, ++ bfqd->bfq_max_budget_async_rq, 0); ++SHOW_FUNCTION(bfq_timeout_sync_show, bfqd->bfq_timeout[BLK_RW_SYNC], 1); ++SHOW_FUNCTION(bfq_timeout_async_show, bfqd->bfq_timeout[BLK_RW_ASYNC], 1); ++SHOW_FUNCTION(bfq_low_latency_show, bfqd->low_latency, 0); ++SHOW_FUNCTION(bfq_wr_coeff_show, bfqd->bfq_wr_coeff, 0); ++SHOW_FUNCTION(bfq_wr_rt_max_time_show, bfqd->bfq_wr_rt_max_time, 1); ++SHOW_FUNCTION(bfq_wr_min_idle_time_show, bfqd->bfq_wr_min_idle_time, 1); ++SHOW_FUNCTION(bfq_wr_min_inter_arr_async_show, bfqd->bfq_wr_min_inter_arr_async, ++ 1); ++SHOW_FUNCTION(bfq_wr_max_softrt_rate_show, bfqd->bfq_wr_max_softrt_rate, 0); ++#undef SHOW_FUNCTION ++ ++#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV) \ ++static ssize_t \ ++__FUNC(struct elevator_queue *e, const char *page, size_t count) \ ++{ \ ++ struct bfq_data *bfqd = e->elevator_data; \ ++ unsigned long uninitialized_var(__data); \ ++ int ret = bfq_var_store(&__data, (page), count); \ ++ if (__data < (MIN)) \ ++ __data = (MIN); \ ++ else if (__data > (MAX)) \ ++ __data = (MAX); \ ++ if (__CONV) \ ++ *(__PTR) = msecs_to_jiffies(__data); \ ++ else \ ++ *(__PTR) = __data; \ ++ return ret; \ ++} ++STORE_FUNCTION(bfq_quantum_store, &bfqd->bfq_quantum, 1, INT_MAX, 0); ++STORE_FUNCTION(bfq_fifo_expire_sync_store, &bfqd->bfq_fifo_expire[1], 1, ++ INT_MAX, 1); ++STORE_FUNCTION(bfq_fifo_expire_async_store, &bfqd->bfq_fifo_expire[0], 1, ++ INT_MAX, 1); ++STORE_FUNCTION(bfq_back_seek_max_store, &bfqd->bfq_back_max, 0, INT_MAX, 0); ++STORE_FUNCTION(bfq_back_seek_penalty_store, &bfqd->bfq_back_penalty, 1, ++ INT_MAX, 0); ++STORE_FUNCTION(bfq_slice_idle_store, &bfqd->bfq_slice_idle, 0, INT_MAX, 1); ++STORE_FUNCTION(bfq_max_budget_async_rq_store, &bfqd->bfq_max_budget_async_rq, ++ 1, INT_MAX, 0); ++STORE_FUNCTION(bfq_timeout_async_store, &bfqd->bfq_timeout[BLK_RW_ASYNC], 0, ++ INT_MAX, 1); ++STORE_FUNCTION(bfq_wr_coeff_store, &bfqd->bfq_wr_coeff, 1, INT_MAX, 0); ++STORE_FUNCTION(bfq_wr_max_time_store, &bfqd->bfq_wr_max_time, 0, INT_MAX, 1); ++STORE_FUNCTION(bfq_wr_rt_max_time_store, &bfqd->bfq_wr_rt_max_time, 0, INT_MAX, ++ 1); ++STORE_FUNCTION(bfq_wr_min_idle_time_store, &bfqd->bfq_wr_min_idle_time, 0, ++ INT_MAX, 1); ++STORE_FUNCTION(bfq_wr_min_inter_arr_async_store, ++ &bfqd->bfq_wr_min_inter_arr_async, 0, INT_MAX, 1); ++STORE_FUNCTION(bfq_wr_max_softrt_rate_store, &bfqd->bfq_wr_max_softrt_rate, 0, ++ INT_MAX, 0); ++#undef STORE_FUNCTION ++ ++/* do nothing for the moment */ ++static ssize_t bfq_weights_store(struct elevator_queue *e, ++ const char *page, size_t count) ++{ ++ return count; ++} ++ ++static inline unsigned long bfq_estimated_max_budget(struct bfq_data *bfqd) ++{ ++ u64 timeout = jiffies_to_msecs(bfqd->bfq_timeout[BLK_RW_SYNC]); ++ ++ if (bfqd->peak_rate_samples >= BFQ_PEAK_RATE_SAMPLES) ++ return bfq_calc_max_budget(bfqd->peak_rate, timeout); ++ else ++ return bfq_default_max_budget; ++} ++ ++static ssize_t bfq_max_budget_store(struct elevator_queue *e, ++ const char *page, size_t count) ++{ ++ struct bfq_data *bfqd = e->elevator_data; ++ unsigned long uninitialized_var(__data); ++ int ret = bfq_var_store(&__data, (page), count); ++ ++ if (__data == 0) ++ bfqd->bfq_max_budget = bfq_estimated_max_budget(bfqd); ++ else { ++ if (__data > INT_MAX) ++ __data = INT_MAX; ++ bfqd->bfq_max_budget = __data; ++ } ++ ++ bfqd->bfq_user_max_budget = __data; ++ ++ return ret; ++} ++ ++static ssize_t bfq_timeout_sync_store(struct elevator_queue *e, ++ const char *page, size_t count) ++{ ++ struct bfq_data *bfqd = e->elevator_data; ++ unsigned long uninitialized_var(__data); ++ int ret = bfq_var_store(&__data, (page), count); ++ ++ if (__data < 1) ++ __data = 1; ++ else if (__data > INT_MAX) ++ __data = INT_MAX; ++ ++ bfqd->bfq_timeout[BLK_RW_SYNC] = msecs_to_jiffies(__data); ++ if (bfqd->bfq_user_max_budget == 0) ++ bfqd->bfq_max_budget = bfq_estimated_max_budget(bfqd); ++ ++ return ret; ++} ++ ++static ssize_t bfq_low_latency_store(struct elevator_queue *e, ++ const char *page, size_t count) ++{ ++ struct bfq_data *bfqd = e->elevator_data; ++ unsigned long uninitialized_var(__data); ++ int ret = bfq_var_store(&__data, (page), count); ++ ++ if (__data > 1) ++ __data = 1; ++ if (__data == 0 && bfqd->low_latency != 0) ++ bfq_end_wr(bfqd); ++ bfqd->low_latency = __data; ++ ++ return ret; ++} ++ ++#define BFQ_ATTR(name) \ ++ __ATTR(name, S_IRUGO|S_IWUSR, bfq_##name##_show, bfq_##name##_store) ++ ++static struct elv_fs_entry bfq_attrs[] = { ++ BFQ_ATTR(quantum), ++ BFQ_ATTR(fifo_expire_sync), ++ BFQ_ATTR(fifo_expire_async), ++ BFQ_ATTR(back_seek_max), ++ BFQ_ATTR(back_seek_penalty), ++ BFQ_ATTR(slice_idle), ++ BFQ_ATTR(max_budget), ++ BFQ_ATTR(max_budget_async_rq), ++ BFQ_ATTR(timeout_sync), ++ BFQ_ATTR(timeout_async), ++ BFQ_ATTR(low_latency), ++ BFQ_ATTR(wr_coeff), ++ BFQ_ATTR(wr_max_time), ++ BFQ_ATTR(wr_rt_max_time), ++ BFQ_ATTR(wr_min_idle_time), ++ BFQ_ATTR(wr_min_inter_arr_async), ++ BFQ_ATTR(wr_max_softrt_rate), ++ BFQ_ATTR(weights), ++ __ATTR_NULL ++}; ++ ++static struct elevator_type iosched_bfq = { ++ .ops = { ++ .elevator_merge_fn = bfq_merge, ++ .elevator_merged_fn = bfq_merged_request, ++ .elevator_merge_req_fn = bfq_merged_requests, ++ .elevator_allow_merge_fn = bfq_allow_merge, ++ .elevator_dispatch_fn = bfq_dispatch_requests, ++ .elevator_add_req_fn = bfq_insert_request, ++ .elevator_activate_req_fn = bfq_activate_request, ++ .elevator_deactivate_req_fn = bfq_deactivate_request, ++ .elevator_completed_req_fn = bfq_completed_request, ++ .elevator_former_req_fn = elv_rb_former_request, ++ .elevator_latter_req_fn = elv_rb_latter_request, ++ .elevator_init_icq_fn = bfq_init_icq, ++ .elevator_exit_icq_fn = bfq_exit_icq, ++ .elevator_set_req_fn = bfq_set_request, ++ .elevator_put_req_fn = bfq_put_request, ++ .elevator_may_queue_fn = bfq_may_queue, ++ .elevator_init_fn = bfq_init_queue, ++ .elevator_exit_fn = bfq_exit_queue, ++ }, ++ .icq_size = sizeof(struct bfq_io_cq), ++ .icq_align = __alignof__(struct bfq_io_cq), ++ .elevator_attrs = bfq_attrs, ++ .elevator_name = "bfq", ++ .elevator_owner = THIS_MODULE, ++}; ++ ++static int __init bfq_init(void) ++{ ++ /* ++ * Can be 0 on HZ < 1000 setups. ++ */ ++ if (bfq_slice_idle == 0) ++ bfq_slice_idle = 1; ++ ++ if (bfq_timeout_async == 0) ++ bfq_timeout_async = 1; ++ ++ if (bfq_slab_setup()) ++ return -ENOMEM; ++ ++ /* ++ * Times to load large popular applications for the typical systems ++ * installed on the reference devices (see the comments before the ++ * definitions of the two arrays). ++ */ ++ T_slow[0] = msecs_to_jiffies(2600); ++ T_slow[1] = msecs_to_jiffies(1000); ++ T_fast[0] = msecs_to_jiffies(5500); ++ T_fast[1] = msecs_to_jiffies(2000); ++ ++ /* ++ * Thresholds that determine the switch between speed classes (see ++ * the comments before the definition of the array). ++ */ ++ device_speed_thresh[0] = (R_fast[0] + R_slow[0]) / 2; ++ device_speed_thresh[1] = (R_fast[1] + R_slow[1]) / 2; ++ ++ elv_register(&iosched_bfq); ++ pr_info("BFQ I/O-scheduler version: v7r7"); ++ ++ return 0; ++} ++ ++static void __exit bfq_exit(void) ++{ ++ elv_unregister(&iosched_bfq); ++ bfq_slab_kill(); ++} ++ ++module_init(bfq_init); ++module_exit(bfq_exit); ++ ++MODULE_AUTHOR("Fabio Checconi, Paolo Valente"); ++MODULE_LICENSE("GPL"); +diff --git a/block/bfq-sched.c b/block/bfq-sched.c +new file mode 100644 +index 0000000..2931563 +--- /dev/null ++++ b/block/bfq-sched.c +@@ -0,0 +1,1214 @@ ++/* ++ * BFQ: Hierarchical B-WF2Q+ scheduler. ++ * ++ * Based on ideas and code from CFQ: ++ * Copyright (C) 2003 Jens Axboe ++ * ++ * Copyright (C) 2008 Fabio Checconi ++ * Paolo Valente ++ * ++ * Copyright (C) 2010 Paolo Valente ++ */ ++ ++#ifdef CONFIG_CGROUP_BFQIO ++#define for_each_entity(entity) \ ++ for (; entity != NULL; entity = entity->parent) ++ ++#define for_each_entity_safe(entity, parent) \ ++ for (; entity && ({ parent = entity->parent; 1; }); entity = parent) ++ ++static struct bfq_entity *bfq_lookup_next_entity(struct bfq_sched_data *sd, ++ int extract, ++ struct bfq_data *bfqd); ++ ++static inline void bfq_update_budget(struct bfq_entity *next_in_service) ++{ ++ struct bfq_entity *bfqg_entity; ++ struct bfq_group *bfqg; ++ struct bfq_sched_data *group_sd; ++ ++ BUG_ON(next_in_service == NULL); ++ ++ group_sd = next_in_service->sched_data; ++ ++ bfqg = container_of(group_sd, struct bfq_group, sched_data); ++ /* ++ * bfq_group's my_entity field is not NULL only if the group ++ * is not the root group. We must not touch the root entity ++ * as it must never become an in-service entity. ++ */ ++ bfqg_entity = bfqg->my_entity; ++ if (bfqg_entity != NULL) ++ bfqg_entity->budget = next_in_service->budget; ++} ++ ++static int bfq_update_next_in_service(struct bfq_sched_data *sd) ++{ ++ struct bfq_entity *next_in_service; ++ ++ if (sd->in_service_entity != NULL) ++ /* will update/requeue at the end of service */ ++ return 0; ++ ++ /* ++ * NOTE: this can be improved in many ways, such as returning ++ * 1 (and thus propagating upwards the update) only when the ++ * budget changes, or caching the bfqq that will be scheduled ++ * next from this subtree. By now we worry more about ++ * correctness than about performance... ++ */ ++ next_in_service = bfq_lookup_next_entity(sd, 0, NULL); ++ sd->next_in_service = next_in_service; ++ ++ if (next_in_service != NULL) ++ bfq_update_budget(next_in_service); ++ ++ return 1; ++} ++ ++static inline void bfq_check_next_in_service(struct bfq_sched_data *sd, ++ struct bfq_entity *entity) ++{ ++ BUG_ON(sd->next_in_service != entity); ++} ++#else ++#define for_each_entity(entity) \ ++ for (; entity != NULL; entity = NULL) ++ ++#define for_each_entity_safe(entity, parent) \ ++ for (parent = NULL; entity != NULL; entity = parent) ++ ++static inline int bfq_update_next_in_service(struct bfq_sched_data *sd) ++{ ++ return 0; ++} ++ ++static inline void bfq_check_next_in_service(struct bfq_sched_data *sd, ++ struct bfq_entity *entity) ++{ ++} ++ ++static inline void bfq_update_budget(struct bfq_entity *next_in_service) ++{ ++} ++#endif ++ ++/* ++ * Shift for timestamp calculations. This actually limits the maximum ++ * service allowed in one timestamp delta (small shift values increase it), ++ * the maximum total weight that can be used for the queues in the system ++ * (big shift values increase it), and the period of virtual time ++ * wraparounds. ++ */ ++#define WFQ_SERVICE_SHIFT 22 ++ ++/** ++ * bfq_gt - compare two timestamps. ++ * @a: first ts. ++ * @b: second ts. ++ * ++ * Return @a > @b, dealing with wrapping correctly. ++ */ ++static inline int bfq_gt(u64 a, u64 b) ++{ ++ return (s64)(a - b) > 0; ++} ++ ++static inline struct bfq_queue *bfq_entity_to_bfqq(struct bfq_entity *entity) ++{ ++ struct bfq_queue *bfqq = NULL; ++ ++ BUG_ON(entity == NULL); ++ ++ if (entity->my_sched_data == NULL) ++ bfqq = container_of(entity, struct bfq_queue, entity); ++ ++ return bfqq; ++} ++ ++ ++/** ++ * bfq_delta - map service into the virtual time domain. ++ * @service: amount of service. ++ * @weight: scale factor (weight of an entity or weight sum). ++ */ ++static inline u64 bfq_delta(unsigned long service, ++ unsigned long weight) ++{ ++ u64 d = (u64)service << WFQ_SERVICE_SHIFT; ++ ++ do_div(d, weight); ++ return d; ++} ++ ++/** ++ * bfq_calc_finish - assign the finish time to an entity. ++ * @entity: the entity to act upon. ++ * @service: the service to be charged to the entity. ++ */ ++static inline void bfq_calc_finish(struct bfq_entity *entity, ++ unsigned long service) ++{ ++ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); ++ ++ BUG_ON(entity->weight == 0); ++ ++ entity->finish = entity->start + ++ bfq_delta(service, entity->weight); ++ ++ if (bfqq != NULL) { ++ bfq_log_bfqq(bfqq->bfqd, bfqq, ++ "calc_finish: serv %lu, w %d", ++ service, entity->weight); ++ bfq_log_bfqq(bfqq->bfqd, bfqq, ++ "calc_finish: start %llu, finish %llu, delta %llu", ++ entity->start, entity->finish, ++ bfq_delta(service, entity->weight)); ++ } ++} ++ ++/** ++ * bfq_entity_of - get an entity from a node. ++ * @node: the node field of the entity. ++ * ++ * Convert a node pointer to the relative entity. This is used only ++ * to simplify the logic of some functions and not as the generic ++ * conversion mechanism because, e.g., in the tree walking functions, ++ * the check for a %NULL value would be redundant. ++ */ ++static inline struct bfq_entity *bfq_entity_of(struct rb_node *node) ++{ ++ struct bfq_entity *entity = NULL; ++ ++ if (node != NULL) ++ entity = rb_entry(node, struct bfq_entity, rb_node); ++ ++ return entity; ++} ++ ++/** ++ * bfq_extract - remove an entity from a tree. ++ * @root: the tree root. ++ * @entity: the entity to remove. ++ */ ++static inline void bfq_extract(struct rb_root *root, ++ struct bfq_entity *entity) ++{ ++ BUG_ON(entity->tree != root); ++ ++ entity->tree = NULL; ++ rb_erase(&entity->rb_node, root); ++} ++ ++/** ++ * bfq_idle_extract - extract an entity from the idle tree. ++ * @st: the service tree of the owning @entity. ++ * @entity: the entity being removed. ++ */ ++static void bfq_idle_extract(struct bfq_service_tree *st, ++ struct bfq_entity *entity) ++{ ++ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); ++ struct rb_node *next; ++ ++ BUG_ON(entity->tree != &st->idle); ++ ++ if (entity == st->first_idle) { ++ next = rb_next(&entity->rb_node); ++ st->first_idle = bfq_entity_of(next); ++ } ++ ++ if (entity == st->last_idle) { ++ next = rb_prev(&entity->rb_node); ++ st->last_idle = bfq_entity_of(next); ++ } ++ ++ bfq_extract(&st->idle, entity); ++ ++ if (bfqq != NULL) ++ list_del(&bfqq->bfqq_list); ++} ++ ++/** ++ * bfq_insert - generic tree insertion. ++ * @root: tree root. ++ * @entity: entity to insert. ++ * ++ * This is used for the idle and the active tree, since they are both ++ * ordered by finish time. ++ */ ++static void bfq_insert(struct rb_root *root, struct bfq_entity *entity) ++{ ++ struct bfq_entity *entry; ++ struct rb_node **node = &root->rb_node; ++ struct rb_node *parent = NULL; ++ ++ BUG_ON(entity->tree != NULL); ++ ++ while (*node != NULL) { ++ parent = *node; ++ entry = rb_entry(parent, struct bfq_entity, rb_node); ++ ++ if (bfq_gt(entry->finish, entity->finish)) ++ node = &parent->rb_left; ++ else ++ node = &parent->rb_right; ++ } ++ ++ rb_link_node(&entity->rb_node, parent, node); ++ rb_insert_color(&entity->rb_node, root); ++ ++ entity->tree = root; ++} ++ ++/** ++ * bfq_update_min - update the min_start field of a entity. ++ * @entity: the entity to update. ++ * @node: one of its children. ++ * ++ * This function is called when @entity may store an invalid value for ++ * min_start due to updates to the active tree. The function assumes ++ * that the subtree rooted at @node (which may be its left or its right ++ * child) has a valid min_start value. ++ */ ++static inline void bfq_update_min(struct bfq_entity *entity, ++ struct rb_node *node) ++{ ++ struct bfq_entity *child; ++ ++ if (node != NULL) { ++ child = rb_entry(node, struct bfq_entity, rb_node); ++ if (bfq_gt(entity->min_start, child->min_start)) ++ entity->min_start = child->min_start; ++ } ++} ++ ++/** ++ * bfq_update_active_node - recalculate min_start. ++ * @node: the node to update. ++ * ++ * @node may have changed position or one of its children may have moved, ++ * this function updates its min_start value. The left and right subtrees ++ * are assumed to hold a correct min_start value. ++ */ ++static inline void bfq_update_active_node(struct rb_node *node) ++{ ++ struct bfq_entity *entity = rb_entry(node, struct bfq_entity, rb_node); ++ ++ entity->min_start = entity->start; ++ bfq_update_min(entity, node->rb_right); ++ bfq_update_min(entity, node->rb_left); ++} ++ ++/** ++ * bfq_update_active_tree - update min_start for the whole active tree. ++ * @node: the starting node. ++ * ++ * @node must be the deepest modified node after an update. This function ++ * updates its min_start using the values held by its children, assuming ++ * that they did not change, and then updates all the nodes that may have ++ * changed in the path to the root. The only nodes that may have changed ++ * are the ones in the path or their siblings. ++ */ ++static void bfq_update_active_tree(struct rb_node *node) ++{ ++ struct rb_node *parent; ++ ++up: ++ bfq_update_active_node(node); ++ ++ parent = rb_parent(node); ++ if (parent == NULL) ++ return; ++ ++ if (node == parent->rb_left && parent->rb_right != NULL) ++ bfq_update_active_node(parent->rb_right); ++ else if (parent->rb_left != NULL) ++ bfq_update_active_node(parent->rb_left); ++ ++ node = parent; ++ goto up; ++} ++ ++static void bfq_weights_tree_add(struct bfq_data *bfqd, ++ struct bfq_entity *entity, ++ struct rb_root *root); ++ ++static void bfq_weights_tree_remove(struct bfq_data *bfqd, ++ struct bfq_entity *entity, ++ struct rb_root *root); ++ ++ ++/** ++ * bfq_active_insert - insert an entity in the active tree of its ++ * group/device. ++ * @st: the service tree of the entity. ++ * @entity: the entity being inserted. ++ * ++ * The active tree is ordered by finish time, but an extra key is kept ++ * per each node, containing the minimum value for the start times of ++ * its children (and the node itself), so it's possible to search for ++ * the eligible node with the lowest finish time in logarithmic time. ++ */ ++static void bfq_active_insert(struct bfq_service_tree *st, ++ struct bfq_entity *entity) ++{ ++ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); ++ struct rb_node *node = &entity->rb_node; ++#ifdef CONFIG_CGROUP_BFQIO ++ struct bfq_sched_data *sd = NULL; ++ struct bfq_group *bfqg = NULL; ++ struct bfq_data *bfqd = NULL; ++#endif ++ ++ bfq_insert(&st->active, entity); ++ ++ if (node->rb_left != NULL) ++ node = node->rb_left; ++ else if (node->rb_right != NULL) ++ node = node->rb_right; ++ ++ bfq_update_active_tree(node); ++ ++#ifdef CONFIG_CGROUP_BFQIO ++ sd = entity->sched_data; ++ bfqg = container_of(sd, struct bfq_group, sched_data); ++ BUG_ON(!bfqg); ++ bfqd = (struct bfq_data *)bfqg->bfqd; ++#endif ++ if (bfqq != NULL) ++ list_add(&bfqq->bfqq_list, &bfqq->bfqd->active_list); ++#ifdef CONFIG_CGROUP_BFQIO ++ else { /* bfq_group */ ++ BUG_ON(!bfqd); ++ bfq_weights_tree_add(bfqd, entity, &bfqd->group_weights_tree); ++ } ++ if (bfqg != bfqd->root_group) { ++ BUG_ON(!bfqg); ++ BUG_ON(!bfqd); ++ bfqg->active_entities++; ++ if (bfqg->active_entities == 2) ++ bfqd->active_numerous_groups++; ++ } ++#endif ++} ++ ++/** ++ * bfq_ioprio_to_weight - calc a weight from an ioprio. ++ * @ioprio: the ioprio value to convert. ++ */ ++static inline unsigned short bfq_ioprio_to_weight(int ioprio) ++{ ++ BUG_ON(ioprio < 0 || ioprio >= IOPRIO_BE_NR); ++ return IOPRIO_BE_NR - ioprio; ++} ++ ++/** ++ * bfq_weight_to_ioprio - calc an ioprio from a weight. ++ * @weight: the weight value to convert. ++ * ++ * To preserve as mush as possible the old only-ioprio user interface, ++ * 0 is used as an escape ioprio value for weights (numerically) equal or ++ * larger than IOPRIO_BE_NR ++ */ ++static inline unsigned short bfq_weight_to_ioprio(int weight) ++{ ++ BUG_ON(weight < BFQ_MIN_WEIGHT || weight > BFQ_MAX_WEIGHT); ++ return IOPRIO_BE_NR - weight < 0 ? 0 : IOPRIO_BE_NR - weight; ++} ++ ++static inline void bfq_get_entity(struct bfq_entity *entity) ++{ ++ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); ++ ++ if (bfqq != NULL) { ++ atomic_inc(&bfqq->ref); ++ bfq_log_bfqq(bfqq->bfqd, bfqq, "get_entity: %p %d", ++ bfqq, atomic_read(&bfqq->ref)); ++ } ++} ++ ++/** ++ * bfq_find_deepest - find the deepest node that an extraction can modify. ++ * @node: the node being removed. ++ * ++ * Do the first step of an extraction in an rb tree, looking for the ++ * node that will replace @node, and returning the deepest node that ++ * the following modifications to the tree can touch. If @node is the ++ * last node in the tree return %NULL. ++ */ ++static struct rb_node *bfq_find_deepest(struct rb_node *node) ++{ ++ struct rb_node *deepest; ++ ++ if (node->rb_right == NULL && node->rb_left == NULL) ++ deepest = rb_parent(node); ++ else if (node->rb_right == NULL) ++ deepest = node->rb_left; ++ else if (node->rb_left == NULL) ++ deepest = node->rb_right; ++ else { ++ deepest = rb_next(node); ++ if (deepest->rb_right != NULL) ++ deepest = deepest->rb_right; ++ else if (rb_parent(deepest) != node) ++ deepest = rb_parent(deepest); ++ } ++ ++ return deepest; ++} ++ ++/** ++ * bfq_active_extract - remove an entity from the active tree. ++ * @st: the service_tree containing the tree. ++ * @entity: the entity being removed. ++ */ ++static void bfq_active_extract(struct bfq_service_tree *st, ++ struct bfq_entity *entity) ++{ ++ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); ++ struct rb_node *node; ++#ifdef CONFIG_CGROUP_BFQIO ++ struct bfq_sched_data *sd = NULL; ++ struct bfq_group *bfqg = NULL; ++ struct bfq_data *bfqd = NULL; ++#endif ++ ++ node = bfq_find_deepest(&entity->rb_node); ++ bfq_extract(&st->active, entity); ++ ++ if (node != NULL) ++ bfq_update_active_tree(node); ++ ++#ifdef CONFIG_CGROUP_BFQIO ++ sd = entity->sched_data; ++ bfqg = container_of(sd, struct bfq_group, sched_data); ++ BUG_ON(!bfqg); ++ bfqd = (struct bfq_data *)bfqg->bfqd; ++#endif ++ if (bfqq != NULL) ++ list_del(&bfqq->bfqq_list); ++#ifdef CONFIG_CGROUP_BFQIO ++ else { /* bfq_group */ ++ BUG_ON(!bfqd); ++ bfq_weights_tree_remove(bfqd, entity, ++ &bfqd->group_weights_tree); ++ } ++ if (bfqg != bfqd->root_group) { ++ BUG_ON(!bfqg); ++ BUG_ON(!bfqd); ++ BUG_ON(!bfqg->active_entities); ++ bfqg->active_entities--; ++ if (bfqg->active_entities == 1) { ++ BUG_ON(!bfqd->active_numerous_groups); ++ bfqd->active_numerous_groups--; ++ } ++ } ++#endif ++} ++ ++/** ++ * bfq_idle_insert - insert an entity into the idle tree. ++ * @st: the service tree containing the tree. ++ * @entity: the entity to insert. ++ */ ++static void bfq_idle_insert(struct bfq_service_tree *st, ++ struct bfq_entity *entity) ++{ ++ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); ++ struct bfq_entity *first_idle = st->first_idle; ++ struct bfq_entity *last_idle = st->last_idle; ++ ++ if (first_idle == NULL || bfq_gt(first_idle->finish, entity->finish)) ++ st->first_idle = entity; ++ if (last_idle == NULL || bfq_gt(entity->finish, last_idle->finish)) ++ st->last_idle = entity; ++ ++ bfq_insert(&st->idle, entity); ++ ++ if (bfqq != NULL) ++ list_add(&bfqq->bfqq_list, &bfqq->bfqd->idle_list); ++} ++ ++/** ++ * bfq_forget_entity - remove an entity from the wfq trees. ++ * @st: the service tree. ++ * @entity: the entity being removed. ++ * ++ * Update the device status and forget everything about @entity, putting ++ * the device reference to it, if it is a queue. Entities belonging to ++ * groups are not refcounted. ++ */ ++static void bfq_forget_entity(struct bfq_service_tree *st, ++ struct bfq_entity *entity) ++{ ++ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); ++ struct bfq_sched_data *sd; ++ ++ BUG_ON(!entity->on_st); ++ ++ entity->on_st = 0; ++ st->wsum -= entity->weight; ++ if (bfqq != NULL) { ++ sd = entity->sched_data; ++ bfq_log_bfqq(bfqq->bfqd, bfqq, "forget_entity: %p %d", ++ bfqq, atomic_read(&bfqq->ref)); ++ bfq_put_queue(bfqq); ++ } ++} ++ ++/** ++ * bfq_put_idle_entity - release the idle tree ref of an entity. ++ * @st: service tree for the entity. ++ * @entity: the entity being released. ++ */ ++static void bfq_put_idle_entity(struct bfq_service_tree *st, ++ struct bfq_entity *entity) ++{ ++ bfq_idle_extract(st, entity); ++ bfq_forget_entity(st, entity); ++} ++ ++/** ++ * bfq_forget_idle - update the idle tree if necessary. ++ * @st: the service tree to act upon. ++ * ++ * To preserve the global O(log N) complexity we only remove one entry here; ++ * as the idle tree will not grow indefinitely this can be done safely. ++ */ ++static void bfq_forget_idle(struct bfq_service_tree *st) ++{ ++ struct bfq_entity *first_idle = st->first_idle; ++ struct bfq_entity *last_idle = st->last_idle; ++ ++ if (RB_EMPTY_ROOT(&st->active) && last_idle != NULL && ++ !bfq_gt(last_idle->finish, st->vtime)) { ++ /* ++ * Forget the whole idle tree, increasing the vtime past ++ * the last finish time of idle entities. ++ */ ++ st->vtime = last_idle->finish; ++ } ++ ++ if (first_idle != NULL && !bfq_gt(first_idle->finish, st->vtime)) ++ bfq_put_idle_entity(st, first_idle); ++} ++ ++static struct bfq_service_tree * ++__bfq_entity_update_weight_prio(struct bfq_service_tree *old_st, ++ struct bfq_entity *entity) ++{ ++ struct bfq_service_tree *new_st = old_st; ++ ++ if (entity->ioprio_changed) { ++ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); ++ unsigned short prev_weight, new_weight; ++ struct bfq_data *bfqd = NULL; ++ struct rb_root *root; ++#ifdef CONFIG_CGROUP_BFQIO ++ struct bfq_sched_data *sd; ++ struct bfq_group *bfqg; ++#endif ++ ++ if (bfqq != NULL) ++ bfqd = bfqq->bfqd; ++#ifdef CONFIG_CGROUP_BFQIO ++ else { ++ sd = entity->my_sched_data; ++ bfqg = container_of(sd, struct bfq_group, sched_data); ++ BUG_ON(!bfqg); ++ bfqd = (struct bfq_data *)bfqg->bfqd; ++ BUG_ON(!bfqd); ++ } ++#endif ++ ++ BUG_ON(old_st->wsum < entity->weight); ++ old_st->wsum -= entity->weight; ++ ++ if (entity->new_weight != entity->orig_weight) { ++ if (entity->new_weight < BFQ_MIN_WEIGHT || ++ entity->new_weight > BFQ_MAX_WEIGHT) { ++ printk(KERN_CRIT "update_weight_prio: " ++ "new_weight %d\n", ++ entity->new_weight); ++ BUG(); ++ } ++ entity->orig_weight = entity->new_weight; ++ entity->ioprio = ++ bfq_weight_to_ioprio(entity->orig_weight); ++ } else if (entity->new_ioprio != entity->ioprio) { ++ entity->ioprio = entity->new_ioprio; ++ entity->orig_weight = ++ bfq_ioprio_to_weight(entity->ioprio); ++ } else ++ entity->new_weight = entity->orig_weight = ++ bfq_ioprio_to_weight(entity->ioprio); ++ ++ entity->ioprio_class = entity->new_ioprio_class; ++ entity->ioprio_changed = 0; ++ ++ /* ++ * NOTE: here we may be changing the weight too early, ++ * this will cause unfairness. The correct approach ++ * would have required additional complexity to defer ++ * weight changes to the proper time instants (i.e., ++ * when entity->finish <= old_st->vtime). ++ */ ++ new_st = bfq_entity_service_tree(entity); ++ ++ prev_weight = entity->weight; ++ new_weight = entity->orig_weight * ++ (bfqq != NULL ? bfqq->wr_coeff : 1); ++ /* ++ * If the weight of the entity changes, remove the entity ++ * from its old weight counter (if there is a counter ++ * associated with the entity), and add it to the counter ++ * associated with its new weight. ++ */ ++ if (prev_weight != new_weight) { ++ root = bfqq ? &bfqd->queue_weights_tree : ++ &bfqd->group_weights_tree; ++ bfq_weights_tree_remove(bfqd, entity, root); ++ } ++ entity->weight = new_weight; ++ /* ++ * Add the entity to its weights tree only if it is ++ * not associated with a weight-raised queue. ++ */ ++ if (prev_weight != new_weight && ++ (bfqq ? bfqq->wr_coeff == 1 : 1)) ++ /* If we get here, root has been initialized. */ ++ bfq_weights_tree_add(bfqd, entity, root); ++ ++ new_st->wsum += entity->weight; ++ ++ if (new_st != old_st) ++ entity->start = new_st->vtime; ++ } ++ ++ return new_st; ++} ++ ++/** ++ * bfq_bfqq_served - update the scheduler status after selection for ++ * service. ++ * @bfqq: the queue being served. ++ * @served: bytes to transfer. ++ * ++ * NOTE: this can be optimized, as the timestamps of upper level entities ++ * are synchronized every time a new bfqq is selected for service. By now, ++ * we keep it to better check consistency. ++ */ ++static void bfq_bfqq_served(struct bfq_queue *bfqq, unsigned long served) ++{ ++ struct bfq_entity *entity = &bfqq->entity; ++ struct bfq_service_tree *st; ++ ++ for_each_entity(entity) { ++ st = bfq_entity_service_tree(entity); ++ ++ entity->service += served; ++ BUG_ON(entity->service > entity->budget); ++ BUG_ON(st->wsum == 0); ++ ++ st->vtime += bfq_delta(served, st->wsum); ++ bfq_forget_idle(st); ++ } ++ bfq_log_bfqq(bfqq->bfqd, bfqq, "bfqq_served %lu secs", served); ++} ++ ++/** ++ * bfq_bfqq_charge_full_budget - set the service to the entity budget. ++ * @bfqq: the queue that needs a service update. ++ * ++ * When it's not possible to be fair in the service domain, because ++ * a queue is not consuming its budget fast enough (the meaning of ++ * fast depends on the timeout parameter), we charge it a full ++ * budget. In this way we should obtain a sort of time-domain ++ * fairness among all the seeky/slow queues. ++ */ ++static inline void bfq_bfqq_charge_full_budget(struct bfq_queue *bfqq) ++{ ++ struct bfq_entity *entity = &bfqq->entity; ++ ++ bfq_log_bfqq(bfqq->bfqd, bfqq, "charge_full_budget"); ++ ++ bfq_bfqq_served(bfqq, entity->budget - entity->service); ++} ++ ++/** ++ * __bfq_activate_entity - activate an entity. ++ * @entity: the entity being activated. ++ * ++ * Called whenever an entity is activated, i.e., it is not active and one ++ * of its children receives a new request, or has to be reactivated due to ++ * budget exhaustion. It uses the current budget of the entity (and the ++ * service received if @entity is active) of the queue to calculate its ++ * timestamps. ++ */ ++static void __bfq_activate_entity(struct bfq_entity *entity) ++{ ++ struct bfq_sched_data *sd = entity->sched_data; ++ struct bfq_service_tree *st = bfq_entity_service_tree(entity); ++ ++ if (entity == sd->in_service_entity) { ++ BUG_ON(entity->tree != NULL); ++ /* ++ * If we are requeueing the current entity we have ++ * to take care of not charging to it service it has ++ * not received. ++ */ ++ bfq_calc_finish(entity, entity->service); ++ entity->start = entity->finish; ++ sd->in_service_entity = NULL; ++ } else if (entity->tree == &st->active) { ++ /* ++ * Requeueing an entity due to a change of some ++ * next_in_service entity below it. We reuse the ++ * old start time. ++ */ ++ bfq_active_extract(st, entity); ++ } else if (entity->tree == &st->idle) { ++ /* ++ * Must be on the idle tree, bfq_idle_extract() will ++ * check for that. ++ */ ++ bfq_idle_extract(st, entity); ++ entity->start = bfq_gt(st->vtime, entity->finish) ? ++ st->vtime : entity->finish; ++ } else { ++ /* ++ * The finish time of the entity may be invalid, and ++ * it is in the past for sure, otherwise the queue ++ * would have been on the idle tree. ++ */ ++ entity->start = st->vtime; ++ st->wsum += entity->weight; ++ bfq_get_entity(entity); ++ ++ BUG_ON(entity->on_st); ++ entity->on_st = 1; ++ } ++ ++ st = __bfq_entity_update_weight_prio(st, entity); ++ bfq_calc_finish(entity, entity->budget); ++ bfq_active_insert(st, entity); ++} ++ ++/** ++ * bfq_activate_entity - activate an entity and its ancestors if necessary. ++ * @entity: the entity to activate. ++ * ++ * Activate @entity and all the entities on the path from it to the root. ++ */ ++static void bfq_activate_entity(struct bfq_entity *entity) ++{ ++ struct bfq_sched_data *sd; ++ ++ for_each_entity(entity) { ++ __bfq_activate_entity(entity); ++ ++ sd = entity->sched_data; ++ if (!bfq_update_next_in_service(sd)) ++ /* ++ * No need to propagate the activation to the ++ * upper entities, as they will be updated when ++ * the in-service entity is rescheduled. ++ */ ++ break; ++ } ++} ++ ++/** ++ * __bfq_deactivate_entity - deactivate an entity from its service tree. ++ * @entity: the entity to deactivate. ++ * @requeue: if false, the entity will not be put into the idle tree. ++ * ++ * Deactivate an entity, independently from its previous state. If the ++ * entity was not on a service tree just return, otherwise if it is on ++ * any scheduler tree, extract it from that tree, and if necessary ++ * and if the caller did not specify @requeue, put it on the idle tree. ++ * ++ * Return %1 if the caller should update the entity hierarchy, i.e., ++ * if the entity was in service or if it was the next_in_service for ++ * its sched_data; return %0 otherwise. ++ */ ++static int __bfq_deactivate_entity(struct bfq_entity *entity, int requeue) ++{ ++ struct bfq_sched_data *sd = entity->sched_data; ++ struct bfq_service_tree *st = bfq_entity_service_tree(entity); ++ int was_in_service = entity == sd->in_service_entity; ++ int ret = 0; ++ ++ if (!entity->on_st) ++ return 0; ++ ++ BUG_ON(was_in_service && entity->tree != NULL); ++ ++ if (was_in_service) { ++ bfq_calc_finish(entity, entity->service); ++ sd->in_service_entity = NULL; ++ } else if (entity->tree == &st->active) ++ bfq_active_extract(st, entity); ++ else if (entity->tree == &st->idle) ++ bfq_idle_extract(st, entity); ++ else if (entity->tree != NULL) ++ BUG(); ++ ++ if (was_in_service || sd->next_in_service == entity) ++ ret = bfq_update_next_in_service(sd); ++ ++ if (!requeue || !bfq_gt(entity->finish, st->vtime)) ++ bfq_forget_entity(st, entity); ++ else ++ bfq_idle_insert(st, entity); ++ ++ BUG_ON(sd->in_service_entity == entity); ++ BUG_ON(sd->next_in_service == entity); ++ ++ return ret; ++} ++ ++/** ++ * bfq_deactivate_entity - deactivate an entity. ++ * @entity: the entity to deactivate. ++ * @requeue: true if the entity can be put on the idle tree ++ */ ++static void bfq_deactivate_entity(struct bfq_entity *entity, int requeue) ++{ ++ struct bfq_sched_data *sd; ++ struct bfq_entity *parent; ++ ++ for_each_entity_safe(entity, parent) { ++ sd = entity->sched_data; ++ ++ if (!__bfq_deactivate_entity(entity, requeue)) ++ /* ++ * The parent entity is still backlogged, and ++ * we don't need to update it as it is still ++ * in service. ++ */ ++ break; ++ ++ if (sd->next_in_service != NULL) ++ /* ++ * The parent entity is still backlogged and ++ * the budgets on the path towards the root ++ * need to be updated. ++ */ ++ goto update; ++ ++ /* ++ * If we reach there the parent is no more backlogged and ++ * we want to propagate the dequeue upwards. ++ */ ++ requeue = 1; ++ } ++ ++ return; ++ ++update: ++ entity = parent; ++ for_each_entity(entity) { ++ __bfq_activate_entity(entity); ++ ++ sd = entity->sched_data; ++ if (!bfq_update_next_in_service(sd)) ++ break; ++ } ++} ++ ++/** ++ * bfq_update_vtime - update vtime if necessary. ++ * @st: the service tree to act upon. ++ * ++ * If necessary update the service tree vtime to have at least one ++ * eligible entity, skipping to its start time. Assumes that the ++ * active tree of the device is not empty. ++ * ++ * NOTE: this hierarchical implementation updates vtimes quite often, ++ * we may end up with reactivated processes getting timestamps after a ++ * vtime skip done because we needed a ->first_active entity on some ++ * intermediate node. ++ */ ++static void bfq_update_vtime(struct bfq_service_tree *st) ++{ ++ struct bfq_entity *entry; ++ struct rb_node *node = st->active.rb_node; ++ ++ entry = rb_entry(node, struct bfq_entity, rb_node); ++ if (bfq_gt(entry->min_start, st->vtime)) { ++ st->vtime = entry->min_start; ++ bfq_forget_idle(st); ++ } ++} ++ ++/** ++ * bfq_first_active_entity - find the eligible entity with ++ * the smallest finish time ++ * @st: the service tree to select from. ++ * ++ * This function searches the first schedulable entity, starting from the ++ * root of the tree and going on the left every time on this side there is ++ * a subtree with at least one eligible (start >= vtime) entity. The path on ++ * the right is followed only if a) the left subtree contains no eligible ++ * entities and b) no eligible entity has been found yet. ++ */ ++static struct bfq_entity *bfq_first_active_entity(struct bfq_service_tree *st) ++{ ++ struct bfq_entity *entry, *first = NULL; ++ struct rb_node *node = st->active.rb_node; ++ ++ while (node != NULL) { ++ entry = rb_entry(node, struct bfq_entity, rb_node); ++left: ++ if (!bfq_gt(entry->start, st->vtime)) ++ first = entry; ++ ++ BUG_ON(bfq_gt(entry->min_start, st->vtime)); ++ ++ if (node->rb_left != NULL) { ++ entry = rb_entry(node->rb_left, ++ struct bfq_entity, rb_node); ++ if (!bfq_gt(entry->min_start, st->vtime)) { ++ node = node->rb_left; ++ goto left; ++ } ++ } ++ if (first != NULL) ++ break; ++ node = node->rb_right; ++ } ++ ++ BUG_ON(first == NULL && !RB_EMPTY_ROOT(&st->active)); ++ return first; ++} ++ ++/** ++ * __bfq_lookup_next_entity - return the first eligible entity in @st. ++ * @st: the service tree. ++ * ++ * Update the virtual time in @st and return the first eligible entity ++ * it contains. ++ */ ++static struct bfq_entity *__bfq_lookup_next_entity(struct bfq_service_tree *st, ++ bool force) ++{ ++ struct bfq_entity *entity, *new_next_in_service = NULL; ++ ++ if (RB_EMPTY_ROOT(&st->active)) ++ return NULL; ++ ++ bfq_update_vtime(st); ++ entity = bfq_first_active_entity(st); ++ BUG_ON(bfq_gt(entity->start, st->vtime)); ++ ++ /* ++ * If the chosen entity does not match with the sched_data's ++ * next_in_service and we are forcedly serving the IDLE priority ++ * class tree, bubble up budget update. ++ */ ++ if (unlikely(force && entity != entity->sched_data->next_in_service)) { ++ new_next_in_service = entity; ++ for_each_entity(new_next_in_service) ++ bfq_update_budget(new_next_in_service); ++ } ++ ++ return entity; ++} ++ ++/** ++ * bfq_lookup_next_entity - return the first eligible entity in @sd. ++ * @sd: the sched_data. ++ * @extract: if true the returned entity will be also extracted from @sd. ++ * ++ * NOTE: since we cache the next_in_service entity at each level of the ++ * hierarchy, the complexity of the lookup can be decreased with ++ * absolutely no effort just returning the cached next_in_service value; ++ * we prefer to do full lookups to test the consistency of * the data ++ * structures. ++ */ ++static struct bfq_entity *bfq_lookup_next_entity(struct bfq_sched_data *sd, ++ int extract, ++ struct bfq_data *bfqd) ++{ ++ struct bfq_service_tree *st = sd->service_tree; ++ struct bfq_entity *entity; ++ int i = 0; ++ ++ BUG_ON(sd->in_service_entity != NULL); ++ ++ if (bfqd != NULL && ++ jiffies - bfqd->bfq_class_idle_last_service > BFQ_CL_IDLE_TIMEOUT) { ++ entity = __bfq_lookup_next_entity(st + BFQ_IOPRIO_CLASSES - 1, ++ true); ++ if (entity != NULL) { ++ i = BFQ_IOPRIO_CLASSES - 1; ++ bfqd->bfq_class_idle_last_service = jiffies; ++ sd->next_in_service = entity; ++ } ++ } ++ for (; i < BFQ_IOPRIO_CLASSES; i++) { ++ entity = __bfq_lookup_next_entity(st + i, false); ++ if (entity != NULL) { ++ if (extract) { ++ bfq_check_next_in_service(sd, entity); ++ bfq_active_extract(st + i, entity); ++ sd->in_service_entity = entity; ++ sd->next_in_service = NULL; ++ } ++ break; ++ } ++ } ++ ++ return entity; ++} ++ ++/* ++ * Get next queue for service. ++ */ ++static struct bfq_queue *bfq_get_next_queue(struct bfq_data *bfqd) ++{ ++ struct bfq_entity *entity = NULL; ++ struct bfq_sched_data *sd; ++ struct bfq_queue *bfqq; ++ ++ BUG_ON(bfqd->in_service_queue != NULL); ++ ++ if (bfqd->busy_queues == 0) ++ return NULL; ++ ++ sd = &bfqd->root_group->sched_data; ++ for (; sd != NULL; sd = entity->my_sched_data) { ++ entity = bfq_lookup_next_entity(sd, 1, bfqd); ++ BUG_ON(entity == NULL); ++ entity->service = 0; ++ } ++ ++ bfqq = bfq_entity_to_bfqq(entity); ++ BUG_ON(bfqq == NULL); ++ ++ return bfqq; ++} ++ ++/* ++ * Forced extraction of the given queue. ++ */ ++static void bfq_get_next_queue_forced(struct bfq_data *bfqd, ++ struct bfq_queue *bfqq) ++{ ++ struct bfq_entity *entity; ++ struct bfq_sched_data *sd; ++ ++ BUG_ON(bfqd->in_service_queue != NULL); ++ ++ entity = &bfqq->entity; ++ /* ++ * Bubble up extraction/update from the leaf to the root. ++ */ ++ for_each_entity(entity) { ++ sd = entity->sched_data; ++ bfq_update_budget(entity); ++ bfq_update_vtime(bfq_entity_service_tree(entity)); ++ bfq_active_extract(bfq_entity_service_tree(entity), entity); ++ sd->in_service_entity = entity; ++ sd->next_in_service = NULL; ++ entity->service = 0; ++ } ++ ++ return; ++} ++ ++static void __bfq_bfqd_reset_in_service(struct bfq_data *bfqd) ++{ ++ if (bfqd->in_service_bic != NULL) { ++ put_io_context(bfqd->in_service_bic->icq.ioc); ++ bfqd->in_service_bic = NULL; ++ } ++ ++ bfqd->in_service_queue = NULL; ++ del_timer(&bfqd->idle_slice_timer); ++} ++ ++static void bfq_deactivate_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq, ++ int requeue) ++{ ++ struct bfq_entity *entity = &bfqq->entity; ++ ++ if (bfqq == bfqd->in_service_queue) ++ __bfq_bfqd_reset_in_service(bfqd); ++ ++ bfq_deactivate_entity(entity, requeue); ++} ++ ++static void bfq_activate_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq) ++{ ++ struct bfq_entity *entity = &bfqq->entity; ++ ++ bfq_activate_entity(entity); ++} ++ ++/* ++ * Called when the bfqq no longer has requests pending, remove it from ++ * the service tree. ++ */ ++static void bfq_del_bfqq_busy(struct bfq_data *bfqd, struct bfq_queue *bfqq, ++ int requeue) ++{ ++ BUG_ON(!bfq_bfqq_busy(bfqq)); ++ BUG_ON(!RB_EMPTY_ROOT(&bfqq->sort_list)); ++ ++ bfq_log_bfqq(bfqd, bfqq, "del from busy"); ++ ++ bfq_clear_bfqq_busy(bfqq); ++ ++ BUG_ON(bfqd->busy_queues == 0); ++ bfqd->busy_queues--; ++ ++ if (!bfqq->dispatched) { ++ bfq_weights_tree_remove(bfqd, &bfqq->entity, ++ &bfqd->queue_weights_tree); ++ if (!blk_queue_nonrot(bfqd->queue)) { ++ BUG_ON(!bfqd->busy_in_flight_queues); ++ bfqd->busy_in_flight_queues--; ++ if (bfq_bfqq_constantly_seeky(bfqq)) { ++ BUG_ON(!bfqd-> ++ const_seeky_busy_in_flight_queues); ++ bfqd->const_seeky_busy_in_flight_queues--; ++ } ++ } ++ } ++ if (bfqq->wr_coeff > 1) ++ bfqd->wr_busy_queues--; ++ ++ bfq_deactivate_bfqq(bfqd, bfqq, requeue); ++} ++ ++/* ++ * Called when an inactive queue receives a new request. ++ */ ++static void bfq_add_bfqq_busy(struct bfq_data *bfqd, struct bfq_queue *bfqq) ++{ ++ BUG_ON(bfq_bfqq_busy(bfqq)); ++ BUG_ON(bfqq == bfqd->in_service_queue); ++ ++ bfq_log_bfqq(bfqd, bfqq, "add to busy"); ++ ++ bfq_activate_bfqq(bfqd, bfqq); ++ ++ bfq_mark_bfqq_busy(bfqq); ++ bfqd->busy_queues++; ++ ++ if (!bfqq->dispatched) { ++ if (bfqq->wr_coeff == 1) ++ bfq_weights_tree_add(bfqd, &bfqq->entity, ++ &bfqd->queue_weights_tree); ++ if (!blk_queue_nonrot(bfqd->queue)) { ++ bfqd->busy_in_flight_queues++; ++ if (bfq_bfqq_constantly_seeky(bfqq)) ++ bfqd->const_seeky_busy_in_flight_queues++; ++ } ++ } ++ if (bfqq->wr_coeff > 1) ++ bfqd->wr_busy_queues++; ++} +diff --git a/block/bfq.h b/block/bfq.h +new file mode 100644 +index 0000000..3c5d85e +--- /dev/null ++++ b/block/bfq.h +@@ -0,0 +1,775 @@ ++/* ++ * BFQ-v7r7 for 3.19.0: data structures and common functions prototypes. ++ * ++ * Based on ideas and code from CFQ: ++ * Copyright (C) 2003 Jens Axboe ++ * ++ * Copyright (C) 2008 Fabio Checconi ++ * Paolo Valente ++ * ++ * Copyright (C) 2010 Paolo Valente ++ */ ++ ++#ifndef _BFQ_H ++#define _BFQ_H ++ ++#include ++#include ++#include ++#include ++ ++#define BFQ_IOPRIO_CLASSES 3 ++#define BFQ_CL_IDLE_TIMEOUT (HZ/5) ++ ++#define BFQ_MIN_WEIGHT 1 ++#define BFQ_MAX_WEIGHT 1000 ++ ++#define BFQ_DEFAULT_QUEUE_IOPRIO 4 ++ ++#define BFQ_DEFAULT_GRP_WEIGHT 10 ++#define BFQ_DEFAULT_GRP_IOPRIO 0 ++#define BFQ_DEFAULT_GRP_CLASS IOPRIO_CLASS_BE ++ ++struct bfq_entity; ++ ++/** ++ * struct bfq_service_tree - per ioprio_class service tree. ++ * @active: tree for active entities (i.e., those backlogged). ++ * @idle: tree for idle entities (i.e., those not backlogged, with V <= F_i). ++ * @first_idle: idle entity with minimum F_i. ++ * @last_idle: idle entity with maximum F_i. ++ * @vtime: scheduler virtual time. ++ * @wsum: scheduler weight sum; active and idle entities contribute to it. ++ * ++ * Each service tree represents a B-WF2Q+ scheduler on its own. Each ++ * ioprio_class has its own independent scheduler, and so its own ++ * bfq_service_tree. All the fields are protected by the queue lock ++ * of the containing bfqd. ++ */ ++struct bfq_service_tree { ++ struct rb_root active; ++ struct rb_root idle; ++ ++ struct bfq_entity *first_idle; ++ struct bfq_entity *last_idle; ++ ++ u64 vtime; ++ unsigned long wsum; ++}; ++ ++/** ++ * struct bfq_sched_data - multi-class scheduler. ++ * @in_service_entity: entity in service. ++ * @next_in_service: head-of-the-line entity in the scheduler. ++ * @service_tree: array of service trees, one per ioprio_class. ++ * ++ * bfq_sched_data is the basic scheduler queue. It supports three ++ * ioprio_classes, and can be used either as a toplevel queue or as ++ * an intermediate queue on a hierarchical setup. ++ * @next_in_service points to the active entity of the sched_data ++ * service trees that will be scheduled next. ++ * ++ * The supported ioprio_classes are the same as in CFQ, in descending ++ * priority order, IOPRIO_CLASS_RT, IOPRIO_CLASS_BE, IOPRIO_CLASS_IDLE. ++ * Requests from higher priority queues are served before all the ++ * requests from lower priority queues; among requests of the same ++ * queue requests are served according to B-WF2Q+. ++ * All the fields are protected by the queue lock of the containing bfqd. ++ */ ++struct bfq_sched_data { ++ struct bfq_entity *in_service_entity; ++ struct bfq_entity *next_in_service; ++ struct bfq_service_tree service_tree[BFQ_IOPRIO_CLASSES]; ++}; ++ ++/** ++ * struct bfq_weight_counter - counter of the number of all active entities ++ * with a given weight. ++ * @weight: weight of the entities that this counter refers to. ++ * @num_active: number of active entities with this weight. ++ * @weights_node: weights tree member (see bfq_data's @queue_weights_tree ++ * and @group_weights_tree). ++ */ ++struct bfq_weight_counter { ++ short int weight; ++ unsigned int num_active; ++ struct rb_node weights_node; ++}; ++ ++/** ++ * struct bfq_entity - schedulable entity. ++ * @rb_node: service_tree member. ++ * @weight_counter: pointer to the weight counter associated with this entity. ++ * @on_st: flag, true if the entity is on a tree (either the active or ++ * the idle one of its service_tree). ++ * @finish: B-WF2Q+ finish timestamp (aka F_i). ++ * @start: B-WF2Q+ start timestamp (aka S_i). ++ * @tree: tree the entity is enqueued into; %NULL if not on a tree. ++ * @min_start: minimum start time of the (active) subtree rooted at ++ * this entity; used for O(log N) lookups into active trees. ++ * @service: service received during the last round of service. ++ * @budget: budget used to calculate F_i; F_i = S_i + @budget / @weight. ++ * @weight: weight of the queue ++ * @parent: parent entity, for hierarchical scheduling. ++ * @my_sched_data: for non-leaf nodes in the cgroup hierarchy, the ++ * associated scheduler queue, %NULL on leaf nodes. ++ * @sched_data: the scheduler queue this entity belongs to. ++ * @ioprio: the ioprio in use. ++ * @new_weight: when a weight change is requested, the new weight value. ++ * @orig_weight: original weight, used to implement weight boosting ++ * @new_ioprio: when an ioprio change is requested, the new ioprio value. ++ * @ioprio_class: the ioprio_class in use. ++ * @new_ioprio_class: when an ioprio_class change is requested, the new ++ * ioprio_class value. ++ * @ioprio_changed: flag, true when the user requested a weight, ioprio or ++ * ioprio_class change. ++ * ++ * A bfq_entity is used to represent either a bfq_queue (leaf node in the ++ * cgroup hierarchy) or a bfq_group into the upper level scheduler. Each ++ * entity belongs to the sched_data of the parent group in the cgroup ++ * hierarchy. Non-leaf entities have also their own sched_data, stored ++ * in @my_sched_data. ++ * ++ * Each entity stores independently its priority values; this would ++ * allow different weights on different devices, but this ++ * functionality is not exported to userspace by now. Priorities and ++ * weights are updated lazily, first storing the new values into the ++ * new_* fields, then setting the @ioprio_changed flag. As soon as ++ * there is a transition in the entity state that allows the priority ++ * update to take place the effective and the requested priority ++ * values are synchronized. ++ * ++ * Unless cgroups are used, the weight value is calculated from the ++ * ioprio to export the same interface as CFQ. When dealing with ++ * ``well-behaved'' queues (i.e., queues that do not spend too much ++ * time to consume their budget and have true sequential behavior, and ++ * when there are no external factors breaking anticipation) the ++ * relative weights at each level of the cgroups hierarchy should be ++ * guaranteed. All the fields are protected by the queue lock of the ++ * containing bfqd. ++ */ ++struct bfq_entity { ++ struct rb_node rb_node; ++ struct bfq_weight_counter *weight_counter; ++ ++ int on_st; ++ ++ u64 finish; ++ u64 start; ++ ++ struct rb_root *tree; ++ ++ u64 min_start; ++ ++ unsigned long service, budget; ++ unsigned short weight, new_weight; ++ unsigned short orig_weight; ++ ++ struct bfq_entity *parent; ++ ++ struct bfq_sched_data *my_sched_data; ++ struct bfq_sched_data *sched_data; ++ ++ unsigned short ioprio, new_ioprio; ++ unsigned short ioprio_class, new_ioprio_class; ++ ++ int ioprio_changed; ++}; ++ ++struct bfq_group; ++ ++/** ++ * struct bfq_queue - leaf schedulable entity. ++ * @ref: reference counter. ++ * @bfqd: parent bfq_data. ++ * @new_bfqq: shared bfq_queue if queue is cooperating with ++ * one or more other queues. ++ * @pos_node: request-position tree member (see bfq_data's @rq_pos_tree). ++ * @pos_root: request-position tree root (see bfq_data's @rq_pos_tree). ++ * @sort_list: sorted list of pending requests. ++ * @next_rq: if fifo isn't expired, next request to serve. ++ * @queued: nr of requests queued in @sort_list. ++ * @allocated: currently allocated requests. ++ * @meta_pending: pending metadata requests. ++ * @fifo: fifo list of requests in sort_list. ++ * @entity: entity representing this queue in the scheduler. ++ * @max_budget: maximum budget allowed from the feedback mechanism. ++ * @budget_timeout: budget expiration (in jiffies). ++ * @dispatched: number of requests on the dispatch list or inside driver. ++ * @flags: status flags. ++ * @bfqq_list: node for active/idle bfqq list inside our bfqd. ++ * @burst_list_node: node for the device's burst list. ++ * @seek_samples: number of seeks sampled ++ * @seek_total: sum of the distances of the seeks sampled ++ * @seek_mean: mean seek distance ++ * @last_request_pos: position of the last request enqueued ++ * @requests_within_timer: number of consecutive pairs of request completion ++ * and arrival, such that the queue becomes idle ++ * after the completion, but the next request arrives ++ * within an idle time slice; used only if the queue's ++ * IO_bound has been cleared. ++ * @pid: pid of the process owning the queue, used for logging purposes. ++ * @last_wr_start_finish: start time of the current weight-raising period if ++ * the @bfq-queue is being weight-raised, otherwise ++ * finish time of the last weight-raising period ++ * @wr_cur_max_time: current max raising time for this queue ++ * @soft_rt_next_start: minimum time instant such that, only if a new ++ * request is enqueued after this time instant in an ++ * idle @bfq_queue with no outstanding requests, then ++ * the task associated with the queue it is deemed as ++ * soft real-time (see the comments to the function ++ * bfq_bfqq_softrt_next_start()). ++ * @last_idle_bklogged: time of the last transition of the @bfq_queue from ++ * idle to backlogged ++ * @service_from_backlogged: cumulative service received from the @bfq_queue ++ * since the last transition from idle to ++ * backlogged ++ * ++ * A bfq_queue is a leaf request queue; it can be associated with an io_context ++ * or more, if it is async or shared between cooperating processes. @cgroup ++ * holds a reference to the cgroup, to be sure that it does not disappear while ++ * a bfqq still references it (mostly to avoid races between request issuing and ++ * task migration followed by cgroup destruction). ++ * All the fields are protected by the queue lock of the containing bfqd. ++ */ ++struct bfq_queue { ++ atomic_t ref; ++ struct bfq_data *bfqd; ++ ++ /* fields for cooperating queues handling */ ++ struct bfq_queue *new_bfqq; ++ struct rb_node pos_node; ++ struct rb_root *pos_root; ++ ++ struct rb_root sort_list; ++ struct request *next_rq; ++ int queued[2]; ++ int allocated[2]; ++ int meta_pending; ++ struct list_head fifo; ++ ++ struct bfq_entity entity; ++ ++ unsigned long max_budget; ++ unsigned long budget_timeout; ++ ++ int dispatched; ++ ++ unsigned int flags; ++ ++ struct list_head bfqq_list; ++ ++ struct hlist_node burst_list_node; ++ ++ unsigned int seek_samples; ++ u64 seek_total; ++ sector_t seek_mean; ++ sector_t last_request_pos; ++ ++ unsigned int requests_within_timer; ++ ++ pid_t pid; ++ ++ /* weight-raising fields */ ++ unsigned long wr_cur_max_time; ++ unsigned long soft_rt_next_start; ++ unsigned long last_wr_start_finish; ++ unsigned int wr_coeff; ++ unsigned long last_idle_bklogged; ++ unsigned long service_from_backlogged; ++}; ++ ++/** ++ * struct bfq_ttime - per process thinktime stats. ++ * @ttime_total: total process thinktime ++ * @ttime_samples: number of thinktime samples ++ * @ttime_mean: average process thinktime ++ */ ++struct bfq_ttime { ++ unsigned long last_end_request; ++ ++ unsigned long ttime_total; ++ unsigned long ttime_samples; ++ unsigned long ttime_mean; ++}; ++ ++/** ++ * struct bfq_io_cq - per (request_queue, io_context) structure. ++ * @icq: associated io_cq structure ++ * @bfqq: array of two process queues, the sync and the async ++ * @ttime: associated @bfq_ttime struct ++ */ ++struct bfq_io_cq { ++ struct io_cq icq; /* must be the first member */ ++ struct bfq_queue *bfqq[2]; ++ struct bfq_ttime ttime; ++ int ioprio; ++}; ++ ++enum bfq_device_speed { ++ BFQ_BFQD_FAST, ++ BFQ_BFQD_SLOW, ++}; ++ ++/** ++ * struct bfq_data - per device data structure. ++ * @queue: request queue for the managed device. ++ * @root_group: root bfq_group for the device. ++ * @rq_pos_tree: rbtree sorted by next_request position, used when ++ * determining if two or more queues have interleaving ++ * requests (see bfq_close_cooperator()). ++ * @active_numerous_groups: number of bfq_groups containing more than one ++ * active @bfq_entity. ++ * @queue_weights_tree: rbtree of weight counters of @bfq_queues, sorted by ++ * weight. Used to keep track of whether all @bfq_queues ++ * have the same weight. The tree contains one counter ++ * for each distinct weight associated to some active ++ * and not weight-raised @bfq_queue (see the comments to ++ * the functions bfq_weights_tree_[add|remove] for ++ * further details). ++ * @group_weights_tree: rbtree of non-queue @bfq_entity weight counters, sorted ++ * by weight. Used to keep track of whether all ++ * @bfq_groups have the same weight. The tree contains ++ * one counter for each distinct weight associated to ++ * some active @bfq_group (see the comments to the ++ * functions bfq_weights_tree_[add|remove] for further ++ * details). ++ * @busy_queues: number of bfq_queues containing requests (including the ++ * queue in service, even if it is idling). ++ * @busy_in_flight_queues: number of @bfq_queues containing pending or ++ * in-flight requests, plus the @bfq_queue in ++ * service, even if idle but waiting for the ++ * possible arrival of its next sync request. This ++ * field is updated only if the device is rotational, ++ * but used only if the device is also NCQ-capable. ++ * The reason why the field is updated also for non- ++ * NCQ-capable rotational devices is related to the ++ * fact that the value of @hw_tag may be set also ++ * later than when busy_in_flight_queues may need to ++ * be incremented for the first time(s). Taking also ++ * this possibility into account, to avoid unbalanced ++ * increments/decrements, would imply more overhead ++ * than just updating busy_in_flight_queues ++ * regardless of the value of @hw_tag. ++ * @const_seeky_busy_in_flight_queues: number of constantly-seeky @bfq_queues ++ * (that is, seeky queues that expired ++ * for budget timeout at least once) ++ * containing pending or in-flight ++ * requests, including the in-service ++ * @bfq_queue if constantly seeky. This ++ * field is updated only if the device ++ * is rotational, but used only if the ++ * device is also NCQ-capable (see the ++ * comments to @busy_in_flight_queues). ++ * @wr_busy_queues: number of weight-raised busy @bfq_queues. ++ * @queued: number of queued requests. ++ * @rq_in_driver: number of requests dispatched and waiting for completion. ++ * @sync_flight: number of sync requests in the driver. ++ * @max_rq_in_driver: max number of reqs in driver in the last ++ * @hw_tag_samples completed requests. ++ * @hw_tag_samples: nr of samples used to calculate hw_tag. ++ * @hw_tag: flag set to one if the driver is showing a queueing behavior. ++ * @budgets_assigned: number of budgets assigned. ++ * @idle_slice_timer: timer set when idling for the next sequential request ++ * from the queue in service. ++ * @unplug_work: delayed work to restart dispatching on the request queue. ++ * @in_service_queue: bfq_queue in service. ++ * @in_service_bic: bfq_io_cq (bic) associated with the @in_service_queue. ++ * @last_position: on-disk position of the last served request. ++ * @last_budget_start: beginning of the last budget. ++ * @last_idling_start: beginning of the last idle slice. ++ * @peak_rate: peak transfer rate observed for a budget. ++ * @peak_rate_samples: number of samples used to calculate @peak_rate. ++ * @bfq_max_budget: maximum budget allotted to a bfq_queue before ++ * rescheduling. ++ * @group_list: list of all the bfq_groups active on the device. ++ * @active_list: list of all the bfq_queues active on the device. ++ * @idle_list: list of all the bfq_queues idle on the device. ++ * @bfq_quantum: max number of requests dispatched per dispatch round. ++ * @bfq_fifo_expire: timeout for async/sync requests; when it expires ++ * requests are served in fifo order. ++ * @bfq_back_penalty: weight of backward seeks wrt forward ones. ++ * @bfq_back_max: maximum allowed backward seek. ++ * @bfq_slice_idle: maximum idling time. ++ * @bfq_user_max_budget: user-configured max budget value ++ * (0 for auto-tuning). ++ * @bfq_max_budget_async_rq: maximum budget (in nr of requests) allotted to ++ * async queues. ++ * @bfq_timeout: timeout for bfq_queues to consume their budget; used to ++ * to prevent seeky queues to impose long latencies to well ++ * behaved ones (this also implies that seeky queues cannot ++ * receive guarantees in the service domain; after a timeout ++ * they are charged for the whole allocated budget, to try ++ * to preserve a behavior reasonably fair among them, but ++ * without service-domain guarantees). ++ * @bfq_coop_thresh: number of queue merges after which a @bfq_queue is ++ * no more granted any weight-raising. ++ * @bfq_failed_cooperations: number of consecutive failed cooperation ++ * chances after which weight-raising is restored ++ * to a queue subject to more than bfq_coop_thresh ++ * queue merges. ++ * @bfq_requests_within_timer: number of consecutive requests that must be ++ * issued within the idle time slice to set ++ * again idling to a queue which was marked as ++ * non-I/O-bound (see the definition of the ++ * IO_bound flag for further details). ++ * @last_ins_in_burst: last time at which a queue entered the current ++ * burst of queues being activated shortly after ++ * each other; for more details about this and the ++ * following parameters related to a burst of ++ * activations, see the comments to the function ++ * @bfq_handle_burst. ++ * @bfq_burst_interval: reference time interval used to decide whether a ++ * queue has been activated shortly after ++ * @last_ins_in_burst. ++ * @burst_size: number of queues in the current burst of queue activations. ++ * @bfq_large_burst_thresh: maximum burst size above which the current ++ * queue-activation burst is deemed as 'large'. ++ * @large_burst: true if a large queue-activation burst is in progress. ++ * @burst_list: head of the burst list (as for the above fields, more details ++ * in the comments to the function bfq_handle_burst). ++ * @low_latency: if set to true, low-latency heuristics are enabled. ++ * @bfq_wr_coeff: maximum factor by which the weight of a weight-raised ++ * queue is multiplied. ++ * @bfq_wr_max_time: maximum duration of a weight-raising period (jiffies). ++ * @bfq_wr_rt_max_time: maximum duration for soft real-time processes. ++ * @bfq_wr_min_idle_time: minimum idle period after which weight-raising ++ * may be reactivated for a queue (in jiffies). ++ * @bfq_wr_min_inter_arr_async: minimum period between request arrivals ++ * after which weight-raising may be ++ * reactivated for an already busy queue ++ * (in jiffies). ++ * @bfq_wr_max_softrt_rate: max service-rate for a soft real-time queue, ++ * sectors per seconds. ++ * @RT_prod: cached value of the product R*T used for computing the maximum ++ * duration of the weight raising automatically. ++ * @device_speed: device-speed class for the low-latency heuristic. ++ * @oom_bfqq: fallback dummy bfqq for extreme OOM conditions. ++ * ++ * All the fields are protected by the @queue lock. ++ */ ++struct bfq_data { ++ struct request_queue *queue; ++ ++ struct bfq_group *root_group; ++ struct rb_root rq_pos_tree; ++ ++#ifdef CONFIG_CGROUP_BFQIO ++ int active_numerous_groups; ++#endif ++ ++ struct rb_root queue_weights_tree; ++ struct rb_root group_weights_tree; ++ ++ int busy_queues; ++ int busy_in_flight_queues; ++ int const_seeky_busy_in_flight_queues; ++ int wr_busy_queues; ++ int queued; ++ int rq_in_driver; ++ int sync_flight; ++ ++ int max_rq_in_driver; ++ int hw_tag_samples; ++ int hw_tag; ++ ++ int budgets_assigned; ++ ++ struct timer_list idle_slice_timer; ++ struct work_struct unplug_work; ++ ++ struct bfq_queue *in_service_queue; ++ struct bfq_io_cq *in_service_bic; ++ ++ sector_t last_position; ++ ++ ktime_t last_budget_start; ++ ktime_t last_idling_start; ++ int peak_rate_samples; ++ u64 peak_rate; ++ unsigned long bfq_max_budget; ++ ++ struct hlist_head group_list; ++ struct list_head active_list; ++ struct list_head idle_list; ++ ++ unsigned int bfq_quantum; ++ unsigned int bfq_fifo_expire[2]; ++ unsigned int bfq_back_penalty; ++ unsigned int bfq_back_max; ++ unsigned int bfq_slice_idle; ++ u64 bfq_class_idle_last_service; ++ ++ unsigned int bfq_user_max_budget; ++ unsigned int bfq_max_budget_async_rq; ++ unsigned int bfq_timeout[2]; ++ ++ unsigned int bfq_coop_thresh; ++ unsigned int bfq_failed_cooperations; ++ unsigned int bfq_requests_within_timer; ++ ++ unsigned long last_ins_in_burst; ++ unsigned long bfq_burst_interval; ++ int burst_size; ++ unsigned long bfq_large_burst_thresh; ++ bool large_burst; ++ struct hlist_head burst_list; ++ ++ bool low_latency; ++ ++ /* parameters of the low_latency heuristics */ ++ unsigned int bfq_wr_coeff; ++ unsigned int bfq_wr_max_time; ++ unsigned int bfq_wr_rt_max_time; ++ unsigned int bfq_wr_min_idle_time; ++ unsigned long bfq_wr_min_inter_arr_async; ++ unsigned int bfq_wr_max_softrt_rate; ++ u64 RT_prod; ++ enum bfq_device_speed device_speed; ++ ++ struct bfq_queue oom_bfqq; ++}; ++ ++enum bfqq_state_flags { ++ BFQ_BFQQ_FLAG_busy = 0, /* has requests or is in service */ ++ BFQ_BFQQ_FLAG_wait_request, /* waiting for a request */ ++ BFQ_BFQQ_FLAG_must_alloc, /* must be allowed rq alloc */ ++ BFQ_BFQQ_FLAG_fifo_expire, /* FIFO checked in this slice */ ++ BFQ_BFQQ_FLAG_idle_window, /* slice idling enabled */ ++ BFQ_BFQQ_FLAG_prio_changed, /* task priority has changed */ ++ BFQ_BFQQ_FLAG_sync, /* synchronous queue */ ++ BFQ_BFQQ_FLAG_budget_new, /* no completion with this budget */ ++ BFQ_BFQQ_FLAG_IO_bound, /* ++ * bfqq has timed-out at least once ++ * having consumed at most 2/10 of ++ * its budget ++ */ ++ BFQ_BFQQ_FLAG_in_large_burst, /* ++ * bfqq activated in a large burst, ++ * see comments to bfq_handle_burst. ++ */ ++ BFQ_BFQQ_FLAG_constantly_seeky, /* ++ * bfqq has proved to be slow and ++ * seeky until budget timeout ++ */ ++ BFQ_BFQQ_FLAG_softrt_update, /* ++ * may need softrt-next-start ++ * update ++ */ ++ BFQ_BFQQ_FLAG_coop, /* bfqq is shared */ ++ BFQ_BFQQ_FLAG_split_coop, /* shared bfqq will be splitted */ ++}; ++ ++#define BFQ_BFQQ_FNS(name) \ ++static inline void bfq_mark_bfqq_##name(struct bfq_queue *bfqq) \ ++{ \ ++ (bfqq)->flags |= (1 << BFQ_BFQQ_FLAG_##name); \ ++} \ ++static inline void bfq_clear_bfqq_##name(struct bfq_queue *bfqq) \ ++{ \ ++ (bfqq)->flags &= ~(1 << BFQ_BFQQ_FLAG_##name); \ ++} \ ++static inline int bfq_bfqq_##name(const struct bfq_queue *bfqq) \ ++{ \ ++ return ((bfqq)->flags & (1 << BFQ_BFQQ_FLAG_##name)) != 0; \ ++} ++ ++BFQ_BFQQ_FNS(busy); ++BFQ_BFQQ_FNS(wait_request); ++BFQ_BFQQ_FNS(must_alloc); ++BFQ_BFQQ_FNS(fifo_expire); ++BFQ_BFQQ_FNS(idle_window); ++BFQ_BFQQ_FNS(prio_changed); ++BFQ_BFQQ_FNS(sync); ++BFQ_BFQQ_FNS(budget_new); ++BFQ_BFQQ_FNS(IO_bound); ++BFQ_BFQQ_FNS(in_large_burst); ++BFQ_BFQQ_FNS(constantly_seeky); ++BFQ_BFQQ_FNS(coop); ++BFQ_BFQQ_FNS(split_coop); ++BFQ_BFQQ_FNS(softrt_update); ++#undef BFQ_BFQQ_FNS ++ ++/* Logging facilities. */ ++#define bfq_log_bfqq(bfqd, bfqq, fmt, args...) \ ++ blk_add_trace_msg((bfqd)->queue, "bfq%d " fmt, (bfqq)->pid, ##args) ++ ++#define bfq_log(bfqd, fmt, args...) \ ++ blk_add_trace_msg((bfqd)->queue, "bfq " fmt, ##args) ++ ++/* Expiration reasons. */ ++enum bfqq_expiration { ++ BFQ_BFQQ_TOO_IDLE = 0, /* ++ * queue has been idling for ++ * too long ++ */ ++ BFQ_BFQQ_BUDGET_TIMEOUT, /* budget took too long to be used */ ++ BFQ_BFQQ_BUDGET_EXHAUSTED, /* budget consumed */ ++ BFQ_BFQQ_NO_MORE_REQUESTS, /* the queue has no more requests */ ++}; ++ ++#ifdef CONFIG_CGROUP_BFQIO ++/** ++ * struct bfq_group - per (device, cgroup) data structure. ++ * @entity: schedulable entity to insert into the parent group sched_data. ++ * @sched_data: own sched_data, to contain child entities (they may be ++ * both bfq_queues and bfq_groups). ++ * @group_node: node to be inserted into the bfqio_cgroup->group_data ++ * list of the containing cgroup's bfqio_cgroup. ++ * @bfqd_node: node to be inserted into the @bfqd->group_list list ++ * of the groups active on the same device; used for cleanup. ++ * @bfqd: the bfq_data for the device this group acts upon. ++ * @async_bfqq: array of async queues for all the tasks belonging to ++ * the group, one queue per ioprio value per ioprio_class, ++ * except for the idle class that has only one queue. ++ * @async_idle_bfqq: async queue for the idle class (ioprio is ignored). ++ * @my_entity: pointer to @entity, %NULL for the toplevel group; used ++ * to avoid too many special cases during group creation/ ++ * migration. ++ * @active_entities: number of active entities belonging to the group; ++ * unused for the root group. Used to know whether there ++ * are groups with more than one active @bfq_entity ++ * (see the comments to the function ++ * bfq_bfqq_must_not_expire()). ++ * ++ * Each (device, cgroup) pair has its own bfq_group, i.e., for each cgroup ++ * there is a set of bfq_groups, each one collecting the lower-level ++ * entities belonging to the group that are acting on the same device. ++ * ++ * Locking works as follows: ++ * o @group_node is protected by the bfqio_cgroup lock, and is accessed ++ * via RCU from its readers. ++ * o @bfqd is protected by the queue lock, RCU is used to access it ++ * from the readers. ++ * o All the other fields are protected by the @bfqd queue lock. ++ */ ++struct bfq_group { ++ struct bfq_entity entity; ++ struct bfq_sched_data sched_data; ++ ++ struct hlist_node group_node; ++ struct hlist_node bfqd_node; ++ ++ void *bfqd; ++ ++ struct bfq_queue *async_bfqq[2][IOPRIO_BE_NR]; ++ struct bfq_queue *async_idle_bfqq; ++ ++ struct bfq_entity *my_entity; ++ ++ int active_entities; ++}; ++ ++/** ++ * struct bfqio_cgroup - bfq cgroup data structure. ++ * @css: subsystem state for bfq in the containing cgroup. ++ * @online: flag marked when the subsystem is inserted. ++ * @weight: cgroup weight. ++ * @ioprio: cgroup ioprio. ++ * @ioprio_class: cgroup ioprio_class. ++ * @lock: spinlock that protects @ioprio, @ioprio_class and @group_data. ++ * @group_data: list containing the bfq_group belonging to this cgroup. ++ * ++ * @group_data is accessed using RCU, with @lock protecting the updates, ++ * @ioprio and @ioprio_class are protected by @lock. ++ */ ++struct bfqio_cgroup { ++ struct cgroup_subsys_state css; ++ bool online; ++ ++ unsigned short weight, ioprio, ioprio_class; ++ ++ spinlock_t lock; ++ struct hlist_head group_data; ++}; ++#else ++struct bfq_group { ++ struct bfq_sched_data sched_data; ++ ++ struct bfq_queue *async_bfqq[2][IOPRIO_BE_NR]; ++ struct bfq_queue *async_idle_bfqq; ++}; ++#endif ++ ++static inline struct bfq_service_tree * ++bfq_entity_service_tree(struct bfq_entity *entity) ++{ ++ struct bfq_sched_data *sched_data = entity->sched_data; ++ unsigned int idx = entity->ioprio_class - 1; ++ ++ BUG_ON(idx >= BFQ_IOPRIO_CLASSES); ++ BUG_ON(sched_data == NULL); ++ ++ return sched_data->service_tree + idx; ++} ++ ++static inline struct bfq_queue *bic_to_bfqq(struct bfq_io_cq *bic, ++ bool is_sync) ++{ ++ return bic->bfqq[is_sync]; ++} ++ ++static inline void bic_set_bfqq(struct bfq_io_cq *bic, ++ struct bfq_queue *bfqq, bool is_sync) ++{ ++ bic->bfqq[is_sync] = bfqq; ++} ++ ++static inline struct bfq_data *bic_to_bfqd(struct bfq_io_cq *bic) ++{ ++ return bic->icq.q->elevator->elevator_data; ++} ++ ++/** ++ * bfq_get_bfqd_locked - get a lock to a bfqd using a RCU protected pointer. ++ * @ptr: a pointer to a bfqd. ++ * @flags: storage for the flags to be saved. ++ * ++ * This function allows bfqg->bfqd to be protected by the ++ * queue lock of the bfqd they reference; the pointer is dereferenced ++ * under RCU, so the storage for bfqd is assured to be safe as long ++ * as the RCU read side critical section does not end. After the ++ * bfqd->queue->queue_lock is taken the pointer is rechecked, to be ++ * sure that no other writer accessed it. If we raced with a writer, ++ * the function returns NULL, with the queue unlocked, otherwise it ++ * returns the dereferenced pointer, with the queue locked. ++ */ ++static inline struct bfq_data *bfq_get_bfqd_locked(void **ptr, ++ unsigned long *flags) ++{ ++ struct bfq_data *bfqd; ++ ++ rcu_read_lock(); ++ bfqd = rcu_dereference(*(struct bfq_data **)ptr); ++ ++ if (bfqd != NULL) { ++ spin_lock_irqsave(bfqd->queue->queue_lock, *flags); ++ if (*ptr == bfqd) ++ goto out; ++ spin_unlock_irqrestore(bfqd->queue->queue_lock, *flags); ++ } ++ ++ bfqd = NULL; ++out: ++ rcu_read_unlock(); ++ return bfqd; ++} ++ ++static inline void bfq_put_bfqd_unlock(struct bfq_data *bfqd, ++ unsigned long *flags) ++{ ++ spin_unlock_irqrestore(bfqd->queue->queue_lock, *flags); ++} ++ ++static void bfq_changed_ioprio(struct bfq_io_cq *bic); ++static void bfq_put_queue(struct bfq_queue *bfqq); ++static void bfq_dispatch_insert(struct request_queue *q, struct request *rq); ++static struct bfq_queue *bfq_get_queue(struct bfq_data *bfqd, ++ struct bfq_group *bfqg, int is_sync, ++ struct bfq_io_cq *bic, gfp_t gfp_mask); ++static void bfq_end_wr_async_queues(struct bfq_data *bfqd, ++ struct bfq_group *bfqg); ++static void bfq_put_async_queues(struct bfq_data *bfqd, struct bfq_group *bfqg); ++static void bfq_exit_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq); ++ ++#endif /* _BFQ_H */ +-- +2.3.0 + diff --git a/kernel/tools/cpupowertools/files/patches/gentoo/5003_block-bfq-add-Early-Queue-Merge-EQM-to-BFQ-v7r7-for-3.19.0.patch b/kernel/tools/cpupowertools/files/patches/gentoo/5003_block-bfq-add-Early-Queue-Merge-EQM-to-BFQ-v7r7-for-3.19.0.patch new file mode 100644 index 00000000..b2e83e40 --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/gentoo/5003_block-bfq-add-Early-Queue-Merge-EQM-to-BFQ-v7r7-for-3.19.0.patch @@ -0,0 +1,1222 @@ +From 8308a96c0ba080015eb1c58a1bfbfbf1fee80fd6 Mon Sep 17 00:00:00 2001 +From: Mauro Andreolini +Date: Thu, 18 Dec 2014 21:32:08 +0100 +Subject: [PATCH 3/3] block, bfq: add Early Queue Merge (EQM) to BFQ-v7r7 for + 3.19.0 + +A set of processes may happen to perform interleaved reads, i.e.,requests +whose union would give rise to a sequential read pattern. There are two +typical cases: in the first case, processes read fixed-size chunks of +data at a fixed distance from each other, while in the second case processes +may read variable-size chunks at variable distances. The latter case occurs +for example with QEMU, which splits the I/O generated by the guest into +multiple chunks, and lets these chunks be served by a pool of cooperating +processes, iteratively assigning the next chunk of I/O to the first +available process. CFQ uses actual queue merging for the first type of +rocesses, whereas it uses preemption to get a sequential read pattern out +of the read requests performed by the second type of processes. In the end +it uses two different mechanisms to achieve the same goal: boosting the +throughput with interleaved I/O. + +This patch introduces Early Queue Merge (EQM), a unified mechanism to get a +sequential read pattern with both types of processes. The main idea is +checking newly arrived requests against the next request of the active queue +both in case of actual request insert and in case of request merge. By doing +so, both the types of processes can be handled by just merging their queues. +EQM is then simpler and more compact than the pair of mechanisms used in +CFQ. + +Finally, EQM also preserves the typical low-latency properties of BFQ, by +properly restoring the weight-raising state of a queue when it gets back to +a non-merged state. + +Signed-off-by: Mauro Andreolini +Signed-off-by: Arianna Avanzini +Signed-off-by: Paolo Valente +--- + block/bfq-iosched.c | 751 +++++++++++++++++++++++++++++++++++++--------------- + block/bfq-sched.c | 28 -- + block/bfq.h | 54 +++- + 3 files changed, 581 insertions(+), 252 deletions(-) + +diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c +index 97ee934..328f33c 100644 +--- a/block/bfq-iosched.c ++++ b/block/bfq-iosched.c +@@ -571,6 +571,57 @@ static inline unsigned int bfq_wr_duration(struct bfq_data *bfqd) + return dur; + } + ++static inline unsigned ++bfq_bfqq_cooperations(struct bfq_queue *bfqq) ++{ ++ return bfqq->bic ? bfqq->bic->cooperations : 0; ++} ++ ++static inline void ++bfq_bfqq_resume_state(struct bfq_queue *bfqq, struct bfq_io_cq *bic) ++{ ++ if (bic->saved_idle_window) ++ bfq_mark_bfqq_idle_window(bfqq); ++ else ++ bfq_clear_bfqq_idle_window(bfqq); ++ if (bic->saved_IO_bound) ++ bfq_mark_bfqq_IO_bound(bfqq); ++ else ++ bfq_clear_bfqq_IO_bound(bfqq); ++ /* Assuming that the flag in_large_burst is already correctly set */ ++ if (bic->wr_time_left && bfqq->bfqd->low_latency && ++ !bfq_bfqq_in_large_burst(bfqq) && ++ bic->cooperations < bfqq->bfqd->bfq_coop_thresh) { ++ /* ++ * Start a weight raising period with the duration given by ++ * the raising_time_left snapshot. ++ */ ++ if (bfq_bfqq_busy(bfqq)) ++ bfqq->bfqd->wr_busy_queues++; ++ bfqq->wr_coeff = bfqq->bfqd->bfq_wr_coeff; ++ bfqq->wr_cur_max_time = bic->wr_time_left; ++ bfqq->last_wr_start_finish = jiffies; ++ bfqq->entity.ioprio_changed = 1; ++ } ++ /* ++ * Clear wr_time_left to prevent bfq_bfqq_save_state() from ++ * getting confused about the queue's need of a weight-raising ++ * period. ++ */ ++ bic->wr_time_left = 0; ++} ++ ++/* Must be called with the queue_lock held. */ ++static int bfqq_process_refs(struct bfq_queue *bfqq) ++{ ++ int process_refs, io_refs; ++ ++ io_refs = bfqq->allocated[READ] + bfqq->allocated[WRITE]; ++ process_refs = atomic_read(&bfqq->ref) - io_refs - bfqq->entity.on_st; ++ BUG_ON(process_refs < 0); ++ return process_refs; ++} ++ + /* Empty burst list and add just bfqq (see comments to bfq_handle_burst) */ + static inline void bfq_reset_burst_list(struct bfq_data *bfqd, + struct bfq_queue *bfqq) +@@ -815,7 +866,7 @@ static void bfq_add_request(struct request *rq) + bfq_rq_pos_tree_add(bfqd, bfqq); + + if (!bfq_bfqq_busy(bfqq)) { +- bool soft_rt, ++ bool soft_rt, coop_or_in_burst, + idle_for_long_time = time_is_before_jiffies( + bfqq->budget_timeout + + bfqd->bfq_wr_min_idle_time); +@@ -839,11 +890,12 @@ static void bfq_add_request(struct request *rq) + bfqd->last_ins_in_burst = jiffies; + } + ++ coop_or_in_burst = bfq_bfqq_in_large_burst(bfqq) || ++ bfq_bfqq_cooperations(bfqq) >= bfqd->bfq_coop_thresh; + soft_rt = bfqd->bfq_wr_max_softrt_rate > 0 && +- !bfq_bfqq_in_large_burst(bfqq) && ++ !coop_or_in_burst && + time_is_before_jiffies(bfqq->soft_rt_next_start); +- interactive = !bfq_bfqq_in_large_burst(bfqq) && +- idle_for_long_time; ++ interactive = !coop_or_in_burst && idle_for_long_time; + entity->budget = max_t(unsigned long, bfqq->max_budget, + bfq_serv_to_charge(next_rq, bfqq)); + +@@ -862,11 +914,20 @@ static void bfq_add_request(struct request *rq) + if (!bfqd->low_latency) + goto add_bfqq_busy; + ++ if (bfq_bfqq_just_split(bfqq)) ++ goto set_ioprio_changed; ++ + /* +- * If the queue is not being boosted and has been idle +- * for enough time, start a weight-raising period ++ * If the queue: ++ * - is not being boosted, ++ * - has been idle for enough time, ++ * - is not a sync queue or is linked to a bfq_io_cq (it is ++ * shared "for its nature" or it is not shared and its ++ * requests have not been redirected to a shared queue) ++ * start a weight-raising period. + */ +- if (old_wr_coeff == 1 && (interactive || soft_rt)) { ++ if (old_wr_coeff == 1 && (interactive || soft_rt) && ++ (!bfq_bfqq_sync(bfqq) || bfqq->bic != NULL)) { + bfqq->wr_coeff = bfqd->bfq_wr_coeff; + if (interactive) + bfqq->wr_cur_max_time = bfq_wr_duration(bfqd); +@@ -880,7 +941,7 @@ static void bfq_add_request(struct request *rq) + } else if (old_wr_coeff > 1) { + if (interactive) + bfqq->wr_cur_max_time = bfq_wr_duration(bfqd); +- else if (bfq_bfqq_in_large_burst(bfqq) || ++ else if (coop_or_in_burst || + (bfqq->wr_cur_max_time == + bfqd->bfq_wr_rt_max_time && + !soft_rt)) { +@@ -899,18 +960,18 @@ static void bfq_add_request(struct request *rq) + /* + * + * The remaining weight-raising time is lower +- * than bfqd->bfq_wr_rt_max_time, which +- * means that the application is enjoying +- * weight raising either because deemed soft- +- * rt in the near past, or because deemed +- * interactive a long ago. In both cases, +- * resetting now the current remaining weight- +- * raising time for the application to the +- * weight-raising duration for soft rt +- * applications would not cause any latency +- * increase for the application (as the new +- * duration would be higher than the remaining +- * time). ++ * than bfqd->bfq_wr_rt_max_time, which means ++ * that the application is enjoying weight ++ * raising either because deemed soft-rt in ++ * the near past, or because deemed interactive ++ * a long ago. ++ * In both cases, resetting now the current ++ * remaining weight-raising time for the ++ * application to the weight-raising duration ++ * for soft rt applications would not cause any ++ * latency increase for the application (as the ++ * new duration would be higher than the ++ * remaining time). + * + * In addition, the application is now meeting + * the requirements for being deemed soft rt. +@@ -945,6 +1006,7 @@ static void bfq_add_request(struct request *rq) + bfqd->bfq_wr_rt_max_time; + } + } ++set_ioprio_changed: + if (old_wr_coeff != bfqq->wr_coeff) + entity->ioprio_changed = 1; + add_bfqq_busy: +@@ -1156,90 +1218,35 @@ static void bfq_end_wr(struct bfq_data *bfqd) + spin_unlock_irq(bfqd->queue->queue_lock); + } + +-static int bfq_allow_merge(struct request_queue *q, struct request *rq, +- struct bio *bio) ++static inline sector_t bfq_io_struct_pos(void *io_struct, bool request) + { +- struct bfq_data *bfqd = q->elevator->elevator_data; +- struct bfq_io_cq *bic; +- struct bfq_queue *bfqq; +- +- /* +- * Disallow merge of a sync bio into an async request. +- */ +- if (bfq_bio_sync(bio) && !rq_is_sync(rq)) +- return 0; +- +- /* +- * Lookup the bfqq that this bio will be queued with. Allow +- * merge only if rq is queued there. +- * Queue lock is held here. +- */ +- bic = bfq_bic_lookup(bfqd, current->io_context); +- if (bic == NULL) +- return 0; +- +- bfqq = bic_to_bfqq(bic, bfq_bio_sync(bio)); +- return bfqq == RQ_BFQQ(rq); +-} +- +-static void __bfq_set_in_service_queue(struct bfq_data *bfqd, +- struct bfq_queue *bfqq) +-{ +- if (bfqq != NULL) { +- bfq_mark_bfqq_must_alloc(bfqq); +- bfq_mark_bfqq_budget_new(bfqq); +- bfq_clear_bfqq_fifo_expire(bfqq); +- +- bfqd->budgets_assigned = (bfqd->budgets_assigned*7 + 256) / 8; +- +- bfq_log_bfqq(bfqd, bfqq, +- "set_in_service_queue, cur-budget = %lu", +- bfqq->entity.budget); +- } +- +- bfqd->in_service_queue = bfqq; +-} +- +-/* +- * Get and set a new queue for service. +- */ +-static struct bfq_queue *bfq_set_in_service_queue(struct bfq_data *bfqd, +- struct bfq_queue *bfqq) +-{ +- if (!bfqq) +- bfqq = bfq_get_next_queue(bfqd); ++ if (request) ++ return blk_rq_pos(io_struct); + else +- bfq_get_next_queue_forced(bfqd, bfqq); +- +- __bfq_set_in_service_queue(bfqd, bfqq); +- return bfqq; ++ return ((struct bio *)io_struct)->bi_iter.bi_sector; + } + +-static inline sector_t bfq_dist_from_last(struct bfq_data *bfqd, +- struct request *rq) ++static inline sector_t bfq_dist_from(sector_t pos1, ++ sector_t pos2) + { +- if (blk_rq_pos(rq) >= bfqd->last_position) +- return blk_rq_pos(rq) - bfqd->last_position; ++ if (pos1 >= pos2) ++ return pos1 - pos2; + else +- return bfqd->last_position - blk_rq_pos(rq); ++ return pos2 - pos1; + } + +-/* +- * Return true if bfqq has no request pending and rq is close enough to +- * bfqd->last_position, or if rq is closer to bfqd->last_position than +- * bfqq->next_rq +- */ +-static inline int bfq_rq_close(struct bfq_data *bfqd, struct request *rq) ++static inline int bfq_rq_close_to_sector(void *io_struct, bool request, ++ sector_t sector) + { +- return bfq_dist_from_last(bfqd, rq) <= BFQQ_SEEK_THR; ++ return bfq_dist_from(bfq_io_struct_pos(io_struct, request), sector) <= ++ BFQQ_SEEK_THR; + } + +-static struct bfq_queue *bfqq_close(struct bfq_data *bfqd) ++static struct bfq_queue *bfqq_close(struct bfq_data *bfqd, sector_t sector) + { + struct rb_root *root = &bfqd->rq_pos_tree; + struct rb_node *parent, *node; + struct bfq_queue *__bfqq; +- sector_t sector = bfqd->last_position; + + if (RB_EMPTY_ROOT(root)) + return NULL; +@@ -1258,7 +1265,7 @@ static struct bfq_queue *bfqq_close(struct bfq_data *bfqd) + * next_request position). + */ + __bfqq = rb_entry(parent, struct bfq_queue, pos_node); +- if (bfq_rq_close(bfqd, __bfqq->next_rq)) ++ if (bfq_rq_close_to_sector(__bfqq->next_rq, true, sector)) + return __bfqq; + + if (blk_rq_pos(__bfqq->next_rq) < sector) +@@ -1269,7 +1276,7 @@ static struct bfq_queue *bfqq_close(struct bfq_data *bfqd) + return NULL; + + __bfqq = rb_entry(node, struct bfq_queue, pos_node); +- if (bfq_rq_close(bfqd, __bfqq->next_rq)) ++ if (bfq_rq_close_to_sector(__bfqq->next_rq, true, sector)) + return __bfqq; + + return NULL; +@@ -1278,14 +1285,12 @@ static struct bfq_queue *bfqq_close(struct bfq_data *bfqd) + /* + * bfqd - obvious + * cur_bfqq - passed in so that we don't decide that the current queue +- * is closely cooperating with itself. +- * +- * We are assuming that cur_bfqq has dispatched at least one request, +- * and that bfqd->last_position reflects a position on the disk associated +- * with the I/O issued by cur_bfqq. ++ * is closely cooperating with itself ++ * sector - used as a reference point to search for a close queue + */ + static struct bfq_queue *bfq_close_cooperator(struct bfq_data *bfqd, +- struct bfq_queue *cur_bfqq) ++ struct bfq_queue *cur_bfqq, ++ sector_t sector) + { + struct bfq_queue *bfqq; + +@@ -1305,7 +1310,7 @@ static struct bfq_queue *bfq_close_cooperator(struct bfq_data *bfqd, + * working closely on the same area of the disk. In that case, + * we can group them together and don't waste time idling. + */ +- bfqq = bfqq_close(bfqd); ++ bfqq = bfqq_close(bfqd, sector); + if (bfqq == NULL || bfqq == cur_bfqq) + return NULL; + +@@ -1332,6 +1337,315 @@ static struct bfq_queue *bfq_close_cooperator(struct bfq_data *bfqd, + return bfqq; + } + ++static struct bfq_queue * ++bfq_setup_merge(struct bfq_queue *bfqq, struct bfq_queue *new_bfqq) ++{ ++ int process_refs, new_process_refs; ++ struct bfq_queue *__bfqq; ++ ++ /* ++ * If there are no process references on the new_bfqq, then it is ++ * unsafe to follow the ->new_bfqq chain as other bfqq's in the chain ++ * may have dropped their last reference (not just their last process ++ * reference). ++ */ ++ if (!bfqq_process_refs(new_bfqq)) ++ return NULL; ++ ++ /* Avoid a circular list and skip interim queue merges. */ ++ while ((__bfqq = new_bfqq->new_bfqq)) { ++ if (__bfqq == bfqq) ++ return NULL; ++ new_bfqq = __bfqq; ++ } ++ ++ process_refs = bfqq_process_refs(bfqq); ++ new_process_refs = bfqq_process_refs(new_bfqq); ++ /* ++ * If the process for the bfqq has gone away, there is no ++ * sense in merging the queues. ++ */ ++ if (process_refs == 0 || new_process_refs == 0) ++ return NULL; ++ ++ bfq_log_bfqq(bfqq->bfqd, bfqq, "scheduling merge with queue %d", ++ new_bfqq->pid); ++ ++ /* ++ * Merging is just a redirection: the requests of the process ++ * owning one of the two queues are redirected to the other queue. ++ * The latter queue, in its turn, is set as shared if this is the ++ * first time that the requests of some process are redirected to ++ * it. ++ * ++ * We redirect bfqq to new_bfqq and not the opposite, because we ++ * are in the context of the process owning bfqq, hence we have ++ * the io_cq of this process. So we can immediately configure this ++ * io_cq to redirect the requests of the process to new_bfqq. ++ * ++ * NOTE, even if new_bfqq coincides with the in-service queue, the ++ * io_cq of new_bfqq is not available, because, if the in-service ++ * queue is shared, bfqd->in_service_bic may not point to the ++ * io_cq of the in-service queue. ++ * Redirecting the requests of the process owning bfqq to the ++ * currently in-service queue is in any case the best option, as ++ * we feed the in-service queue with new requests close to the ++ * last request served and, by doing so, hopefully increase the ++ * throughput. ++ */ ++ bfqq->new_bfqq = new_bfqq; ++ atomic_add(process_refs, &new_bfqq->ref); ++ return new_bfqq; ++} ++ ++/* ++ * Attempt to schedule a merge of bfqq with the currently in-service queue ++ * or with a close queue among the scheduled queues. ++ * Return NULL if no merge was scheduled, a pointer to the shared bfq_queue ++ * structure otherwise. ++ * ++ * The OOM queue is not allowed to participate to cooperation: in fact, since ++ * the requests temporarily redirected to the OOM queue could be redirected ++ * again to dedicated queues at any time, the state needed to correctly ++ * handle merging with the OOM queue would be quite complex and expensive ++ * to maintain. Besides, in such a critical condition as an out of memory, ++ * the benefits of queue merging may be little relevant, or even negligible. ++ */ ++static struct bfq_queue * ++bfq_setup_cooperator(struct bfq_data *bfqd, struct bfq_queue *bfqq, ++ void *io_struct, bool request) ++{ ++ struct bfq_queue *in_service_bfqq, *new_bfqq; ++ ++ if (bfqq->new_bfqq) ++ return bfqq->new_bfqq; ++ ++ if (!io_struct || unlikely(bfqq == &bfqd->oom_bfqq)) ++ return NULL; ++ ++ in_service_bfqq = bfqd->in_service_queue; ++ ++ if (in_service_bfqq == NULL || in_service_bfqq == bfqq || ++ !bfqd->in_service_bic || ++ unlikely(in_service_bfqq == &bfqd->oom_bfqq)) ++ goto check_scheduled; ++ ++ if (bfq_class_idle(in_service_bfqq) || bfq_class_idle(bfqq)) ++ goto check_scheduled; ++ ++ if (bfq_class_rt(in_service_bfqq) != bfq_class_rt(bfqq)) ++ goto check_scheduled; ++ ++ if (in_service_bfqq->entity.parent != bfqq->entity.parent) ++ goto check_scheduled; ++ ++ if (bfq_rq_close_to_sector(io_struct, request, bfqd->last_position) && ++ bfq_bfqq_sync(in_service_bfqq) && bfq_bfqq_sync(bfqq)) { ++ new_bfqq = bfq_setup_merge(bfqq, in_service_bfqq); ++ if (new_bfqq != NULL) ++ return new_bfqq; /* Merge with in-service queue */ ++ } ++ ++ /* ++ * Check whether there is a cooperator among currently scheduled ++ * queues. The only thing we need is that the bio/request is not ++ * NULL, as we need it to establish whether a cooperator exists. ++ */ ++check_scheduled: ++ new_bfqq = bfq_close_cooperator(bfqd, bfqq, ++ bfq_io_struct_pos(io_struct, request)); ++ if (new_bfqq && likely(new_bfqq != &bfqd->oom_bfqq)) ++ return bfq_setup_merge(bfqq, new_bfqq); ++ ++ return NULL; ++} ++ ++static inline void ++bfq_bfqq_save_state(struct bfq_queue *bfqq) ++{ ++ /* ++ * If bfqq->bic == NULL, the queue is already shared or its requests ++ * have already been redirected to a shared queue; both idle window ++ * and weight raising state have already been saved. Do nothing. ++ */ ++ if (bfqq->bic == NULL) ++ return; ++ if (bfqq->bic->wr_time_left) ++ /* ++ * This is the queue of a just-started process, and would ++ * deserve weight raising: we set wr_time_left to the full ++ * weight-raising duration to trigger weight-raising when ++ * and if the queue is split and the first request of the ++ * queue is enqueued. ++ */ ++ bfqq->bic->wr_time_left = bfq_wr_duration(bfqq->bfqd); ++ else if (bfqq->wr_coeff > 1) { ++ unsigned long wr_duration = ++ jiffies - bfqq->last_wr_start_finish; ++ /* ++ * It may happen that a queue's weight raising period lasts ++ * longer than its wr_cur_max_time, as weight raising is ++ * handled only when a request is enqueued or dispatched (it ++ * does not use any timer). If the weight raising period is ++ * about to end, don't save it. ++ */ ++ if (bfqq->wr_cur_max_time <= wr_duration) ++ bfqq->bic->wr_time_left = 0; ++ else ++ bfqq->bic->wr_time_left = ++ bfqq->wr_cur_max_time - wr_duration; ++ /* ++ * The bfq_queue is becoming shared or the requests of the ++ * process owning the queue are being redirected to a shared ++ * queue. Stop the weight raising period of the queue, as in ++ * both cases it should not be owned by an interactive or ++ * soft real-time application. ++ */ ++ bfq_bfqq_end_wr(bfqq); ++ } else ++ bfqq->bic->wr_time_left = 0; ++ bfqq->bic->saved_idle_window = bfq_bfqq_idle_window(bfqq); ++ bfqq->bic->saved_IO_bound = bfq_bfqq_IO_bound(bfqq); ++ bfqq->bic->saved_in_large_burst = bfq_bfqq_in_large_burst(bfqq); ++ bfqq->bic->was_in_burst_list = !hlist_unhashed(&bfqq->burst_list_node); ++ bfqq->bic->cooperations++; ++ bfqq->bic->failed_cooperations = 0; ++} ++ ++static inline void ++bfq_get_bic_reference(struct bfq_queue *bfqq) ++{ ++ /* ++ * If bfqq->bic has a non-NULL value, the bic to which it belongs ++ * is about to begin using a shared bfq_queue. ++ */ ++ if (bfqq->bic) ++ atomic_long_inc(&bfqq->bic->icq.ioc->refcount); ++} ++ ++static void ++bfq_merge_bfqqs(struct bfq_data *bfqd, struct bfq_io_cq *bic, ++ struct bfq_queue *bfqq, struct bfq_queue *new_bfqq) ++{ ++ bfq_log_bfqq(bfqd, bfqq, "merging with queue %lu", ++ (long unsigned)new_bfqq->pid); ++ /* Save weight raising and idle window of the merged queues */ ++ bfq_bfqq_save_state(bfqq); ++ bfq_bfqq_save_state(new_bfqq); ++ if (bfq_bfqq_IO_bound(bfqq)) ++ bfq_mark_bfqq_IO_bound(new_bfqq); ++ bfq_clear_bfqq_IO_bound(bfqq); ++ /* ++ * Grab a reference to the bic, to prevent it from being destroyed ++ * before being possibly touched by a bfq_split_bfqq(). ++ */ ++ bfq_get_bic_reference(bfqq); ++ bfq_get_bic_reference(new_bfqq); ++ /* ++ * Merge queues (that is, let bic redirect its requests to new_bfqq) ++ */ ++ bic_set_bfqq(bic, new_bfqq, 1); ++ bfq_mark_bfqq_coop(new_bfqq); ++ /* ++ * new_bfqq now belongs to at least two bics (it is a shared queue): ++ * set new_bfqq->bic to NULL. bfqq either: ++ * - does not belong to any bic any more, and hence bfqq->bic must ++ * be set to NULL, or ++ * - is a queue whose owning bics have already been redirected to a ++ * different queue, hence the queue is destined to not belong to ++ * any bic soon and bfqq->bic is already NULL (therefore the next ++ * assignment causes no harm). ++ */ ++ new_bfqq->bic = NULL; ++ bfqq->bic = NULL; ++ bfq_put_queue(bfqq); ++} ++ ++static inline void bfq_bfqq_increase_failed_cooperations(struct bfq_queue *bfqq) ++{ ++ struct bfq_io_cq *bic = bfqq->bic; ++ struct bfq_data *bfqd = bfqq->bfqd; ++ ++ if (bic && bfq_bfqq_cooperations(bfqq) >= bfqd->bfq_coop_thresh) { ++ bic->failed_cooperations++; ++ if (bic->failed_cooperations >= bfqd->bfq_failed_cooperations) ++ bic->cooperations = 0; ++ } ++} ++ ++static int bfq_allow_merge(struct request_queue *q, struct request *rq, ++ struct bio *bio) ++{ ++ struct bfq_data *bfqd = q->elevator->elevator_data; ++ struct bfq_io_cq *bic; ++ struct bfq_queue *bfqq, *new_bfqq; ++ ++ /* ++ * Disallow merge of a sync bio into an async request. ++ */ ++ if (bfq_bio_sync(bio) && !rq_is_sync(rq)) ++ return 0; ++ ++ /* ++ * Lookup the bfqq that this bio will be queued with. Allow ++ * merge only if rq is queued there. ++ * Queue lock is held here. ++ */ ++ bic = bfq_bic_lookup(bfqd, current->io_context); ++ if (bic == NULL) ++ return 0; ++ ++ bfqq = bic_to_bfqq(bic, bfq_bio_sync(bio)); ++ /* ++ * We take advantage of this function to perform an early merge ++ * of the queues of possible cooperating processes. ++ */ ++ if (bfqq != NULL) { ++ new_bfqq = bfq_setup_cooperator(bfqd, bfqq, bio, false); ++ if (new_bfqq != NULL) { ++ bfq_merge_bfqqs(bfqd, bic, bfqq, new_bfqq); ++ /* ++ * If we get here, the bio will be queued in the ++ * shared queue, i.e., new_bfqq, so use new_bfqq ++ * to decide whether bio and rq can be merged. ++ */ ++ bfqq = new_bfqq; ++ } else ++ bfq_bfqq_increase_failed_cooperations(bfqq); ++ } ++ ++ return bfqq == RQ_BFQQ(rq); ++} ++ ++static void __bfq_set_in_service_queue(struct bfq_data *bfqd, ++ struct bfq_queue *bfqq) ++{ ++ if (bfqq != NULL) { ++ bfq_mark_bfqq_must_alloc(bfqq); ++ bfq_mark_bfqq_budget_new(bfqq); ++ bfq_clear_bfqq_fifo_expire(bfqq); ++ ++ bfqd->budgets_assigned = (bfqd->budgets_assigned*7 + 256) / 8; ++ ++ bfq_log_bfqq(bfqd, bfqq, ++ "set_in_service_queue, cur-budget = %lu", ++ bfqq->entity.budget); ++ } ++ ++ bfqd->in_service_queue = bfqq; ++} ++ ++/* ++ * Get and set a new queue for service. ++ */ ++static struct bfq_queue *bfq_set_in_service_queue(struct bfq_data *bfqd) ++{ ++ struct bfq_queue *bfqq = bfq_get_next_queue(bfqd); ++ ++ __bfq_set_in_service_queue(bfqd, bfqq); ++ return bfqq; ++} ++ + /* + * If enough samples have been computed, return the current max budget + * stored in bfqd, which is dynamically updated according to the +@@ -1475,61 +1789,6 @@ static struct request *bfq_check_fifo(struct bfq_queue *bfqq) + return rq; + } + +-/* Must be called with the queue_lock held. */ +-static int bfqq_process_refs(struct bfq_queue *bfqq) +-{ +- int process_refs, io_refs; +- +- io_refs = bfqq->allocated[READ] + bfqq->allocated[WRITE]; +- process_refs = atomic_read(&bfqq->ref) - io_refs - bfqq->entity.on_st; +- BUG_ON(process_refs < 0); +- return process_refs; +-} +- +-static void bfq_setup_merge(struct bfq_queue *bfqq, struct bfq_queue *new_bfqq) +-{ +- int process_refs, new_process_refs; +- struct bfq_queue *__bfqq; +- +- /* +- * If there are no process references on the new_bfqq, then it is +- * unsafe to follow the ->new_bfqq chain as other bfqq's in the chain +- * may have dropped their last reference (not just their last process +- * reference). +- */ +- if (!bfqq_process_refs(new_bfqq)) +- return; +- +- /* Avoid a circular list and skip interim queue merges. */ +- while ((__bfqq = new_bfqq->new_bfqq)) { +- if (__bfqq == bfqq) +- return; +- new_bfqq = __bfqq; +- } +- +- process_refs = bfqq_process_refs(bfqq); +- new_process_refs = bfqq_process_refs(new_bfqq); +- /* +- * If the process for the bfqq has gone away, there is no +- * sense in merging the queues. +- */ +- if (process_refs == 0 || new_process_refs == 0) +- return; +- +- /* +- * Merge in the direction of the lesser amount of work. +- */ +- if (new_process_refs >= process_refs) { +- bfqq->new_bfqq = new_bfqq; +- atomic_add(process_refs, &new_bfqq->ref); +- } else { +- new_bfqq->new_bfqq = bfqq; +- atomic_add(new_process_refs, &bfqq->ref); +- } +- bfq_log_bfqq(bfqq->bfqd, bfqq, "scheduling merge with queue %d", +- new_bfqq->pid); +-} +- + static inline unsigned long bfq_bfqq_budget_left(struct bfq_queue *bfqq) + { + struct bfq_entity *entity = &bfqq->entity; +@@ -2263,7 +2522,7 @@ static inline bool bfq_bfqq_must_idle(struct bfq_queue *bfqq) + */ + static struct bfq_queue *bfq_select_queue(struct bfq_data *bfqd) + { +- struct bfq_queue *bfqq, *new_bfqq = NULL; ++ struct bfq_queue *bfqq; + struct request *next_rq; + enum bfqq_expiration reason = BFQ_BFQQ_BUDGET_TIMEOUT; + +@@ -2273,17 +2532,6 @@ static struct bfq_queue *bfq_select_queue(struct bfq_data *bfqd) + + bfq_log_bfqq(bfqd, bfqq, "select_queue: already in-service queue"); + +- /* +- * If another queue has a request waiting within our mean seek +- * distance, let it run. The expire code will check for close +- * cooperators and put the close queue at the front of the +- * service tree. If possible, merge the expiring queue with the +- * new bfqq. +- */ +- new_bfqq = bfq_close_cooperator(bfqd, bfqq); +- if (new_bfqq != NULL && bfqq->new_bfqq == NULL) +- bfq_setup_merge(bfqq, new_bfqq); +- + if (bfq_may_expire_for_budg_timeout(bfqq) && + !timer_pending(&bfqd->idle_slice_timer) && + !bfq_bfqq_must_idle(bfqq)) +@@ -2322,10 +2570,7 @@ static struct bfq_queue *bfq_select_queue(struct bfq_data *bfqd) + bfq_clear_bfqq_wait_request(bfqq); + del_timer(&bfqd->idle_slice_timer); + } +- if (new_bfqq == NULL) +- goto keep_queue; +- else +- goto expire; ++ goto keep_queue; + } + } + +@@ -2334,40 +2579,30 @@ static struct bfq_queue *bfq_select_queue(struct bfq_data *bfqd) + * in flight (possibly waiting for a completion) or is idling for a + * new request, then keep it. + */ +- if (new_bfqq == NULL && (timer_pending(&bfqd->idle_slice_timer) || +- (bfqq->dispatched != 0 && bfq_bfqq_must_not_expire(bfqq)))) { ++ if (timer_pending(&bfqd->idle_slice_timer) || ++ (bfqq->dispatched != 0 && bfq_bfqq_must_not_expire(bfqq))) { + bfqq = NULL; + goto keep_queue; +- } else if (new_bfqq != NULL && timer_pending(&bfqd->idle_slice_timer)) { +- /* +- * Expiring the queue because there is a close cooperator, +- * cancel timer. +- */ +- bfq_clear_bfqq_wait_request(bfqq); +- del_timer(&bfqd->idle_slice_timer); + } + + reason = BFQ_BFQQ_NO_MORE_REQUESTS; + expire: + bfq_bfqq_expire(bfqd, bfqq, 0, reason); + new_queue: +- bfqq = bfq_set_in_service_queue(bfqd, new_bfqq); ++ bfqq = bfq_set_in_service_queue(bfqd); + bfq_log(bfqd, "select_queue: new queue %d returned", + bfqq != NULL ? bfqq->pid : 0); + keep_queue: + return bfqq; + } + +-static void bfq_update_wr_data(struct bfq_data *bfqd, +- struct bfq_queue *bfqq) ++static void bfq_update_wr_data(struct bfq_data *bfqd, struct bfq_queue *bfqq) + { +- if (bfqq->wr_coeff > 1) { /* queue is being boosted */ +- struct bfq_entity *entity = &bfqq->entity; +- ++ struct bfq_entity *entity = &bfqq->entity; ++ if (bfqq->wr_coeff > 1) { /* queue is being weight-raised */ + bfq_log_bfqq(bfqd, bfqq, + "raising period dur %u/%u msec, old coeff %u, w %d(%d)", +- jiffies_to_msecs(jiffies - +- bfqq->last_wr_start_finish), ++ jiffies_to_msecs(jiffies - bfqq->last_wr_start_finish), + jiffies_to_msecs(bfqq->wr_cur_max_time), + bfqq->wr_coeff, + bfqq->entity.weight, bfqq->entity.orig_weight); +@@ -2376,12 +2611,16 @@ static void bfq_update_wr_data(struct bfq_data *bfqd, + entity->orig_weight * bfqq->wr_coeff); + if (entity->ioprio_changed) + bfq_log_bfqq(bfqd, bfqq, "WARN: pending prio change"); ++ + /* + * If the queue was activated in a burst, or + * too much time has elapsed from the beginning +- * of this weight-raising, then end weight raising. ++ * of this weight-raising period, or the queue has ++ * exceeded the acceptable number of cooperations, ++ * then end weight raising. + */ + if (bfq_bfqq_in_large_burst(bfqq) || ++ bfq_bfqq_cooperations(bfqq) >= bfqd->bfq_coop_thresh || + time_is_before_jiffies(bfqq->last_wr_start_finish + + bfqq->wr_cur_max_time)) { + bfqq->last_wr_start_finish = jiffies; +@@ -2390,11 +2629,13 @@ static void bfq_update_wr_data(struct bfq_data *bfqd, + bfqq->last_wr_start_finish, + jiffies_to_msecs(bfqq->wr_cur_max_time)); + bfq_bfqq_end_wr(bfqq); +- __bfq_entity_update_weight_prio( +- bfq_entity_service_tree(entity), +- entity); + } + } ++ /* Update weight both if it must be raised and if it must be lowered */ ++ if ((entity->weight > entity->orig_weight) != (bfqq->wr_coeff > 1)) ++ __bfq_entity_update_weight_prio( ++ bfq_entity_service_tree(entity), ++ entity); + } + + /* +@@ -2642,6 +2883,25 @@ static inline void bfq_init_icq(struct io_cq *icq) + struct bfq_io_cq *bic = icq_to_bic(icq); + + bic->ttime.last_end_request = jiffies; ++ /* ++ * A newly created bic indicates that the process has just ++ * started doing I/O, and is probably mapping into memory its ++ * executable and libraries: it definitely needs weight raising. ++ * There is however the possibility that the process performs, ++ * for a while, I/O close to some other process. EQM intercepts ++ * this behavior and may merge the queue corresponding to the ++ * process with some other queue, BEFORE the weight of the queue ++ * is raised. Merged queues are not weight-raised (they are assumed ++ * to belong to processes that benefit only from high throughput). ++ * If the merge is basically the consequence of an accident, then ++ * the queue will be split soon and will get back its old weight. ++ * It is then important to write down somewhere that this queue ++ * does need weight raising, even if it did not make it to get its ++ * weight raised before being merged. To this purpose, we overload ++ * the field raising_time_left and assign 1 to it, to mark the queue ++ * as needing weight raising. ++ */ ++ bic->wr_time_left = 1; + } + + static void bfq_exit_icq(struct io_cq *icq) +@@ -2655,6 +2915,13 @@ static void bfq_exit_icq(struct io_cq *icq) + } + + if (bic->bfqq[BLK_RW_SYNC]) { ++ /* ++ * If the bic is using a shared queue, put the reference ++ * taken on the io_context when the bic started using a ++ * shared bfq_queue. ++ */ ++ if (bfq_bfqq_coop(bic->bfqq[BLK_RW_SYNC])) ++ put_io_context(icq->ioc); + bfq_exit_bfqq(bfqd, bic->bfqq[BLK_RW_SYNC]); + bic->bfqq[BLK_RW_SYNC] = NULL; + } +@@ -2950,6 +3217,10 @@ static void bfq_update_idle_window(struct bfq_data *bfqd, + if (!bfq_bfqq_sync(bfqq) || bfq_class_idle(bfqq)) + return; + ++ /* Idle window just restored, statistics are meaningless. */ ++ if (bfq_bfqq_just_split(bfqq)) ++ return; ++ + enable_idle = bfq_bfqq_idle_window(bfqq); + + if (atomic_read(&bic->icq.ioc->active_ref) == 0 || +@@ -2997,6 +3268,7 @@ static void bfq_rq_enqueued(struct bfq_data *bfqd, struct bfq_queue *bfqq, + if (bfqq->entity.service > bfq_max_budget(bfqd) / 8 || + !BFQQ_SEEKY(bfqq)) + bfq_update_idle_window(bfqd, bfqq, bic); ++ bfq_clear_bfqq_just_split(bfqq); + + bfq_log_bfqq(bfqd, bfqq, + "rq_enqueued: idle_window=%d (seeky %d, mean %llu)", +@@ -3057,13 +3329,49 @@ static void bfq_rq_enqueued(struct bfq_data *bfqd, struct bfq_queue *bfqq, + static void bfq_insert_request(struct request_queue *q, struct request *rq) + { + struct bfq_data *bfqd = q->elevator->elevator_data; +- struct bfq_queue *bfqq = RQ_BFQQ(rq); ++ struct bfq_queue *bfqq = RQ_BFQQ(rq), *new_bfqq; + + assert_spin_locked(bfqd->queue->queue_lock); ++ ++ /* ++ * An unplug may trigger a requeue of a request from the device ++ * driver: make sure we are in process context while trying to ++ * merge two bfq_queues. ++ */ ++ if (!in_interrupt()) { ++ new_bfqq = bfq_setup_cooperator(bfqd, bfqq, rq, true); ++ if (new_bfqq != NULL) { ++ if (bic_to_bfqq(RQ_BIC(rq), 1) != bfqq) ++ new_bfqq = bic_to_bfqq(RQ_BIC(rq), 1); ++ /* ++ * Release the request's reference to the old bfqq ++ * and make sure one is taken to the shared queue. ++ */ ++ new_bfqq->allocated[rq_data_dir(rq)]++; ++ bfqq->allocated[rq_data_dir(rq)]--; ++ atomic_inc(&new_bfqq->ref); ++ bfq_put_queue(bfqq); ++ if (bic_to_bfqq(RQ_BIC(rq), 1) == bfqq) ++ bfq_merge_bfqqs(bfqd, RQ_BIC(rq), ++ bfqq, new_bfqq); ++ rq->elv.priv[1] = new_bfqq; ++ bfqq = new_bfqq; ++ } else ++ bfq_bfqq_increase_failed_cooperations(bfqq); ++ } ++ + bfq_init_prio_data(bfqq, RQ_BIC(rq)); + + bfq_add_request(rq); + ++ /* ++ * Here a newly-created bfq_queue has already started a weight-raising ++ * period: clear raising_time_left to prevent bfq_bfqq_save_state() ++ * from assigning it a full weight-raising period. See the detailed ++ * comments about this field in bfq_init_icq(). ++ */ ++ if (bfqq->bic != NULL) ++ bfqq->bic->wr_time_left = 0; + rq->fifo_time = jiffies + bfqd->bfq_fifo_expire[rq_is_sync(rq)]; + list_add_tail(&rq->queuelist, &bfqq->fifo); + +@@ -3228,18 +3536,6 @@ static void bfq_put_request(struct request *rq) + } + } + +-static struct bfq_queue * +-bfq_merge_bfqqs(struct bfq_data *bfqd, struct bfq_io_cq *bic, +- struct bfq_queue *bfqq) +-{ +- bfq_log_bfqq(bfqd, bfqq, "merging with queue %lu", +- (long unsigned)bfqq->new_bfqq->pid); +- bic_set_bfqq(bic, bfqq->new_bfqq, 1); +- bfq_mark_bfqq_coop(bfqq->new_bfqq); +- bfq_put_queue(bfqq); +- return bic_to_bfqq(bic, 1); +-} +- + /* + * Returns NULL if a new bfqq should be allocated, or the old bfqq if this + * was the last process referring to said bfqq. +@@ -3248,6 +3544,9 @@ static struct bfq_queue * + bfq_split_bfqq(struct bfq_io_cq *bic, struct bfq_queue *bfqq) + { + bfq_log_bfqq(bfqq->bfqd, bfqq, "splitting queue"); ++ ++ put_io_context(bic->icq.ioc); ++ + if (bfqq_process_refs(bfqq) == 1) { + bfqq->pid = current->pid; + bfq_clear_bfqq_coop(bfqq); +@@ -3276,6 +3575,7 @@ static int bfq_set_request(struct request_queue *q, struct request *rq, + struct bfq_queue *bfqq; + struct bfq_group *bfqg; + unsigned long flags; ++ bool split = false; + + might_sleep_if(gfp_mask & __GFP_WAIT); + +@@ -3293,25 +3593,26 @@ new_queue: + if (bfqq == NULL || bfqq == &bfqd->oom_bfqq) { + bfqq = bfq_get_queue(bfqd, bfqg, is_sync, bic, gfp_mask); + bic_set_bfqq(bic, bfqq, is_sync); ++ if (split && is_sync) { ++ if ((bic->was_in_burst_list && bfqd->large_burst) || ++ bic->saved_in_large_burst) ++ bfq_mark_bfqq_in_large_burst(bfqq); ++ else { ++ bfq_clear_bfqq_in_large_burst(bfqq); ++ if (bic->was_in_burst_list) ++ hlist_add_head(&bfqq->burst_list_node, ++ &bfqd->burst_list); ++ } ++ } + } else { +- /* +- * If the queue was seeky for too long, break it apart. +- */ ++ /* If the queue was seeky for too long, break it apart. */ + if (bfq_bfqq_coop(bfqq) && bfq_bfqq_split_coop(bfqq)) { + bfq_log_bfqq(bfqd, bfqq, "breaking apart bfqq"); + bfqq = bfq_split_bfqq(bic, bfqq); ++ split = true; + if (!bfqq) + goto new_queue; + } +- +- /* +- * Check to see if this queue is scheduled to merge with +- * another closely cooperating queue. The merging of queues +- * happens here as it must be done in process context. +- * The reference on new_bfqq was taken in merge_bfqqs. +- */ +- if (bfqq->new_bfqq != NULL) +- bfqq = bfq_merge_bfqqs(bfqd, bic, bfqq); + } + + bfqq->allocated[rw]++; +@@ -3322,6 +3623,26 @@ new_queue: + rq->elv.priv[0] = bic; + rq->elv.priv[1] = bfqq; + ++ /* ++ * If a bfq_queue has only one process reference, it is owned ++ * by only one bfq_io_cq: we can set the bic field of the ++ * bfq_queue to the address of that structure. Also, if the ++ * queue has just been split, mark a flag so that the ++ * information is available to the other scheduler hooks. ++ */ ++ if (likely(bfqq != &bfqd->oom_bfqq) && bfqq_process_refs(bfqq) == 1) { ++ bfqq->bic = bic; ++ if (split) { ++ bfq_mark_bfqq_just_split(bfqq); ++ /* ++ * If the queue has just been split from a shared ++ * queue, restore the idle window and the possible ++ * weight raising period. ++ */ ++ bfq_bfqq_resume_state(bfqq, bic); ++ } ++ } ++ + spin_unlock_irqrestore(q->queue_lock, flags); + + return 0; +diff --git a/block/bfq-sched.c b/block/bfq-sched.c +index 2931563..6764a7e 100644 +--- a/block/bfq-sched.c ++++ b/block/bfq-sched.c +@@ -1091,34 +1091,6 @@ static struct bfq_queue *bfq_get_next_queue(struct bfq_data *bfqd) + return bfqq; + } + +-/* +- * Forced extraction of the given queue. +- */ +-static void bfq_get_next_queue_forced(struct bfq_data *bfqd, +- struct bfq_queue *bfqq) +-{ +- struct bfq_entity *entity; +- struct bfq_sched_data *sd; +- +- BUG_ON(bfqd->in_service_queue != NULL); +- +- entity = &bfqq->entity; +- /* +- * Bubble up extraction/update from the leaf to the root. +- */ +- for_each_entity(entity) { +- sd = entity->sched_data; +- bfq_update_budget(entity); +- bfq_update_vtime(bfq_entity_service_tree(entity)); +- bfq_active_extract(bfq_entity_service_tree(entity), entity); +- sd->in_service_entity = entity; +- sd->next_in_service = NULL; +- entity->service = 0; +- } +- +- return; +-} +- + static void __bfq_bfqd_reset_in_service(struct bfq_data *bfqd) + { + if (bfqd->in_service_bic != NULL) { +diff --git a/block/bfq.h b/block/bfq.h +index 3c5d85e..5ced336 100644 +--- a/block/bfq.h ++++ b/block/bfq.h +@@ -218,18 +218,21 @@ struct bfq_group; + * idle @bfq_queue with no outstanding requests, then + * the task associated with the queue it is deemed as + * soft real-time (see the comments to the function +- * bfq_bfqq_softrt_next_start()). ++ * bfq_bfqq_softrt_next_start()) + * @last_idle_bklogged: time of the last transition of the @bfq_queue from + * idle to backlogged + * @service_from_backlogged: cumulative service received from the @bfq_queue + * since the last transition from idle to + * backlogged ++ * @bic: pointer to the bfq_io_cq owning the bfq_queue, set to %NULL if the ++ * queue is shared + * +- * A bfq_queue is a leaf request queue; it can be associated with an io_context +- * or more, if it is async or shared between cooperating processes. @cgroup +- * holds a reference to the cgroup, to be sure that it does not disappear while +- * a bfqq still references it (mostly to avoid races between request issuing and +- * task migration followed by cgroup destruction). ++ * A bfq_queue is a leaf request queue; it can be associated with an ++ * io_context or more, if it is async or shared between cooperating ++ * processes. @cgroup holds a reference to the cgroup, to be sure that it ++ * does not disappear while a bfqq still references it (mostly to avoid ++ * races between request issuing and task migration followed by cgroup ++ * destruction). + * All the fields are protected by the queue lock of the containing bfqd. + */ + struct bfq_queue { +@@ -269,6 +272,7 @@ struct bfq_queue { + unsigned int requests_within_timer; + + pid_t pid; ++ struct bfq_io_cq *bic; + + /* weight-raising fields */ + unsigned long wr_cur_max_time; +@@ -298,12 +302,42 @@ struct bfq_ttime { + * @icq: associated io_cq structure + * @bfqq: array of two process queues, the sync and the async + * @ttime: associated @bfq_ttime struct ++ * @wr_time_left: snapshot of the time left before weight raising ends ++ * for the sync queue associated to this process; this ++ * snapshot is taken to remember this value while the weight ++ * raising is suspended because the queue is merged with a ++ * shared queue, and is used to set @raising_cur_max_time ++ * when the queue is split from the shared queue and its ++ * weight is raised again ++ * @saved_idle_window: same purpose as the previous field for the idle ++ * window ++ * @saved_IO_bound: same purpose as the previous two fields for the I/O ++ * bound classification of a queue ++ * @saved_in_large_burst: same purpose as the previous fields for the ++ * value of the field keeping the queue's belonging ++ * to a large burst ++ * @was_in_burst_list: true if the queue belonged to a burst list ++ * before its merge with another cooperating queue ++ * @cooperations: counter of consecutive successful queue merges underwent ++ * by any of the process' @bfq_queues ++ * @failed_cooperations: counter of consecutive failed queue merges of any ++ * of the process' @bfq_queues + */ + struct bfq_io_cq { + struct io_cq icq; /* must be the first member */ + struct bfq_queue *bfqq[2]; + struct bfq_ttime ttime; + int ioprio; ++ ++ unsigned int wr_time_left; ++ bool saved_idle_window; ++ bool saved_IO_bound; ++ ++ bool saved_in_large_burst; ++ bool was_in_burst_list; ++ ++ unsigned int cooperations; ++ unsigned int failed_cooperations; + }; + + enum bfq_device_speed { +@@ -539,7 +573,7 @@ enum bfqq_state_flags { + BFQ_BFQQ_FLAG_prio_changed, /* task priority has changed */ + BFQ_BFQQ_FLAG_sync, /* synchronous queue */ + BFQ_BFQQ_FLAG_budget_new, /* no completion with this budget */ +- BFQ_BFQQ_FLAG_IO_bound, /* ++ BFQ_BFQQ_FLAG_IO_bound, /* + * bfqq has timed-out at least once + * having consumed at most 2/10 of + * its budget +@@ -552,12 +586,13 @@ enum bfqq_state_flags { + * bfqq has proved to be slow and + * seeky until budget timeout + */ +- BFQ_BFQQ_FLAG_softrt_update, /* ++ BFQ_BFQQ_FLAG_softrt_update, /* + * may need softrt-next-start + * update + */ + BFQ_BFQQ_FLAG_coop, /* bfqq is shared */ +- BFQ_BFQQ_FLAG_split_coop, /* shared bfqq will be splitted */ ++ BFQ_BFQQ_FLAG_split_coop, /* shared bfqq will be split */ ++ BFQ_BFQQ_FLAG_just_split, /* queue has just been split */ + }; + + #define BFQ_BFQQ_FNS(name) \ +@@ -587,6 +622,7 @@ BFQ_BFQQ_FNS(in_large_burst); + BFQ_BFQQ_FNS(constantly_seeky); + BFQ_BFQQ_FNS(coop); + BFQ_BFQQ_FNS(split_coop); ++BFQ_BFQQ_FNS(just_split); + BFQ_BFQQ_FNS(softrt_update); + #undef BFQ_BFQQ_FNS + +-- +2.3.0 + diff --git a/kernel/tools/cpupowertools/files/patches/gentoo/5010_enable-additional-cpu-optimizations-for-gcc-4.9.patch b/kernel/tools/cpupowertools/files/patches/gentoo/5010_enable-additional-cpu-optimizations-for-gcc-4.9.patch new file mode 100644 index 00000000..f931f75f --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/gentoo/5010_enable-additional-cpu-optimizations-for-gcc-4.9.patch @@ -0,0 +1,387 @@ +WARNING - this version of the patch works with version 4.9+ of gcc and with +kernel version 3.15.x+ and should NOT be applied when compiling on older +versions due to name changes of the flags with the 4.9 release of gcc. +Use the older version of this patch hosted on the same github for older +versions of gcc. For example: + +corei7 --> nehalem +corei7-avx --> sandybridge +core-avx-i --> ivybridge +core-avx2 --> haswell + +For more, see: https://gcc.gnu.org/gcc-4.9/changes.html + +It also changes 'atom' to 'bonnell' in accordance with the gcc v4.9 changes. +Note that upstream is using the deprecated 'match=atom' flags when I believe it +should use the newer 'march=bonnell' flag for atom processors. + +I have made that change to this patch set as well. See the following kernel +bug report to see if I'm right: https://bugzilla.kernel.org/show_bug.cgi?id=77461 + +This patch will expand the number of microarchitectures to include new +processors including: AMD K10-family, AMD Family 10h (Barcelona), AMD Family +14h (Bobcat), AMD Family 15h (Bulldozer), AMD Family 15h (Piledriver), AMD +Family 16h (Jaguar), Intel 1st Gen Core i3/i5/i7 (Nehalem), Intel 1.5 Gen Core +i3/i5/i7 (Westmere), Intel 2nd Gen Core i3/i5/i7 (Sandybridge), Intel 3rd Gen +Core i3/i5/i7 (Ivybridge), Intel 4th Gen Core i3/i5/i7 (Haswell), and Intel 5th +Gen Core i3/i5/i7 (Broadwell). It also offers the compiler the 'native' flag. + +Small but real speed increases are measurable using a make endpoint comparing +a generic kernel to one built with one of the respective microarchs. + +See the following experimental evidence supporting this statement: +https://github.com/graysky2/kernel_gcc_patch + +REQUIREMENTS +linux version >=3.15 +gcc version >=4.9 + +--- a/arch/x86/include/asm/module.h 2014-08-03 18:25:02.000000000 -0400 ++++ b/arch/x86/include/asm/module.h 2014-09-13 09:37:16.721385247 -0400 +@@ -15,6 +15,20 @@ + #define MODULE_PROC_FAMILY "586MMX " + #elif defined CONFIG_MCORE2 + #define MODULE_PROC_FAMILY "CORE2 " ++#elif defined CONFIG_MNATIVE ++#define MODULE_PROC_FAMILY "NATIVE " ++#elif defined CONFIG_MNEHALEM ++#define MODULE_PROC_FAMILY "NEHALEM " ++#elif defined CONFIG_MWESTMERE ++#define MODULE_PROC_FAMILY "WESTMERE " ++#elif defined CONFIG_MSANDYBRIDGE ++#define MODULE_PROC_FAMILY "SANDYBRIDGE " ++#elif defined CONFIG_MIVYBRIDGE ++#define MODULE_PROC_FAMILY "IVYBRIDGE " ++#elif defined CONFIG_MHASWELL ++#define MODULE_PROC_FAMILY "HASWELL " ++#elif defined CONFIG_MBROADWELL ++#define MODULE_PROC_FAMILY "BROADWELL " + #elif defined CONFIG_MATOM + #define MODULE_PROC_FAMILY "ATOM " + #elif defined CONFIG_M686 +@@ -33,6 +47,20 @@ + #define MODULE_PROC_FAMILY "K7 " + #elif defined CONFIG_MK8 + #define MODULE_PROC_FAMILY "K8 " ++#elif defined CONFIG_MK8SSE3 ++#define MODULE_PROC_FAMILY "K8SSE3 " ++#elif defined CONFIG_MK10 ++#define MODULE_PROC_FAMILY "K10 " ++#elif defined CONFIG_MBARCELONA ++#define MODULE_PROC_FAMILY "BARCELONA " ++#elif defined CONFIG_MBOBCAT ++#define MODULE_PROC_FAMILY "BOBCAT " ++#elif defined CONFIG_MBULLDOZER ++#define MODULE_PROC_FAMILY "BULLDOZER " ++#elif defined CONFIG_MPILEDRIVER ++#define MODULE_PROC_FAMILY "PILEDRIVER " ++#elif defined CONFIG_MJAGUAR ++#define MODULE_PROC_FAMILY "JAGUAR " + #elif defined CONFIG_MELAN + #define MODULE_PROC_FAMILY "ELAN " + #elif defined CONFIG_MCRUSOE +--- a/arch/x86/Kconfig.cpu 2014-08-03 18:25:02.000000000 -0400 ++++ b/arch/x86/Kconfig.cpu 2014-09-13 09:37:16.721385247 -0400 +@@ -137,9 +137,8 @@ config MPENTIUM4 + -Paxville + -Dempsey + +- + config MK6 +- bool "K6/K6-II/K6-III" ++ bool "AMD K6/K6-II/K6-III" + depends on X86_32 + ---help--- + Select this for an AMD K6-family processor. Enables use of +@@ -147,7 +146,7 @@ config MK6 + flags to GCC. + + config MK7 +- bool "Athlon/Duron/K7" ++ bool "AMD Athlon/Duron/K7" + depends on X86_32 + ---help--- + Select this for an AMD Athlon K7-family processor. Enables use of +@@ -155,12 +154,62 @@ config MK7 + flags to GCC. + + config MK8 +- bool "Opteron/Athlon64/Hammer/K8" ++ bool "AMD Opteron/Athlon64/Hammer/K8" + ---help--- + Select this for an AMD Opteron or Athlon64 Hammer-family processor. + Enables use of some extended instructions, and passes appropriate + optimization flags to GCC. + ++config MK8SSE3 ++ bool "AMD Opteron/Athlon64/Hammer/K8 with SSE3" ++ ---help--- ++ Select this for improved AMD Opteron or Athlon64 Hammer-family processors. ++ Enables use of some extended instructions, and passes appropriate ++ optimization flags to GCC. ++ ++config MK10 ++ bool "AMD 61xx/7x50/PhenomX3/X4/II/K10" ++ ---help--- ++ Select this for an AMD 61xx Eight-Core Magny-Cours, Athlon X2 7x50, ++ Phenom X3/X4/II, Athlon II X2/X3/X4, or Turion II-family processor. ++ Enables use of some extended instructions, and passes appropriate ++ optimization flags to GCC. ++ ++config MBARCELONA ++ bool "AMD Barcelona" ++ ---help--- ++ Select this for AMD Barcelona and newer processors. ++ ++ Enables -march=barcelona ++ ++config MBOBCAT ++ bool "AMD Bobcat" ++ ---help--- ++ Select this for AMD Bobcat processors. ++ ++ Enables -march=btver1 ++ ++config MBULLDOZER ++ bool "AMD Bulldozer" ++ ---help--- ++ Select this for AMD Bulldozer processors. ++ ++ Enables -march=bdver1 ++ ++config MPILEDRIVER ++ bool "AMD Piledriver" ++ ---help--- ++ Select this for AMD Piledriver processors. ++ ++ Enables -march=bdver2 ++ ++config MJAGUAR ++ bool "AMD Jaguar" ++ ---help--- ++ Select this for AMD Jaguar processors. ++ ++ Enables -march=btver2 ++ + config MCRUSOE + bool "Crusoe" + depends on X86_32 +@@ -251,8 +300,17 @@ config MPSC + using the cpu family field + in /proc/cpuinfo. Family 15 is an older Xeon, Family 6 a newer one. + ++config MATOM ++ bool "Intel Atom" ++ ---help--- ++ ++ Select this for the Intel Atom platform. Intel Atom CPUs have an ++ in-order pipelining architecture and thus can benefit from ++ accordingly optimized code. Use a recent GCC with specific Atom ++ support in order to fully benefit from selecting this option. ++ + config MCORE2 +- bool "Core 2/newer Xeon" ++ bool "Intel Core 2" + ---help--- + + Select this for Intel Core 2 and newer Core 2 Xeons (Xeon 51xx and +@@ -260,14 +318,55 @@ config MCORE2 + family in /proc/cpuinfo. Newer ones have 6 and older ones 15 + (not a typo) + +-config MATOM +- bool "Intel Atom" ++ Enables -march=core2 ++ ++config MNEHALEM ++ bool "Intel Nehalem" + ---help--- + +- Select this for the Intel Atom platform. Intel Atom CPUs have an +- in-order pipelining architecture and thus can benefit from +- accordingly optimized code. Use a recent GCC with specific Atom +- support in order to fully benefit from selecting this option. ++ Select this for 1st Gen Core processors in the Nehalem family. ++ ++ Enables -march=nehalem ++ ++config MWESTMERE ++ bool "Intel Westmere" ++ ---help--- ++ ++ Select this for the Intel Westmere formerly Nehalem-C family. ++ ++ Enables -march=westmere ++ ++config MSANDYBRIDGE ++ bool "Intel Sandy Bridge" ++ ---help--- ++ ++ Select this for 2nd Gen Core processors in the Sandy Bridge family. ++ ++ Enables -march=sandybridge ++ ++config MIVYBRIDGE ++ bool "Intel Ivy Bridge" ++ ---help--- ++ ++ Select this for 3rd Gen Core processors in the Ivy Bridge family. ++ ++ Enables -march=ivybridge ++ ++config MHASWELL ++ bool "Intel Haswell" ++ ---help--- ++ ++ Select this for 4th Gen Core processors in the Haswell family. ++ ++ Enables -march=haswell ++ ++config MBROADWELL ++ bool "Intel Broadwell" ++ ---help--- ++ ++ Select this for 5th Gen Core processors in the Broadwell family. ++ ++ Enables -march=broadwell + + config GENERIC_CPU + bool "Generic-x86-64" +@@ -276,6 +375,19 @@ config GENERIC_CPU + Generic x86-64 CPU. + Run equally well on all x86-64 CPUs. + ++config MNATIVE ++ bool "Native optimizations autodetected by GCC" ++ ---help--- ++ ++ GCC 4.2 and above support -march=native, which automatically detects ++ the optimum settings to use based on your processor. -march=native ++ also detects and applies additional settings beyond -march specific ++ to your CPU, (eg. -msse4). Unless you have a specific reason not to ++ (e.g. distcc cross-compiling), you should probably be using ++ -march=native rather than anything listed below. ++ ++ Enables -march=native ++ + endchoice + + config X86_GENERIC +@@ -300,7 +412,7 @@ config X86_INTERNODE_CACHE_SHIFT + config X86_L1_CACHE_SHIFT + int + default "7" if MPENTIUM4 || MPSC +- default "6" if MK7 || MK8 || MPENTIUMM || MCORE2 || MATOM || MVIAC7 || X86_GENERIC || GENERIC_CPU ++ default "6" if MK7 || MK8 || MK8SSE3 || MK10 || MBARCELONA || MBOBCAT || MBULLDOZER || MPILEDRIVER || MJAGUAR || MPENTIUMM || MCORE2 || MNEHALEM || MWESTMERE || MSANDYBRIDGE || MIVYBRIDGE || MHASWELL || BROADWELL || MNATIVE || MATOM || MVIAC7 || X86_GENERIC || GENERIC_CPU + default "4" if MELAN || M486 || MGEODEGX1 + default "5" if MWINCHIP3D || MWINCHIPC6 || MCRUSOE || MEFFICEON || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || MVIAC3_2 || MGEODE_LX + +@@ -331,11 +443,11 @@ config X86_ALIGNMENT_16 + + config X86_INTEL_USERCOPY + def_bool y +- depends on MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M586MMX || X86_GENERIC || MK8 || MK7 || MEFFICEON || MCORE2 ++ depends on MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M586MMX || X86_GENERIC || MK8 || MK8SSE3 || MK7 || MEFFICEON || MCORE2 || MK10 || MBARCELONA || MNEHALEM || MWESTMERE || MSANDYBRIDGE || MIVYBRIDGE || MHASWELL || MBROADWELL || MNATIVE + + config X86_USE_PPRO_CHECKSUM + def_bool y +- depends on MWINCHIP3D || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MK8 || MVIAC3_2 || MVIAC7 || MEFFICEON || MGEODE_LX || MCORE2 || MATOM ++ depends on MWINCHIP3D || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MK10 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MK8 || MK8SSE3 || MVIAC3_2 || MVIAC7 || MEFFICEON || MGEODE_LX || MCORE2 || MNEHALEM || MWESTMERE || MSANDYBRIDGE || MIVYBRIDGE || MHASWELL || MBROADWELL || MATOM || MNATIVE + + config X86_USE_3DNOW + def_bool y +@@ -359,17 +471,17 @@ config X86_P6_NOP + + config X86_TSC + def_bool y +- depends on (MWINCHIP3D || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MVIAC7 || MGEODEGX1 || MGEODE_LX || MCORE2 || MATOM) || X86_64 ++ depends on (MWINCHIP3D || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MK8SSE3 || MVIAC3_2 || MVIAC7 || MGEODEGX1 || MGEODE_LX || MCORE2 || MNEHALEM || MWESTMERE || MSANDYBRIDGE || MIVYBRIDGE || MHASWELL || MBROADWELL || MNATIVE || MATOM) || X86_64 + + config X86_CMPXCHG64 + def_bool y +- depends on X86_PAE || X86_64 || MCORE2 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MATOM ++ depends on X86_PAE || X86_64 || MCORE2 || MNEHALEM || MWESTMERE || MSANDYBRIDGE || MIVYBRIDGE || MHASWELL || MBROADWELL || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MATOM || MNATIVE + + # this should be set for all -march=.. options where the compiler + # generates cmov. + config X86_CMOV + def_bool y +- depends on (MK8 || MK7 || MCORE2 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MVIAC3_2 || MVIAC7 || MCRUSOE || MEFFICEON || X86_64 || MATOM || MGEODE_LX) ++ depends on (MK8 || MK8SSE3 || MK10 || MBARCELONA || MBOBCAT || MBULLDOZER || MPILEDRIVER || MJAGUAR || MK7 || MCORE2 || MNEHALEM || MWESTMERE || MSANDYBRIDGE || MIVYBRIDGE || MHASWELL || MBROADWELL || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MVIAC3_2 || MVIAC7 || MCRUSOE || MEFFICEON || X86_64 || MNATIVE || MATOM || MGEODE_LX) + + config X86_MINIMUM_CPU_FAMILY + int +--- a/arch/x86/Makefile 2014-08-03 18:25:02.000000000 -0400 ++++ b/arch/x86/Makefile 2014-09-13 09:37:16.721385247 -0400 +@@ -92,13 +92,33 @@ else + KBUILD_CFLAGS += $(call cc-option,-mpreferred-stack-boundary=3) + + # FIXME - should be integrated in Makefile.cpu (Makefile_32.cpu) ++ cflags-$(CONFIG_MNATIVE) += $(call cc-option,-march=native) + cflags-$(CONFIG_MK8) += $(call cc-option,-march=k8) ++ cflags-$(CONFIG_MK8SSE3) += $(call cc-option,-march=k8-sse3,-mtune=k8) ++ cflags-$(CONFIG_MK10) += $(call cc-option,-march=amdfam10) ++ cflags-$(CONFIG_MBARCELONA) += $(call cc-option,-march=barcelona) ++ cflags-$(CONFIG_MBOBCAT) += $(call cc-option,-march=btver1) ++ cflags-$(CONFIG_MBULLDOZER) += $(call cc-option,-march=bdver1) ++ cflags-$(CONFIG_MPILEDRIVER) += $(call cc-option,-march=bdver2) ++ cflags-$(CONFIG_MJAGUAR) += $(call cc-option,-march=btver2) + cflags-$(CONFIG_MPSC) += $(call cc-option,-march=nocona) + + cflags-$(CONFIG_MCORE2) += \ +- $(call cc-option,-march=core2,$(call cc-option,-mtune=generic)) +- cflags-$(CONFIG_MATOM) += $(call cc-option,-march=atom) \ +- $(call cc-option,-mtune=atom,$(call cc-option,-mtune=generic)) ++ $(call cc-option,-march=core2,$(call cc-option,-mtune=core2)) ++ cflags-$(CONFIG_MNEHALEM) += \ ++ $(call cc-option,-march=nehalem,$(call cc-option,-mtune=nehalem)) ++ cflags-$(CONFIG_MWESTMERE) += \ ++ $(call cc-option,-march=westmere,$(call cc-option,-mtune=westmere)) ++ cflags-$(CONFIG_MSANDYBRIDGE) += \ ++ $(call cc-option,-march=sandybridge,$(call cc-option,-mtune=sandybridge)) ++ cflags-$(CONFIG_MIVYBRIDGE) += \ ++ $(call cc-option,-march=ivybridge,$(call cc-option,-mtune=ivybridge)) ++ cflags-$(CONFIG_MHASWELL) += \ ++ $(call cc-option,-march=haswell,$(call cc-option,-mtune=haswell)) ++ cflags-$(CONFIG_MBROADWELL) += \ ++ $(call cc-option,-march=broadwell,$(call cc-option,-mtune=broadwell)) ++ cflags-$(CONFIG_MATOM) += $(call cc-option,-march=bonnell) \ ++ $(call cc-option,-mtune=bonnell,$(call cc-option,-mtune=generic)) + cflags-$(CONFIG_GENERIC_CPU) += $(call cc-option,-mtune=generic) + KBUILD_CFLAGS += $(cflags-y) + +--- a/arch/x86/Makefile_32.cpu 2014-08-03 18:25:02.000000000 -0400 ++++ b/arch/x86/Makefile_32.cpu 2014-09-13 09:37:16.721385247 -0400 +@@ -23,7 +23,15 @@ cflags-$(CONFIG_MK6) += -march=k6 + # Please note, that patches that add -march=athlon-xp and friends are pointless. + # They make zero difference whatsosever to performance at this time. + cflags-$(CONFIG_MK7) += -march=athlon ++cflags-$(CONFIG_MNATIVE) += $(call cc-option,-march=native) + cflags-$(CONFIG_MK8) += $(call cc-option,-march=k8,-march=athlon) ++cflags-$(CONFIG_MK8SSE3) += $(call cc-option,-march=k8-sse3,-march=athlon) ++cflags-$(CONFIG_MK10) += $(call cc-option,-march=amdfam10,-march=athlon) ++cflags-$(CONFIG_MBARCELONA) += $(call cc-option,-march=barcelona,-march=athlon) ++cflags-$(CONFIG_MBOBCAT) += $(call cc-option,-march=btver1,-march=athlon) ++cflags-$(CONFIG_MBULLDOZER) += $(call cc-option,-march=bdver1,-march=athlon) ++cflags-$(CONFIG_MPILEDRIVER) += $(call cc-option,-march=bdver2,-march=athlon) ++cflags-$(CONFIG_MJAGUAR) += $(call cc-option,-march=btver2,-march=athlon) + cflags-$(CONFIG_MCRUSOE) += -march=i686 $(align)-functions=0 $(align)-jumps=0 $(align)-loops=0 + cflags-$(CONFIG_MEFFICEON) += -march=i686 $(call tune,pentium3) $(align)-functions=0 $(align)-jumps=0 $(align)-loops=0 + cflags-$(CONFIG_MWINCHIPC6) += $(call cc-option,-march=winchip-c6,-march=i586) +@@ -32,8 +40,14 @@ cflags-$(CONFIG_MCYRIXIII) += $(call cc- + cflags-$(CONFIG_MVIAC3_2) += $(call cc-option,-march=c3-2,-march=i686) + cflags-$(CONFIG_MVIAC7) += -march=i686 + cflags-$(CONFIG_MCORE2) += -march=i686 $(call tune,core2) +-cflags-$(CONFIG_MATOM) += $(call cc-option,-march=atom,$(call cc-option,-march=core2,-march=i686)) \ +- $(call cc-option,-mtune=atom,$(call cc-option,-mtune=generic)) ++cflags-$(CONFIG_MNEHALEM) += -march=i686 $(call tune,nehalem) ++cflags-$(CONFIG_MWESTMERE) += -march=i686 $(call tune,westmere) ++cflags-$(CONFIG_MSANDYBRIDGE) += -march=i686 $(call tune,sandybridge) ++cflags-$(CONFIG_MIVYBRIDGE) += -march=i686 $(call tune,ivybridge) ++cflags-$(CONFIG_MHASWELL) += -march=i686 $(call tune,haswell) ++cflags-$(CONFIG_MBROADWELL) += -march=i686 $(call tune,broadwell) ++cflags-$(CONFIG_MATOM) += $(call cc-option,-march=bonnell,$(call cc-option,-march=core2,-march=i686)) \ ++ $(call cc-option,-mtune=bonnell,$(call cc-option,-mtune=generic)) + + # AMD Elan support + cflags-$(CONFIG_MELAN) += -march=i486 diff --git a/kernel/tools/cpupowertools/files/patches/linux/patch-4.19.14.xz b/kernel/tools/cpupowertools/files/patches/linux/patch-4.19.14.xz new file mode 100644 index 0000000000000000000000000000000000000000..4dda3d973f909404a33fd7e15b4d9fe3a9ae4dc6 GIT binary patch literal 459580 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

&V*p%DYjuR+f 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�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 z¥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≥39QC*j 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%0DU>nAD`ARH7qgi_h)Pww(j7-#1N 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 u<=Y-mMAI-K~XEITHf)0Hn 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 literal 0 HcmV?d00001 diff --git a/kernel/tools/cpupowertools/files/patches/linux/patch-4.19.26.xz b/kernel/tools/cpupowertools/files/patches/linux/patch-4.19.26.xz new file mode 100644 index 0000000000000000000000000000000000000000..18895a5e1bc325e2990bc152c68fc355e7e33c29 GIT binary patch literal 757952 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

HD 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�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≦R!QZY#$`_QKu*pHKiF~79^GJ_GplL?(Q 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 literal 0 HcmV?d00001 diff --git a/kernel/tools/cpupowertools/files/patches/linux/patch-4.19.27.xz b/kernel/tools/cpupowertools/files/patches/linux/patch-4.19.27.xz new file mode 100644 index 0000000000000000000000000000000000000000..42b0454184bdd937ac4959b253f94244f2a518a4 GIT binary patch literal 776244 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 _6|5Xfji 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

D5Pj%RF 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

Ejt!Cx{Y<|sw zFhEJIoddLc{62<525oB_v=ktGkA`@fyXVV`iS_x7-O$Fh_8YnRTqIJ2h)yiDB`>;1 zto_QgvedsL$*eg8l(!ds9bsLKh@<-Bua_ z&FC?ups?JHG+>vWrm$*IWH-Qq)Akck`ab+jzYOm-Qefa6gDu?>fq4ZeAG}uOyR#(5L?GG#k|H|9=tV6` zP0fdXZx!AG)%>CUgZdRklD0!#L}^waQ-|Y1RBmcM<&{<3^hsTnw27o?tEGgK z_72RRGyM*U%O6&VKId`l{gf)>n3#+wuT3`cq8%Da!U203e6C#I3l zc8~3CsK#<>Kr8bc#q5&X+UQOl@X&i3 zMl`bkcQBN5zY3V^{vh*`-y@OL{FFA~0jLg0`xrU0JNNANZnP& zBCl0fnCKSfVEY@l{224b*GrpnT#=wd10DF7I*4HT_j%<*EGj)r!0O&0>@(7FLRxPy z)HqQa%5LRGtl-jwHjdHKsI};ADHv3yLK`UdzT8Pj_Gg8*#4o;z6>reeYPMnuPiDf@ zR$1!};j6B>6+UCa7Z}OX^H!q0^H;{&)Xv?F->-dPJ&83NTq-FI1E%5qg}=YGO+Q>n z4=IIafO_%rJr3tvqvMjuFt8#~4dgG%#LMh_J&-E1$J@ha{JiZXsLK4k?nYz8pp&d6 zZ0|0s(AlxJC{XDe@-UvHf~NWzJrln|1uY6rJ|olxT)*dujT#V_u+PfKft#@IMii@?#Q6a(4$MGZ?=OY?k#LRyr;Uzc&&4+OC#IBn`md zHzi(H?(vu8CNwgD@CWAGf&|?0&hJ7wF9#u-IEl)8KRDR>ek7e*?NC1(2r@ze46z=P3Z=oj18qfR#y z|Fv384?h8HqOTC({FWd$C)Zo4>528 z5FFusy{q0{rmL_dif+|pCMcGQX9u4X!aJiw^wW-+3R@rERBBt7_-1`xN|*{;Ey0CenRl;C$UD~<;Wd`I&fU=b8O1+qW8O6 z)nCJ%{O<>p21@gOiny++H>GVYctx3Wu>&VIixdi9$^i}%*%Guli|?e+{Dyd->nx7S z9SKdWy97=P(fpq5Rl6lN0+ws`s@N@E9)@m za+y9BmOC3e{c-K!b_Y-l>iW8s2KIF5n}9pwIGrGsq}fIX45`K0Bm%$T9%oVSNL_(RlZJ2iCeuq!5b4ekE0F3*gxR+wA2LOs z(V0Z<>RC1OpQ>Sl!*uw&804>={fMX ztH_B*g@33EJYg_T|GmiQaChE40_Q)DV|0v}2M%&z<~Up~iYWXz0dllYBf?d-^%Y6~ z_g5|6kO)mTovTg>HSL@b26ZqBh_l$vRrO+e`U`0NFJ>lp^vp~=K>+Hq%3GsLzb|1! z`>OsDh?9LHG|DN;tmItJf;<43X+jG49bI2qHC~0heb!lFo1bHiIIIjr>KIO)5Vr9* zZH*r;8)63W5o>c3$n?ZXWjsC=+5l0!INC+3eg+ObJBIaY9{sB<#b zP_|>bKq$!A_fgTzX*pC-B&rCi^Rhn#Z;5-QE}vkraBgy@rcaQ`y@OXzzSGdApy*D~ z2=l5SC|Of?Saz1Y+xOK(ceOIAkK;& z;u|FEV;T8>QyZ?0&O2|5$|3cs2uIs%`snTb;a+g2h}h$>VF24*Z!K|HMr22HjGix-KQ2q^<0dQGV5R_NgHcfD2mHIDS^@{V$!*@ z5W7&to|&E>n*)?#LMyRjix8@#CwodQ^nj1@q|L!44eR987M!!Bq~>Ey@o+zQjx8p; z$NBmW3x#79ePUpxpTE29$x)aNI*MCTH{XqU+27kP-C$q~LTXpA+H%Y(^mc#By^f2M z8G-~0wHNeirtnUylEAtD?$V|<4S73!45&Ms-tKWylmxx5+?5L1sc@{K-y;lBqNZ+b z{nCDKioV@&t$8%T5A%^zh=b#)1lW0(cMQX#zarm7=BE+$}od(Qk2z8y)^@!%)=c_OvI8Vv}9R(y@ zSzVm%)or0upxweH#%+yh#<#FEU<|NZoASTHtww||9uGaIVA2imDwf`uGE{%qrCP&- zbqFsm4{$Rs^2c)?rOGyYz1ZV76Q>mms!|0_3J&qIPb@n@zqB0NUM*>vpgf`TIl2h$ zTZy*vT1+L>hc6dptQZ!-wlSnGFWITKzEshq@={Y+Dsp}p;tO}V1~WZTlnSkAQm}>} zZM=<6Fecc^W6xBwL{ix|2kE$qlJz78Kpmb_f@`ONB_3ItObJ_@ok=UX`11(2#lkJ- zPS)A9#L+BkVPwmB&rM2Z#Xgt+U2}d$KLj`#+7S#9GabT2=7N09TE%`UfiMa{f}&~uB)cu$I@Tl|H{YGQc4 zv}ox)k^&6qW`W3)+k)eVZDz2=3JQQMx`?OiFJ*qrq+d$faeldg^>m}qo}aQzgPD&c zU|Ar}M?7v%19s|lsBkOd^Gcmky3(wiq$TT$25GauvirU-CWpxA^&nqS!%+&*$(~oq z%rj^Ri@pqjdoPkgt1%v9XJ+qg&}OgwS!Gi`;8(Bc)t@Gmn5rSg$2P&zcaG9$txKe( zHgzCkVmQwn0X170s{C1nEZFR089Ni@9o^WvZ*HYR?QH$`1yO7t@R>-cZ`zZ+dw9>F z-_beT_A>qASuwWj{L%_<071oN;1{71{4QM~SkZ0)(uMCBpmjS)xdyw6%Z+O@(lDz? zIzDJ-o1@1m`?^JP$(6(_n1@yNzVpQq8^7#o^t7Ol_ZoMO_KQxFfFE&dpqN%xWNJh{(O;W^!9P&&T?bnv zE^o|5wPXUHh%ukeL=0?^m122#S+_T=qOm$|J|iZulqrbwX2sLM=Z6!G&3zz#Q_S*h z3+4HLd{PEs=ZS?(J(;D;)Q7a)((=QR;=EyhawsujL($x|Nl&zml7~D-$iuL~eS{;2 zOty*tBseJt>8_V^_{?m|gFi4$OXlGnnz3`Qe+_DH=qFY$x_bawU9Kf4U>{BUGtX;^ zI&%BtX$eeY9<%Q?eolDkSSoG32Jh1o&}UR-3$`A$wOj*(E=c2?j#mMhF6d>OzK5I~ zIA>{^WtGKs_baq+PKS&&rVP7H!FK&vDI+d5jdLt1TFi7a){khOEAk7>-tbQ{TsQ)lS$z4Yq+Lx5AgVA9?nSXJS6tE zBy-l9H+jzT)v}M%5g&fVcX#RzE5`xLbW`lCKgE3luq{3jb=q+usNC+N+Hby@F(d*=FWSEM)J=$H%dDS{k3_@>-gn$!;wo!N(#RNe=hJsS0Os_>8 z|7ES{70_8neLKns;*2c*q^!p2U9FIbh*iM--(KdJJ=^|gGP6bW>3K;Ar3PEcuD=@C z5N@OKa!UU8JhEIyH(5bADwH0+I8_!g-h`~q5q za!4slPb9SU27T&<7G*k=~tEFzSm<>3u0}2DyE$ z*J-h1=!FR17E!YSB1PZb%HVWnn;$Qza+1b&s4yM;m-fNc45Gr`ETdFPTXrHhei|xietFQc93Pc#I>g$36>;Q9ywW!D#0p^g5l3y z-&HYyFchIwW1uQcV)=u z7{rh(+e+^+{>0rC+B1|I3Noo>%urP~>3X5`d^At$&`} z_zgR46HJATT?76U;>p|4^l56YfVdV`tas^?hBaz2w^XNQHGs^JNZVd?WS%zdJ699N z0s(OgKWc~ zKC{=QD!&X|CIv)BRaoeH3|=hoK@?GrFd(=7(Xt3>g~QHyn%{l=Z(Uoba{&(JnL%EU zA$Fa3ExLOJ`*o#!kJt|*$+{6VLghjMSvYq6i=B^UNy!sIm_*khb_+Y(aI`uNKSNk- zCu3tWJD>Ep)M|C?V zXa;xQ7qS&4;=ZU;kt^7G(0wXY3xmE;6~9yx1GS&uSE4Xk4a0_u?QX5;J=*@(VuU?; zK`YkP%s(Gw?a$rX8z#a5KoPwfW!U11a^3Gymw)D?oFU~Fe&T6gpyV*F!KOsCZyu8h zd>-l(W5x6#WLb&&+5_2fev>L~9IFBr#F^~*hzA6`66ksFbLf>F!pPLr8Tlz9poWS^ z09qi-6&n<~g5fTv$y79%e_-k%A_f60M+~V-!uT`rM zz!A<`riQ0izP{O}e@(%Q5(v-2@O27o$`q#35!XpCo&NQnEU*4@ zMY$_JF`u?8aN3WSkg@}}@%MTJtBhvy?^vI1^K9d`Wsg_4sVSY0<(KIqP^c8`Cdb(= z9r~BddljDl&V6!5T=?_ zr=cl~ij;b%aueLE{q|@?Fx@s~l$!~}xfN5d`VluP&n3FSa`{+I8#yu>|nRjvdKOt#=_eQz4#I^8A_LVa^O_5o^FhhRAtt>E7$r8u3GYuHVuT+s~>nq!0BIccV5g=k@NQOyU0TfZ&u z{`VYE{2Bz_)uBzDouy?4GH`o8$YKEdzh#j{mtW>JT~h-!+-X8+I)LHZ1t;1LddvdvWKcY^Z%hqY*n^4OsjT?Gjhn#nS0~Rt(%%uy}IY-#fHs z)f1&R>gf0eWY!+B?`P^f{!1XsvX}_?WO>Db%f@cu08oskYgYQS;^|K@znQ-eXtq3= z7Nw(lY1VA10tRH_KWx0l^vRrAZ(<5Zh16%29~eGSFc&Y}{&PkvRT>CdKayg{J4)DG zK~`#0PbZPM^~h_+5Q#flufq_mEy_Gm!qyIEFfB36=1pZx_ugBkm@XXkmbJsxx4(2w z&T*SPR0-pDzKmw1uM?+Hi|Gdo3;@@RihX|wavwbWGE0>9K*q6v_wtdSB=EC1TfDHr z$g1N2&KbmO0A%OIP9k&ANsKv8-P-5F{Yh@A>3Bl9Ew%z-^{k0zh-8rxQ#di)!Vv=w z##~Hzs;ehoV9~164+`5rv2d;&)Rno6TNuLGw|_nqndU?p5fr&Sg|>6Rh9%FfhmSZU zqk|55!z#^J?&e@DXp^lpIG5E5DG+qycr&SMv5089<)uKVpu)S}qSqfWTS!vxYKg!7 zboqzF;wG$a33{n=nWA)#323u)`^W{K!hw-D|% z3LO$fNG6AvEJ5Dif$DCg)fkfoC(U=PUkqzJPSbd6r>8hfX7|?AAPC`9+`Ak8f(gke zw%if&Sl#GBvq7bpn^%Q_hVB>TI-aMBK%fS{_tK#Ktj4($ zi%St8K1GF-n*8(m^3wfgy6sSb?r8RA8S5Tk3C;oE(ui(LPJh`BI_PAfPYJ!uWkmq7 z41e06fz8GV$@or(dFX5-bSH6uFRAz?lNHC8*b8E^|9CoSajq2O40tK9e>@I_c_pDNcM~w|nEC&1x zpk>bF`_04mW-bKT&^@zux?oZ}sE4CGtLBeC3;x{&${#=juAj?2Of>P7*QW5dk6qi) z46^2Zrz=#ZmHkTL1-z8q)hF8J9w%AZHbP1!V2~sNM0K$B1#(0d?&(oxY9tXay_2`{ zWW8P>=<>@_%QH3WaXSTtLf7t;{uGZizUGlD@P{qFRZnUkFG1#aN%xDvsctWwg69o1 zS0huCA>A*@?M{>j1OSs7U_mFQ?}i14B5U|lh~m>|LTI__kRUyg0xf4Aj@1J!h*$U< z4qWn!S5J^tJSizVYV_!VL;7aX%0;MUSU4`L0eR8DS@~d*S`6c*LOS%kWN6(%*9kI1 zjMvtKILT+==P$t-j@SDAoSEyHp??hc3e-I+vEdu9SnPHIL8Fy;6k?Q+1U@F3KebU@ zxvhwZm*gIS+wUoIvAi6>ORG_3Pp?X*qBIQmc8eTNajk8-IB_s8mE)(i3w4#LaVWyF zZHV%4S;4o{YCYy`kuaAy2Dkh!C+qw=aSLS%N*VkIz8c&3gU2Y(gPY7^(Kr1JU`a1}N=pSnbOHc+Rg>&CkG z{1%+kFG&ebqWpctVLmvI2g zSMenn5jl*}>D+jBI6(y0ETZ&i_j5Lu4g0DP%qj`N$?&siIX5PCSvV}kod6;=b~9F} ze!x8(cbvpP8N>~P)P0F!Y9PI#{76dQqwnQ{=B^k(uEAXu!N$Y2OEVnoI#2oB7^<4z z$vehh6E;JCK7W3RMmKV*belLQmo?}K|NFaW6KdU}QDw>~#=#7M9rPyp!t2tU$>g{< zv}0pJ^^o||yUN`oxvefhiXi>>zX)Jj<@KkHu}D*jDa#KxE}pv#rKrIWGX4dp%mG1KBH>$?c0Rk0 z5*;U&@j5GM)@3I5Nu|Yjl1>1`RCS<$S*wgp|Ne&2W19f?IuiXC8`PZFdKwh=Mss(pPHH*UA=3hJqS$mLEfr zUCKE!=3Tal)LFJYr?lQN&@~MLuXcS+)XY;Lw#zwoMWiU1(T1;;S)wo@D@sc*@W093uw;7Pp zE72gcJ~=6CZJlu>n1swS8USen(cf}X%47_97-f+R>W1Rsn^5X~;!~4SPBw_9BQS)t z=d7qx|Lx@D6}dL|VMHK5^XNYlBb_1RP7k$}hCFjYV zs#Xa;ihDU*e+?D>6LvS~JnB|tj1*2)b5kG!pSCOR8OPBXlj+s8OOkL4Fp1k&pzAcQ zCbZY~@Yabjt4B>eY1nh(h)SbL7lbeDQrjnCf@j~tH}bKZ43gAWxw-HESrcOx;}y!Q zwMZ+(_AqYYQoaKEgo3o3xI#bLUy#!V?bnR;$EV0kMNTHG8n$T{LqH!A60wn(TDo6v zDO{5-)cf~)$pN5FS3SUvT&}YvlI$X&j&4yL{UeKbaGi$YBa34wiufw=VKf+0-Dgpz zc-+d2OL2Sr!BF);IRfhBKU7RnR2z?Z@=+F(LYPI%lG@3vs|J9OM1DB(C_ zbkWa!;Ga}^LYZ0mIc=R|)~S@X-*l z(KCj33y-CYU!Ri^68P*7%vQIP0rosxJ%bKbFR3AY04&g=+;9XG;x4R29}J&O?GM%+ zkx580nlQ3AwVePFn{|TM2S{-N3ThZ^ANvyBg994n9#9HFMBg6r1h#hy5XFsbosJ0f z{fEtc8L{2ylMrelSiY_$NeF=Yy6>QLLN=GRp!7dhDk%klBF_JAj(E3O{di*|+PYcL zCkkIm6vyTypl7+m^B|V}Kg}J|7JS?obOZh6`^(VsHnIow)RR5*q00*}0Z^k3rVx7i z3vCgEpZ+E~zcRuTEm{a9Edh)6Zz;)r19?l#eKo-rU!R*a3s7&4TMy_Y&m}q*Zq}2-cR69FOjUo9BWoA{KKI2z_8VCIglT zG|}>k-iJdFG4g;QvLq3&9Xi0SKc6mzk4EY)#|&e3Oj_BpMcvl0m2R=!ro(we~+ z{cG1Y8qvmS-dj0X)brf8>=Y3s4@_Wf_KQ~Wvx1L6_yThcXjyF;Hv^#Y3wlUMK*g6A zWSQ1`FLvZKfKnpCb5gyg9lN#I#j}*ml&?(_dd6M^&Oe9WU)!z=rq>gx`_;$`PNa4( z6RjP!#lET1)jpV%mR>p{v=kyrO_H$~KP^-Y5QQDGJ~SjZOFIqc$+nSD<{p|_sn+)5z+!744s>1~aeN0( zo$rayg)_(v83;HVeIjR~(}2Hk@K>Q0XI5R-In)272}`_bZ)s4<<*LQIonOZaeZb>= zUZR@Y*ZFFQA4QG6PW#hkb$8TS{n~fKfuSFaH_iSJg-nE;v{ZRtW+KAiAZAkX9`9{a zXu~A|lP5gRulGC-G>%NUMSH;>j3i(@7yK?7vR`p9ph16;Cj1w^jXk)^Q8UnXqn(L5 z5aY_LxEOO5=O?7VNLPX~5Ss3cSDRwCG7|xe;=zBZO7NfGlE(Di=R`A20=+$kawgfCD=$pkBviB-sUH>x!MxSr-5va}-sj zZN%3=8Vi#LEgvxb6e2K}uhC0-j(Eb*_ZZ>iGeGxFY);m=LXx3v4zmVL%J-L766Zsu zBl=rQNR@Wovq+*~!5($)rD+eJW>QJ5HvHDGO5jOHVG zUEQz{^^agnk!0m}pnJ{`6cBqtDt7?;T<+7SIri(pma9vO#OM9uSk4JWZsKY|2=F zgbb?hX`WOj#v_{l25qvMhBYA)TsGh!e=StCxY~M2Z?3^2V%8*g-rwDaX7(QPXx3Jj8|rd+ z?e|Jr`}+RR7v7n&IgK@WI_6G4jiZIl+EM)fr@s)J$V*?8=!y&nC5#5R9jY<2)2hCj!DyR-bKZ%m5C8ag&p zk?7>uZz>VL=m9wHn6tdUZGEDgrs+M#WQkK!s54nTLWM~AA>_1-n=cnNPhFOnkZR1~ zvv^8Gj5BSj=oMB414muy%}CaGvv?egUkjWfKzHEWNl}xQ%d~#5c^@?7y#7Us9JE6u zlb2|5Elme~&EB!}7J%MY)Z7lSsL$6Aq^}^?E82alVvbbhcUP2PL`Z&-?5Wg`G0+MO z%uDt0!gmDwM}byyI(?C>vNBJe@*eep3{L^Ewg)4!V>upQkd}UG<6KrpkwmDFhUoYi zmQ+!8Ntv4L5%L8{RVdoaq81Gv|CKl5KQmb|?$LXlH|ozJ#&E9`v~VfOtTPUB)Y<*` zVVEX-qJDXM>2mdD5zK8^gW%$%YJLN<6lcW8wl%bwRI4KJLJL8h0ypQ=`n3MSsDEWM zUnav=WkE$b_r2k}WfND`9nn6`i#mP-N$C6K9C=w3Z%qBHj$596XsCb>Q43mAmu6q` zLkQv*oJm3XmOE3A#BhwsE7WK28|OQI0fuR=tE0twy~slP6cpf39&QE>p*zidbgNr4 z@=3}H`gb3L5#fEwn>1VsqxU#(5f|Nf8GW`rl)sMY_naH&_+U9hta(F5(tkKZLaCc)751BI4 z9WN&rz%%^879RUMlyN|wZjkVS`IZ#uR=cPGy}!>iQJgyjm{g~z@X7ZC=#K3t7Vn!w z2-Qe;^}v4v`n-1g1~Iw0y28uH+k@=rV*xQGLmT{!+GCS!3GA3_Y>!q9M14%`?QfOs zbLM6`TC2Ju?z^+zT*Vq8+*QaS;g~V8(7F@Tf`BI;??%;ui;wB%T6Ml|7t~jh>|?>W z>U-3p3f|S9>VT&6OR8mUqV6Iu$u8%5rm%0vCf&LFeCV3&)=rn7bE0uye)I%YiUP9=xPjE5BfOci$8qj|)^G6t zQ`h=?52VXp-)gXCDLF&1A}m$0W8|CQtQ+cot`F>ydxQBWX^ll!v_RdSWLCAQbkPmL zgnvslBcX)~($C(D&Pv;vr~NeROI5q(hJ3QtGS z!4;|pXZW)T&B<2$p4v}$ABZH|&xav|Xl-=V5D3;wVR@iKUQ9|qTp}hyih1|F5x@4J zq`4`KkkY<+tLyjmTbC>LI`6)LFDAhlCaTOEhzC~0alKWd6xF)#C1FkTls&E_prK#^BJ6)9yTcp zB#+ZD4MEsWn!yMiF28K&@^1ySqiUhs(ltkZ$%n$O=$0|ryh35`bq!>I-_KYH z)~2Aa21pI$i!a6y6pAWB*A%C?=$Cij`0{KyF?#Oym0g$RzpD$gNS@^% zMpwROT}%~OnomuJ5Nfi8;wsnw!Q&lfRgE9KCj37U)lXzSJS31mwp3QT%CPwncRPs^ zJvyB3>%l4&EJ}ew$JcX?Xm{fAEa2=HtB`}1@=GmrSUGN7$ykr=OnsEL)i3futO{@)&eC?bmDQ)Dp_HR~babwE}lsK(2j} zF_ckrj6F7A;eEJD9#R&fmJ(O=E(cbpdN_f*T1=t`pLh`UkmJ0-P}~geCKgdsp!s$z z?QvDgaH|qCk4h}13$}DYpDw*PDcfwURfI&rMP^u$fZkcvV$0aP&95k>?3BhRgkBs^de16d9EVe%kq9>j(<7ib@YSTGzzo7Zvwn4scZ@f} z@u%nVAM*0<-d*JeL%3Jw9t;7XB-bDK!mp-1W_M^SpT=VwL+=a7&VW48mb^DjWf+z> zBj+rzO-n{0kCaU9GI>C)Dd({PtI69zEaC?!^H>^96aiQMXb*N68AdmX!(~GrWuKlK{F0NmpAmkilyGOXx zeWlOk2rp&$&!M!kL9T<(eD>bu0o}VDF&GghGvTTs{c}!wbOLnN!MnAHSzxBQy+hGS)?pt(Drx ztZRoZlK<}84ga1cdv-4EaCC)M_@MXRaO2k5uj4*%1ev)NsTp1!W&h0jf(1QhBaC8h zd&lG1YV_c7R($gEmPSQnj$;HfqM&Bnp&UC89oDd9y33z1?JazmvGAm#K?(uj3lXd~ zF_np&fX-61Rro^G84q`JN_Jt*{yHHC;ZYb>ptvMuZY6nR>5T%?tQ{c4_YkhUubJiY z)|v?N*XfJsC-07yZ%1J$64Bl4gJo>$CE+45i5t8C%M}&t1LZtnj9FRBZYMaIhYbb*6U3kUi4uw^7Ae*Tx*`e?Jnx3mBJpb zH|Bu!T+h?VK(O>tI;9P0D16KaImRq}t`H#(18JP>D1=4BT#jY%&~a&wpV}1^c7QIJ zn?8FHtsCe^(6u_yrkuL20dP{O)|EYP|4oK=D;Hqv?}$7SHX2QTVZAE55=CR+qp|#(u^2Es={qZGG=%l})FGNSYZ&!D}00wBqtfVl*lMFM9y5 zBhJEFv|+{-I+6>&v~zd0bB;S*QH-6#8$Z=LID<(eel9-jvtc(`y^~rO{-lPjEqR3wYEf1Xr z+p>QvUa<}017!%D;t<)o$-`lm{bnU_sQ{wF&rj5RRD)+g8A(}%I~XWf-86>uQu*G^ zkFIk#@1ENJ4%H;+q!Qen@Pkj+tVM-8J^sa2i`1;Z!2rGi(j^udZ~`B*SNMlyagX5P zDWJ>fir(XNY@cv;)oyFUc(9SYSN^gtNFmqsMQJ<8Fuu}oz-iecbdm2N2Jo!BpL)N1MBfnVtvQhj4`InRJ9LJRYH5CHHnp_%EP8l-h_t{CqM-JXCVn z-tLgs$)jnT>{gCA0xqJKnErFmU3=CeTqcl*kS=M9fHTQ;nIocM-r)GlHuaLWxx$SQ zoG2pJdji-qV=YjLRvll!|AFIFYohffMSQ^T+9c05ihI0dc(3>WhT!~ zuUG$L+}5l}o-dW6pypF%P3}o+V>8hL4^i;Z8anLdrjjO8%ZOZ=vKZf zele7@MTj+?PQIPoN3^IOxJqUuQ%!~JF}y49_dL>=xNE~-ox8+z+9~6uZJz)Mbuei2 zblJp``nBD6kC1MabRAPm34H1tQsIeDd@2L9pbUh*+%AMd2lI5N3O09aM}7|}h>!W; z4$pJhu1bhXg5e;jo3K}#dCJ=vgJJ|RLKEJ&F1VoEnOe&4cQnACOO75P2@dM^r`UOP zXBt|Zk`A5l#XyZ{rZX`Vvn)l)72B-&wz~M@3*0ie#0O!IikyU2h0>XoL?8#cDG%T` zhU2e(ZP;0VeMiQl0{8w2pVkRz%1?t#FTf#Y#}T$7&B9Z^;jZrbL_wW&q0P90+Rb8} zdl*o@C$F8vqYGI@_=@%`z*+Y)7}!y3-i>9IdKT@7279x_yCTSx{+!6TSy+6Ss2J0SUzB2cvN~wyqxK8--wl@Zg9NN}|;0<8u386D&Zah9Q-vx9DIw+eo_&i!;08Zy;}9re*E% zN%gsi8YI2uEbPB04cuWg@qQDVy5msSzCEED#sERUX`f?eJefyhw32-o%=`6GSD3X8 zD8x5ixKeieGK9r+{gJLH>$6F_1(vc1gWl%@R|d?bVQBy*4EM^Vr$9c9@))eRR4Q<{7*B_eH{)7NtVK?SvB-zQF)Bh8<@%c9^Vo|lt!J-jS>?11L1 z_{Q&%V(=LmT}XKb4t2DTG(cH7(W@6yO^%^BGffeTXN%$+Ay$)YHv?mzM9xMXgI;&t z5kcP>paP5qturNJRv;Y6wkM3A69)8QROpweBXxX)iL2!w7nmK(GdM~=&lM924+I); zc!J*^1`}tS?TNYCVb}jBsq;3&D8&KRAiDS%)7+xY!wlVUiz5Xo=N}MiTXvJYz9hw@ zduOD2G;TzpqV5x4qk;R#Gb`FcO?&-8&GmQMz+<_70}esJc^%*7)n)AMarW6&_L2}u zanf=A+^5GHilhe8T*JMm1m!jD{A9+DLT7t>_lzza2|q_cl%CU`9PlE^-urkMGit~( zVha&Ks=cGioJkt@vK<^sVU3>S8{@FL4wZ)zPU6thSdqtjqV$wNn4pa@)UT(Y47%Jn zcOUIN(8_6W4UNu~znMFi8Yk6FAirs9c}9zBplpVkLw={az zBirS+UGN2}hMhx4;v^e2#bOS0vB9+U~U9ulX#jqHnxN*HGe!Or`!-KuAnmjgC3$hz<0t zBO4>G_oR!vDIy&_gn;e|)eDJGsTo;@SS*<$*{flDZ^x+@+@nLVPf=y8STK6zx*q6M z%qF_OMW0wBuh_rEDa}Y^FjX`sM5xK}4B}}-9Uzj#(seWN81X)-3PP>9IvB+|I=;~v z_w5ItTLp<@f{cE=8RpS^;l58FTk-T?P~I)cN#TI;(uk;SjPuYLujByk^+JGpcD{q| z#i|KHpiQ2f%%)}huJAd4?;KN+(H&W~v~srb&FdUb+PCS`fPcY`oFmyHyk!>75NmTS zK+BlhwsJp=cejX!v`X=jhmXX`r0FKngDeI zl^!;bd&*QZts-leAn=O+Z^V8+u+UDJNple-7!PSq{8tFgty&^6$6-K)J1-5bYn!1< zfrqp8QRM-Up|wp8P*WMAd}y0N48E(P4a#zvYle@Y2?({wLK<1eNdx|LeL(sv#4GBG z)H3VvdY!-EwuNavJ=3|U4)oGz5;;Ol5M~_D&R5~_Zt-_2AV19sx^{gAookm|^nh?X znrPm>&KIIR!yFGuwY>z?CUMfk6i|x59g87Cb>K`L{BsnqCN#pboIm`ysfjf`84;(e zV;J7iE}m=|R1xJM4y*Y)Fr(0` zLf%=juXTsx42m5{eNDzd0qU&}>T}Y2Cn#q^;x#Gj6WL{mLIefVWE#n^U=?kg%rSW0 z1abjON5P=wck=oXYCISaD)Mk(Y=iqpq9rzR&gkSa)Gk2|LrAabP*Ln$7oZ=`eM|pA z#gRtU&z%&q7W&269}mbnmbP$MVdT%-{x^4xYtUuSAM77u0pQR}ZjtB0ES3_<4u`Mr z&M-|a)A{`U)E z(g&9Zm7JDoYYN-)l&XuMM2v40L9r~=iL7C~O_mH{!sn^v_8*^3N{#YKM+zPVVl5F> z#}bLn+L<(*Jr&wu2^j8zv7FbbBz3ZuqIJrJ3QcVwCJlyiPXukpc4Y587)HK=8vz@O zR9zeO+4&kc?zpwmroHn$jDa|8#clJ%&xG__as&f>|^YcD}Pmc81VKwLB zS3HxXKbAjp@bju;Y2z2s_dTNWN$k;}x#l)M|j@ z!-)uRbB+l2sr^_N&g&0Y(nMJZ$8qr7AAn~KT&UC_EJIMr55}Se=Xb4il`j{OIUE-K z5H^Z(2u~jJK84mz2q^lj;3YUH7I0l@0_Fo24qt$~u<~1DygvQ7_F!m-NUomP!dX@} zSmOexY(*vaQ5`wPRe$)bVT}D?VYj{nL zUGC{MM)`eprv%X{!Obzn6Z5**5=%}5@1zz_ zmTZg;sJZoygM2AiP^6S*?rvjM#K1~v(CrFH0^5HMgL>r_{AyvRn`%vNV+ANO)z-vnl7|vuJM>&ZI(KI) zu^SJM#%i}OTJwsnElj8lJmhF!#S&vSU7YQ$h8}R*Hthx&nPgE77@9rVXEJ(aPzmK5 zvkqjq(NU8!3n-K*s46!L^q4#v1_FTLD+edr4FvGu1I}eSyQLhFQ!+WilsH)3(BD;t;Or{ z`{$`NnT0RH3^W6%ic|&J!g?GMJGwma_Qg(w-Pg-q*j)%l^xg3sRu^!LZBLpmC{5+= zr=I~^+WeV66yNlo;I*>}VUk`g0qe|~_~8T^6{RgE%xQ+Xj6j!)!xJ0mZnRiJoL3xQ_jR^w?o{89*MI)Pc;gX09` zO{3q|aOc?FDc|rbt*?LmSXBRojt^PMIwzNMroQ|VdLaR@EyyP;b^5v1+ei!G7-lrW zxId^|tO&^Z+xlz{jdC+do%w;S2a#KtdMSLt&dTTp;|&aYY{pP{m^^YyZAhP5ywr)< zW|>(X77RCp%29RNw!YI2zF{OT+~o`!PLAhw=S4Ym#ix6RjYjLHfOd+R{9x`~1s1Y9 zBAZ-TnmhsA(RhvJN>3h!t6sZ0e{`&j0cd6Iln5ak0EWLG<&@17P##xcw!-7=%TdPM z1w6kO1X-77$9uV)6NWio=c-5t-pIqf^FE96vw>|=xIJI! z+svR)uGI9DHg0bvbA!~lt`nhIfM6E^R)5ELt7V9tC(h)*D9juBVnR54LbJY2$F702 z7efF0l6`Z5)~db}Sz;-FOo*f1shW!=NzEOxG%5FyqBR44ln)60*;%LP7;@F_cc!r+j4#Q$k_&1K3S)CLH&A*>T{d+(_I!s9R`xcJ zh^X))c4Zn@BA4C$mXKP&+v2|JZ{jlC@Cl2D-aGw*7U;F)3GU2(xG1-7htM;(R-n-j z2yqIBS0CEWSUn1ek|_bHZ|Tn`B1s*taYjE2i>Rf0-Bo>*uU<1hkLl}}zXc3RvOx@;c}EWF*FC)+ot(hWm;+9jdaY7-2=jZbGIT`9GH6*d~cz!=^2HAXB* z0T#|)2>o})uJJF9%;X$eNM--R2{QDC_%?+vnNImu5fKeP5^CLc4X;=L210mu7Kw|K~4=k!iw@6 z{(K7tpc-icVJbitEr7&$9OQghv{z>51i~Xvag}DKPPV|y+KlEaDdZU_ zmC?fQE?W65mNuKk0qn%(I7`ITe#MbEWRx$0NHkAm@KME+2+K2yE0=NrGzSePfa*AT zC=b?k4MmJ)@&uPX@$5ZQS!PV^u8M?pyW-f@d6OWyXeKewSaRI&pYxriJ#=-3sS+uD zy^5vul(Qp^XBUmeHl0>XBnHanD5Za-5U3ARXG=Z>T9qbciE|kUq>P)S>}`77qB=EH zSMk11lE2aEWUkyFJ{{tcSSy=0MkPP--w-^Is%?OQ_A`=`n4|RE5~3+-c0R%Z|H>IF zTQ`n?t(u0lbGm@E^$1Pvb?%>w(5+rl9|*{*gdPOmKE6O3;|)<-77;dbR0A5OeN9n} z|ME=bal4HI)WCy$BnI~3faVKCYF$I2raaAGlLJL3nZHY)=86i+*JaSrcvrU}=q897 zUkA>pl*b&idvl@rG~d9M;+bVb1S0h_WO+&}DdG(jQ)R zFikV%Z;Q1SpO@Kk|Jp{0*s%CeQ;s8b?{x_g*wn}oHjbr*dPEhJaXLBb+)Q@Y2l(%j z)PCem-MBu76#<|+&mb%);eevm74gXNOZ8y@774KoWb}yCvlEQk4hKBQrcAJ8^q$F(MA~$_n zg1A9#S2U_jQMI~wQ{A#whT2{J?}s3S-tFB(m4!w~wvDPPQ6xjt7_qj8EfKgmq-RuR zdG~{Zya`%8AWfenF}e%0MB|Ck%KVkb&`u7>!<)tH*RZPSVviC<@D!CFoK|icZ)g$; zFantI-fR75(Cf`vRkkm=U>%5zkWn;{_MS(3Bj^rr17JBk05x#1YsucaLG7Jfj`equ z9#OGQ@%SZlg)1;D#zTczv9#F%2_@seSH}RG^E9i7%U>FJcm1E3Rnxld42iVO>!EqL ziR@B)z8%~aJ(QpJU&N{k-G|V}icTyrdkfW|FUjeCJahzDHQ{9^v~4#G5~;BonYSaT z>m#k*9wzg{oW1eg>DkcvqulwqgUJs$RWhVVqo$ASShdx>Q&v&>>&Psnd#W=JIJUW zk2Turd#wP;64NN+7aT6dK|sfhs9P*6i>;V~!zpCeG;;X5fmvRR!fgxf3Y#ejNl4@A zl{N@x4$?s)AMu4@B_Wy+bDb*IJ0Ugz`_!&Yey&wXLu3w(mdN68VtD(`x{P#QjQXO1 zYjE+ugQ)+y0F#k?8_lc)+ikY^5KuFvS~2F5kWRzh4SIB4xaldc|0_IQ*Ceq|^SNM{ z&d*K=A#oZM4VZ=@=L>?D8-_xZCN|rID(O1;*dObhH8}EwlSGUKba`Ey-zwWy!a6pjWM6OoszP=qJVK$4HMlB84GfT`IvU@Pu zesF~)XPpA1Gpkdl<(qmAj|VW!LY4^?(6u&~9~2N7gF+y2n6gNv>yd5Z0I@=A{wqm9 z-PR##xrTCZBbSQ?-teJoclb@ns_{k6=U#Ykz>Ws=lLHM;Sc<^H4>3j1_6tJ?HhFe!GJtUg~3xMONcDEJmfG~`m^d`WkSGBSMOSV z)As!31yJ+i+m~Q>emSy9#;eVuh*oZvg(~a|0ROGkbTx!5o!o0|_|L!uCwoK$yH!fO z;H>^Mi?MW*Rq=gG!lFv+k>k{4(USH!a#v^Uvce%jLCT}eT!oQu6LO5~5=-ag36Edx zy2n2|AGW`5~vE2D;scJwhi z9rK(b=He~jmH+gcvsO7-?Pz?!Q#lPleo8v{PYnO)>j&G*a`2Hm(8EdVXN5F*M`B`Y zh&oDS=}cJoOc?6t!Qi<=jQZD~YgO9U_V0*G$#K3LIk<#u$#uZ{bPd(!e)(sTjt9_a zkvo1Sl)E_6W2hEtaTi63=XTV6=>EJKgj#W=uf5tT7QYAk$~;Ov0AFLcspBuD7XYjz zekFdXb>4(hYH(!Rxz1VE0GFNQC6JfY43G2K-;PO@PC<2NuGR(a+cucK!VB0d#mGMtd8lg6lbx%u%=P+M( z$_-b}PNe`HR-u%AZ;nDa(5w!QDeHm5-6=CSVHj(Ky}A5S0YL}-5kNe$`dgzLR*{J? za%e7kM;{fa)aTs&&@$A&@-P;j7znx?O?+4dVKICTn%pbIrh|xPweM zd>MgriF&IBS$33x`Mt6#IH`ZoNE{gsa_|B049UCNC9+pj%4`KeHp>ZCry3XymzA}S z+VqApaL6`ln-a1A-eNz%1Zfju9F}ISMg;U^#Q&?;C$4lamZ|)43 zgzcj|m&;f9qI^yqY`&u|yrpnrwjKz^G$a>F7I0E~+OK~i%F!Vad-yZgTl(`M{4w}? zcqiIyISohPq<&7d3P6?EdnO4##k#+TB=<)0H1MQPdaWEhAXAvrI?|SB$<5Z2E)nmh zp+UkCIqypAU|*eqrfovG+i;?ipbOsx6I1vOtNq)EZqzJgh)G<>DjK%wzRvhP7ED5r zdP4nW)cv^{p+ask3ycD;{7WVqf6tU1Lj$k@^%oSdrOjs(0+;}3w~!Z_Ia&_JZ8vu+ zhul@dBjQHndggihW4yc;RVI9s0E)irR{p;~cMFR~ z2ap*4CD9)JFIvrVDi~7-i&?qzBTNg7`ySGVK>GAXL<;YSKZq}!p9|S8SU)m)QxuDy4|2KI_Ul9K6sjqNTyQws)*gf`Lth)Nw=c5Jo3K^dY zLuYYb4v#pjd^w?rX~y^m2%+DA501z_soC~R(m9&Rwt#&e_oPplduL#L{S1B%w68}t z2TxQC;qUS5jJvFWTjO#ShW_c^X`a(yk8HS z$oV0;p!k*)E3C`FCwXv0ui^7-_^ib0>ZT(Q*zo$lx=IgX!^zEp?i?vCot!Z0ML(7X|h;fJw`rh2AEX<@Bv}drE;}@dc8ay4dqP zAHh3d%9+o11=9Q+sUv5JLy0AjQ6o*6BA#%(G*Hv)9O-a^+voL(BY9rym%QD7@mB@`+HZ)K`+trl4@O#fIj>mek?bo)BkH5+__>b&`=Pv|F}XlZ8?SX zoI=MOm6+ugs3?I}p1u0U^0<4?oQOmJ=QtE9wWI=ynX(0;1g2#!v8bncc9vHD6uPa< z`D6npbvMA1iiu{p-lETtjZw~1cOXi54VUR~ zgpb>^{h|nH-&z<_9}!e?lN!WB<7^m%>Kn2GL|#-=u=8Foe#bwJaZs&CCPaSb+a_NM zUlt6SdVBofcFzhP!cKPq4`S%5rNDC>jzYqUl~2ybU#YGR)ErVsojhntZCioj@orvl zY=u@-@)Z2eOi@~eSu2X4I7ykXm=L<3GIs?2fe3_`1)F80SWoPRiuN)gaACa{y7~BT zy7AP^e@mr`4QIw5iab&SX!(aI#bW9I#>bCi#G1T9LpYr!jFIVp>JM7R)%@JrZ3B(- z;AuOUx1v_{A|Wj5mx8x|SB!e0PZ$TZ{u>I=H)g|KcCKJUu{UqGh&QG7+E5 z3|+I$?u;y*dggHAu}02yx%R=CY*a>s^L?NkZ;%&Atv{-A>4oz6Y$Pp^0p)%^)de`hj8~Shr zjS=^K*>T?*+}+YEzK^TSBu(cd>t7e2dUvyHbs06}lQm^E^4Vd)a7Mu>`Imqp_e*Nj;sm@M%vykQ)I0hJH`3Zl>BhBd zM-bJOf_AA1?MSzbC@nI?96|%YQpZ=p^Yz+8>&HeMa`)zoHqYa>q7#y(nOhSvU^MwS zxb51i#=YqwpB_=~u=7q&^1r^gN<37BZ z2fClxHB_J1Y?@+2=K0ayD=r`OYLlM|YJj}sBiay)pfiD8b@-`vcD|B3B^7#^7$OWR z`L*Lx>VYd(!w}x&dv<_`56cz$a?vmBmw1(eNq~Bm{9j-pQUo;SWuIq zOl{WiOA;2`$Yr^svRh0uVye#hq-8b6*I}?Ji5+YNtsk`M5og!FeoZ3ynfnsirzhBkj7*0&i=#m)me%YwBuPwPU`V(5${k(JzzGIz&rES~ zp(kywLhvt#O@l;|!Ob4mlp=m56LeAVO&nuYF0G;OGq7*Xm4}XavQxr-DeJ6YBpl0Z zktvf>^wT#Sza~i8o`2I?&x#qk`2DH@*6j-Tn~IS&2GIia%*qZ&n%?%Qsjh_Wxpoc} zp`ZnNKLvgPMenP3SdY`j?O`o{lV>k%~)-;9REJ#vi+`4BQw0u&e0Ye(a zAe|?;&Uib#gf#};p0gQ{?BR*(d%_w; zseX1%wofMcju}B=XI6BE*@C ze{`4#-WB*mU)sB0eQt4+M;CaFR^}=>x8;i{YacYq_$)7w5m~Vjbh7bmL2aYZl;1dI z)l3|vvozcuhowJ?LA{lP1ue)td&PZ zp?+#BLv7-bue$qkdh&xiY5ZspIfl)+8r?~ve*5)%Xp5nNr+i9w6-j!ZGms@YgmVll ztY7=OZxC$H3BQ4h?{eD$VvAIl;8gitRC;by%S7A*b$#7ne#bzZ9pE7u48a9LSfk8# z#>!qrPv=d*5X8p+1`vKF%$VV@Th1IeV9i`ER!Ufy&M~f!NENfL>7FTJ zBe&)=D;T_~X3BfFS~eY#FOWQREe+ac1~!1&pXa=-E|TaTbw5tiq4*Z3CNj%HENpvb zmg7~g0Lfec&+~ZhQV@Gk7)hPu;_bzU-BEq2=)x@LM@&Cct2XuHum|D1A1~5niPs%)ctn>mM9p%vL<637@aNyl6d zlX)qLQs6obr9stu+D@@bjpcqJ6dx9iaxJzzJRuJ3XXh+j2um22*nPq^Ec7^=9>CKn z1n~$BukUje@4Mar)J|)8WPa(*~sv*$9)M(`FvtX+GXO73v7|f z*5fgzME35)O#;Gu=`wE$n`poaYa|&4Cq~1vGII-sR8@q`R0{2$%&L5N*-~kEuifkv zc_z9xz?T1Dw4JZ=$=fGpgSOOjb86NX~98m&xazIc;=R^t0>n zqY8FBiY)h;7)?xAAq^%;1=p3>EF*7^foR!{=$&41Jg;2A*0YqatROI7{mwb^J)K*y zxZg|C;7P__n`;#(RGJo4u*NG&4y>Mi1u%^-LK`Yx>CSgu`<3|Vq9Oa)t+*K#-9xhz zOq_ADX}_81OKC;Ujny!*AZ$2yEv28f3LnS+P@rBJS^d-eyQ|^+l=3%KS0?=#4`#62#>V_}9L$v64W1B+8 zNh3uN;++^z81Vj7GjNHe2qgeKp zkIZZ(B)84OS(A=$qF4un2)93Q-ENiscw{cEJ9@SQiu#S*XmxD(RI&FO1|B>*?cIMC zSdwA#f`teWRj#fn4189Fw763&Vm$tL9r-w`ls9eq=vwm>tQ8*{ z2s+$c^S9PCXhxgcO2|r53mvziUY@|rC0WKM0LE$4(fZq>3bx_Kumf9A%uSyi{mZR= zG_CT@;Pb~+j<4(@DFhm?{jwO8Uc+kc|A#gRwWEJvuqkCG5ozQpTYlfoLg{TSp(VLC9iTGHFVIhiNxtArx;H$NbiB|>;|H z_%S}nC|jaCx0#NA!5d*p2V zEjaMOV@O`FAVN8pd^=P-Pf&X+z&eD?WGH5)ah4XzWPQ2_%B1+6YW8xTV&b%sXIRM9 zsOL!d-1&YB+uW$er~mnE{_?O!4rd$f6t!rV9$03b69Ig3eAk|RqziDb3oSjhJ22a> zeaEK-G)BC@`oDW%4O_>dE56wBI&NVl@aWGl>Uc~fxI>OLLM#-1gEfqqJ@-P_G>3aQ zGJi^xW5oz}jy+Way_6!1dF<>;JMDP^$yg0SjKPvNNAT*uoW@PUM{C0u!bPDL{?&M>W$eUfL4c(LR4L$4W4lqT-i$$xv`tNBFZy_cXcSa%d8xIT z{3-x17Vf}uKAR!Su|=Leo<)und~M*R6}Cwl66Rey(!%>*w`Uz1;496gpM3xra^ zbj#sxi$&_N1fH*@iRIA!voS9qe;>m7n=6=H5--YH^)*C9uA-1Du&CtuIM*H6@N*}V(Y_hY4bk(GFLcfv?4W)0P|Olp_Y;jBaVz3ejy z0diLSw~tC4ungRTdY+>rCg!Pbo%u*>M(y^f0XLy%nP^9}`aYkKp$)7=(~*6Y)!r zVl2k>>>0@l{pew+L9g1|txS?UxI94MEtJe@rgvU@bL5cSz?CA_cfc3G%5f}9^@>JL zOK|F&$HA{N`^ol7fk0w0(ZLDqJ~(X%S3V%)LtYSAeXbO3jKFuVtJxEVw_^MS!0PIGXnBvbX;A0tqf_wWThGK0^@MGu z&D@nuYHk_C5w=m(RQI9Bw^rmf8Q zE##CW%qFM^3pO?MZCE6Qw!}C&nMTD^7@0CITLPhL$kVsz4s3Q|z=oonn*MCz45i-3 z8&LgIOtNcll~bs#Xr{0N(b5ZlfRAJLD$`h7--lXi205Yj5&FGRq+S~syN*>We6N*# zqR#t>Qak(Yz`VLzVer-Szqq_XL(uX!YvuPb*3IircXah}X*(js%;RG2;v+v}1phW} zb3k=%m7hrjLzlTif9}AYm3BE~5GF18Fyn>y(uW5NsCBRM0gw9L2IkINL&UoE%M6)N2vZ0haju5Tc>D9$cS&?F~{J(X$MURMQcnKMhB=rON)T#Q`5|2E|o{ z*tD%eWUG~R#~GAJc}pKCMd2vEO!r}QP=->xmSv!GmMvbC{jv}Ct#(R~bx9iN+~YJ) z#=|zoG5WQ1A|-c`?>?D2e9p3~sS6L**P^sTx$}kjqT=I07G#yp${0jfGbQJ}Y<~JL zo??7df{S6q7Oez?8Zv(ku`6vX*xKeVJ7{|;madk?Q3s1#S10IMlu-MGIQkwTMQ1QR zl&mGd&~7oP02I_jv-vneJrTvmAPGD_JRliKd|_mD&bjSiJ>x zCCg_oZh`BGQK*^OABnG6>hsEO>`2w?p&81AS*YEW@W&A0_+E#6d^5#`%dF@vN&S(Q z&l}@#n+nBD!S+fN<>%-~zrTIk|1V&qd~ej>vus?)Udh+h3>Im98Bu*RwBO}5iIWH*3-^}@;qGZMm%c=&{tjspn#S2UU zLx1@76&>m)TPyiV=ydG`%=H6O(*4{Tw?Hy3`IeYrtC`Pzh3%ENSC%UbhsnP|knKjI`(VBzwFYC4KIj6)PyD%UooIdQ} zKhe-#$@r?AV)~z@_b0q++7apJ87S&LJ2bDy5&iuy&Lm1|Yd{`7x*io8!g;scBXond zGauki-4HDZrbPpsK_4#!p}fv^+5`}vuh{51=TvKSdo5mx=z6q9U3TC!*eSd-6gKzn3*2|1+m-Ae>uUj$CYA!m9 zGnMo9w|uuXax6%O)^MI(;<=&DA4h$fV+K~9xKnfvd z{iynofklTNz)C`qJ;AbG_p-2#@^_rU;+1W){mC;I2@l0CK^<&1F7Xi<^Kw2V4~hkl z<-p5gKIm{~=Mp#gEHj<71KYezNzw==^CCF`NME6x^?Fy#(qFHd0sjL`CH7mmIpN$7 z3%w^cKz%^k+6eu^5X^K*IlR+&CB!o?1-*Xb(uQn8d$=JA3=dMM|JkrQpl>rKBV~;; zC+F_|2&S>^#e>N2HTC2VNQ$*72J+D!lgGAeePd^mYVvA)UJ@EfmD5O-GB}*=`Sp?m ztzFZ7k^`R?pMHzFaLDge;X196jKBZkaX+L2Lhuz*G}%mU6Y?xnZ9w+UcPZ{eO(9HhlWl zYV{)TG=1{vfYYd~iA;)*Jmq~*7d!v%NV+HPqu3mz#Y7&iyBIx+-&Dvi5m>xwaO+`sz|U%@!;vk$kPK$syZO>@$J@$$h3V}*fCXH1P9 z0zubFEL~9^^XH~ESyiPgL;8j6^+qPW2s4VDw18bnqCpBkSL>9nL?2m{<4fLUfXUTc zQ&wafCQIYzC7bmIwjCaUFqC6ub>#Hs%{-zqOMb|9G&|M%6tOtgpHT+?P-yT5@dN={ z5PPR+VC-U@6na7I1%IUm7K?0rPv4bsm`RVK=J74&7dYE?t|Snxg~Dj9;k?Ep>Sqj9 z^lzs?5=t6>NkYtsy6OQ2$Ui7B%A2y@Ypm0^o0WW3D0v3_VqZw*S7xO0su7P{p|+}L zPbRyOREgDhQFlqKjd|2yh*82P#wNK$j~wxwywkO4oXx)U4ysd z_HBpG$Cn<$UAPQm0^F6aBva5}IbA(?T!V{ujvo^c6v+!gDv|Wbu2Vj0LruGrv+gDD zP~1A6v+jfbwck)MU90PXv%cKUJJ4D13|sfVcI3B1$pe%CF+k40de7>~+cvg*vr6Ep z%!ccD$&0Nvtb@~j#X~J?SL3^;j-E<7yoRR8Uu;G3d$1sw^j-<@a|y)+n8FjSK;bWC zj6XS&p}ayu!h7GV{E5+pkSTXXrj-=WAqReP8EgUIh#?= zLh4VV>f^XS<<0kaMSY3SJ~WM2!(9v^;`@tVqLm#2ny)*CCFvu{wiHomb8cQKY-uPR zC6y?^s*t$J?58<3icI>6jphB~4bb$ZQ6!rOvn}5&5e;e-eEC-r^_@1gh|Rc_?ak zKGLi`=1#Z2cGDTNkg(!Ed6ZPMQ#o$)T4f?pNGOK2{k1Gj0>VudUh$B5#}95)la*Lu zc(!@1h>Z0Zyp7Q3gQI*cQzQiLCS|yFvzz4dZf&&-dDt`IMdF09pMN?%fb?h2pI`!D zOu6s(-vdHdgG(!W!;FhM+DmU4a2K!!FWnivwL%IH^D%t;5v`4pG*9!tio~cO#+{lN zg_ceLGNnRMxr4{yrEXm@Oi+*@G@ks!dy@Jd(L*&s+80Vs=)@*TVyUtt2hV5%+rm(a z{$j)$;|NBT1nh|}i?u9G5mmwo%xy7H-U4`1UR>hXj$YNO5W*J2pZ}$?WCr% z!28w&B&hqFN4bq6l&tixf-bb7|2Xem3ysGuatjQ!I`#I|;LOJNTaO)`&tFOQpHCbI zoQ0|Yq$zW5xqoD<1J6q~JfJ;N-USVdIrO7{f!;#*{bXn8m-n~a;MqburJ`)VAdwfs~eexn* zKaQBo>|(Yds_#x0C8m~KM+$#b#xSq9W&00+e^$55=+WNYigIoBazMJx%$Y_K4Q9Mj zZoA*k`Vcb8lej?~a;JeVuz;C!V)tIaH<5&slbXZF3#yB|`XM2kQ@g~D7$}}PaJ|%! z%t1#ywTmJWd2`Jt>j}K$b5hPQFsGF?WIhPUV@7YkVOwYd#Ug~-w0NJECx+4yu@RkH zvrCvY@7k7+mUnx!JlFtVZ*L>7S%sZmlsOmden4$KnLkxDS;?C>J{UJ=eLHG2sn6H` zq*4I>h>_23!E3MonjL7ict+4g;i;UTLz^wgkB)sLAm*s}ZeFN3LAyqyWzF9}k7$Eb zL1^;0uZKp+3{R+a-j1==*aqy9`%957f-WxC-oV%b7&g-!amW1708J)*^`PW@@JBsK zWVLrq{i}z=e-!}%P|?{d?3D{L*Zwb(ApXRznmrqu2A^CYv2r1OwQ>?TULSyl6l0rj zO*jp0oXn0|gbP_8T$7!Z4a1Y1>H_W74j3Be{MCWSgZk4n)#`!W&eVLrJVim|P)Z@X zwR@I0r_U+z4S#r%`@5biVvy0)+HzoxWKbu(2r>=}jnQOB`Z~*&38s-^xL;0hqEMb& z74y@ETny3XN1*G+pRs8fS8MjOwk7r_kVd@HECKQlpw@ITdozr*zk26bzuzHLfCuF1 zK*?vP8NcEO?42rYkwc za=&*K!9cd(9n0V9iVY(U%zT0883NR^mox*WGVaRZeB?w`y)_Q6np5|-Dt;tz?6D*N zxIg4_qMeyP?1&muhGeqAqahHdZ5AiYaz1!<| zVYBtVGB$7xXy%=#R-@4fZKqZXJsk2c=8PPzux?s|=UIv0akzoW=N`1Fjlqvw#K{m^ z@+-*5-6QH?k>0Kn8Ua)vwBbrp_xKIC;u!A==Wy3HA+|F^ie4rO>>FqHOxwRo*2>j2 zt31<0ZrJ7{sOQez3w7@&qEZrmfz(tZO>ky4l!_~rc;)e=Xhu@wZq_TBy6O4LCTFX@a7oJXlP%Zh0 zr2tZ2$tfE+bu{AFYC5p|8T&otA#*&_9juX5`Gwz-0Us$ohyN&~`}`! zvX+bo$ph3-8VrwzkhTKCcLuq58Ju%1jn4I;@#n6eHBkG64H_~<&mdc|V2h`A1VxeK zU+wGj&3#{yR2Q{Q-yfZz8nM`bI8fChsv8l$@n44;XftC>E!$n^zt0WlIg-f^Yf_~0 zZ5qHYtPOo8tRsbAOXJ z$gy*H9E;A&Csw-X2;WD0oGi+2TvKzP=OLe_fuw#}RC= zp0st4SLBCzowva(-wC-v2_c40Ph zbwO&7yprT0IW~}!$(W*q0`y&St1g7e6j0kcs0@cLl>c>+#=G=Zc~AE3hN?3Jy6SRy zLx9m8z^6ovs|&M|I}~|Ixev zvT185buDF|m@v^?0+Q8xL$L?Qr{>ZPt+C&P_DKN7T)V?4#JxlYCQ>S5lp)Q)TJh@P z<4`u6$zhMeq_vIrPme_qhA{&0zkP9cR>;(_;hP2Ab&{Y;IKS*choIVf|9ip7rRNwJ z1-_~cgZ~bDcpGzaek?m=^Lsn``r9z|%aFz-1t_ya6?vTc0lG6~kH-pWm7z-eraD{iTy@&7muF5lR?~jaRUPni_4I3lgz%doJ(L9*sYqlyTvh zzDExX`E>UtJ#wK2C+1g68aPxeyWSnU=+>SKh1?&Lp+Z>6fzc{)f_%<<)m^8)MR_g7 zbu{RSB7bj~`heF_xM|FWFuJtNX-cTio(963Wp!X(+7?M4xR&QSNj0nrIsaPjy*MD| zW3Dt4(+F}@8(J@G(~DsHn;|wuwE|9ihDu_JqVA?SDS?`>a;SNcz_P!#C|^Ako=2*l zQdGbW)I1h24f7Mkov5*lFO3H);@{L`Hl{8y*%^V8TO-JK%$SuY4~>w6na#M7=CqY2 z=MTz4tO<(X0EXcfZIVT*1w9y|onu|O(+qz*Az)Y$JT{D5K>!9nc)_o@b^;U9+ObdK zEa~K1@?IX8ICrrLAFyZQsG{$ctLG;#5~CG+@l!uofLSyVeF@@~N*r6ZYjqybo2;;d z+yyop0T?9BSmAyJADdB~r+6Z!xg@W_#!iUZgJIV8@-y@VAG1NjbvE{lXS@L3I4Pgs z26;q39=E5Fk>45raR>+QS(p(LuKQHO)fIxQSVB?VQ%z|NQfl$d*i?KI^pT=-%)n5l?3|hb19?E^SjC;ke*NfhVgw;4Y!$B*(9!>g_}`dD ztJK3VqvU||aJ5%D@(N)->2q^hwBSBD9wV*2{6nT!N+1)Zz!Ev zl2%xvJH{jBn%5Q9VPJpiul?!q5>7_A1D2<=P-F!E3@N!iUt9DqJW{t+swirL+0IAJ zH=xmh-iJ7VU3-EvT}qIg4U?8VqUifjG>lw{u})pcns(+jwqUW@F9a`9*qkJfdC(Rb z+s@3j+Ogvz^wb#4@V%&+F%SbNPWz=iGhpEk3nodh@H<<8RK7`y=V$*p3nWO3KIyDC z*-C6YGyLI^%AdQ}IlV_OtUD58Xnb*l$~Ce__PQh=G^%x`g!YVgZDCR)rkBJjao&$o>==?-mnnYrE((^@u)XEJs`0h%$Z4e+4)nh}v4pz6YTVkrzda1 zC$8fjI#8icmM##X+6{pxhR1ka$v=Y?{|8D4%1%6XYXqYJXVb92P+n_mv3y`*uen%y z=Fu_As?}s*VKE-WMe@4to4A?uYxA_T8TUjk1-#Q{Y5%Wfm#eWM4|A>M8K-cZ27*1D$0oT)b ziEYsjucWstted0H0X-ifpSAtHaAh^_RoR{^$-8IpHV_IU`-VoUt1EMuaMC%#!!2 z+#E?xms=x#`-?wuZ$ zW3u*%MttHcKp=a$Uz}o za2~Eb!M(!IUr>ne(19s~3za+M2+7z1y#Q&*N}~R)*3Hw3?EP$&Ex>YG0T;RC$F6@} zET^#X80;Ur_pW+{G3fUzN=J~77?Gr{feC_Axd^~sW;pZ} z@@MI^#fK3Du;J;8h}thN(<%gOQ)c_p-~4vq+@sUY$mivyE^%6y!X1rHTul+$#K(0t z$NPTny5$hg-jN($$W~hMlRuc$8ANw5CTrZT6MNJ7`56y_3K;z?p|Aa0rDGpkbya0Q0FL|{2_*a&_|)9C#lgcn3)AJj z=G6$T7I8x4W3rMBs&zTOnI%s+Ohj~a6${ULd@Pv%E-njFK_;@9a8Q&HyASxjpjB{g9Su0OlTaHah42^+T1tvt*;xqCMN#L!{#9|>j|X` zsg-40@&oDH4sq1rcRE?=N@IK66uVNei-D+{{lF}Tq)rUD6 zq_~>x5q;kn@uYciG#Q~}jfJGC(^V^6X1Y>ln$3`FNhxAmagC*TJldT7E-7XTm?8%~ z#OfkHtEB#Y%VPCuE6wVy5P+#X=S;-ZCFIjszkA5@d3}&hx@_R5wrIAeQto{iHX5JN z2MgUbmGvnt%u9y7rsRvlCg@EzRqbQHE^o^;N5c+N=o=7~L24$nYIZ})!`^#YbT1Oj z5gre+Q@8?@L98DXra+s=Aoo1k{m2QzCkZ#J^;=s&9s9 zUMKCu2}n|QJ|b*7M;ziU%E%#`-6N{IVMoo`aF+O#Q+D^mRR$0r2XF>&N6Qxqa)leI z*cVmC)AY-?D%^-V0B$3+;=Ii^%GM+eLOsg@_htLrOU7+KCsRedoQjG*fmu^o{G)LA zbFz2CS#v_&Lj8grpOo9+HKy#eZKyS#ABt!0ecXssAAU=l=scTxTYRC!TE=e7HeX0G zKJv@Y66LzX;|yvlcg1w*r6U&l#Z*CKp3(StEhpu4k#$Q*y_PW~WY!DTdyjUljG%t} zfg>XWmwCmI^D7&2j^Am;8M2;=c1|FMn8i(UW)*1q`4)bro`;^UhAe)zZvO(%>d}uP zcFtHSPUs+Ft#ij|jk5uIkrtxUhof)(poQqeSmRsN-9y?YBA)qH*sUUNvNV>!pdOx@ zaw3Ba?JeIV*TQCSjj2f(Jcv6&KT$~)BkPc$aP6-eix8o@&v!yfMB6zN3JwiUYvSza z*mH-{BWgaWwLXs@bMpb-Sd4F-$t#%#as%!PiF|=hDRjVV>k)VwSpBSA=wMd`d{2-o zK)ae1vTF3vmNBcYscxK#vB4GO=ISz#rlJR%%>dNLY{w{udq;l7E_G3xBI;uV(3J0T zKkuodWRnBrV5cU8MxKmj%i%vVLT?;#LXY4#V|2hHp&%?DOQ}e}b)dJsn_b#*ck~rH zLXnA`uN|?+#8$i;YCf}` zn!>~LQKk2q+Pt|WomdE<_tW>S*c@3Oy12mMV=unM?9s~`g89lFIQ~)+tuSRbI2QF? zEcH!n7fJsFB!D+@hgXWyE!`tnmW85U!AIK(2+~*e8%!?mNCtzWi+@2lxdVyuGi_Sv zB*N!~tp)3~_t;$oCwuM1-)?a!T!}J94iq%ZWu`(sE7uiTU<@(w(z#`EGSM=>9s-iY zHQyrFfS+Omg-jb&XY1>ug7S9@kqXFTnzWr^l`A#GOg$;rz#hKQu~f}PE3P*VOeUlv zexYUfNcEO!O!{f|3o_hHK7NeiUh2_Z zqhGVvNONx9cq;^EvRdg)VoMg6iJqtDB!iqc*H>wU=$<-*KsfY??X|0BRe7AU;}M2Y z?O}VFxuYaZL|c%1?9KjP+uOa|@@8_s(9Ohvl#m;XR*nsq#&~W0>|bnMSbw$`eo*|> zE0!$fc3@R2x4cH2pu*h$af{eTv4P~#0Us}2w(H;J1f7wr*?hoNwcJ3znh?o4ns-{A zrkDuTy0CftrDrb-qbpbf4AyHZW+e~#LeAa9C_X$2yE^PYF-de%O-WOfn-gKqY15Y! zM8#7QIWCAnI6&v~m%PlGl-D&iaIhr@d^Q!QPG;TJPk0^Mi6Zf#$UK!AD%q=${SXH> z%*7dAmCvl&YKu)rlxlk!Eq3W8FQwcIE=F2UNc-kXJ}U?%kLVs~r8Z+yki?3BX-ktr z6lAzNut%_;(Et(avZo_}DVtqRrtHB*8gJ8Toqxm5>YCF4)DZ7T+&XI-G+g{|-_i5{ z7o=>zg+=NkI>Dig%kbfB!T?l0tQj>D#G-HD^}I{f7&hYkBqN|tmp^Swvfax|q&A7@ zS{_`2Xi%Cu;xBtK0$zAfuBqoSES#swDd$HJo|binV`zCLN-#5nBzfi#F}I@OWWf-u z6L&*iT9rIJu^A@$dYG!m6)~7W(($fQK@0AS%wSFT;gs`5}nT zCpI|v>ZYeh*?v(4OFiH!scf9{@%n?>u(Bp)oa-K=0STpMW!+@71H5xmgtpxe!=|rr zu_?{o1rOOpz4Xboqw`hX(1r9X`i3hCFMXf-1)_M$B){fc_i;y1*U)`s^ZXpokgQ{c z$PS^L%hLag$~b2jkF@hWeHnCV8jAbJJ*e$>iep9`Oj6%9zoH>o&zk>1uK3-(8wWAM zIBICVBm1Wx#p*i9-59ib+(jO(U992jtx6b2Hr9rx6tfN+IQsun++Sbo;6Lf1IA+{* zR-FHL6y?+xYyD2nSxy5;_tKidCmhPbI88Miu5MnumF#rgJ?m597Y-{-PQyT5b$eZW ztxZ{RqomE5NcS%+Al{nT=)Vp>a;^8B&UhJ0F!b40!gnpGJLq_LGmVE4;V)Emzi$3N z3!Gc3E9dq@N1|XzO~x5>pl43>5Q(5^Mx)%LeykD+Vj?nVZ{1{P>(EEiHDS{EX01K{lI9QGHi~d3% zZDg&gizexIwmLQ8CD`JCehOIl9n07w9N~Ngc2%*vuulcc3a`=jjDVJ!#*b$;v*^GR zLD!o!s^5$R3ovU+p^*)o1y9@TDTij)ypdl}f;kw;sW@I{McY!U6Z-sk^8&Hx3=N0Nwn+9OY{{vi zp?SZwgq97tGbhcUeMx27OsE{mu$-6d*ULnM@sf~anzSXpgt~o2xH-4nnZZX|`gOp% zT&@j~gHm3IGm202AJ0>5WCNh-ZV}OWd=RB_KRz;&X;gkD=bUJiJL5a4ymh56kEplz z<>|XyMa({_!mCZi;E+~5q6t;;%CyQ>e;!`ugldJvG+JYek)xwt=fsdYk=mul+-FA#{L2d!clem|Z5U9sKt_>9ai6 z)+k`>k(Js{_h{7eL`o4V@){=^y2kb+{>3*9owbLEl+>I2X0oN)y)5iHStlkH+#2~I z^SEg@BB9AggVnGnn%^2=P25x7jJSg}lz>rP5W2cu&Gpm3WpR~IOm(!DPUvxDY?z*F zj%Q)qyLDye<4nku6VjSQ`tc&U)27HemujiaVpRQZi(gL+@mbYr+bdR@i(9_8=;yWw z``WoEUc`HBJB03fK)skM8GQ`=l`gA2x*)^S>JKMbY2ANJKB@-Iie2VbO-152L}&lB zNW8+c>^fM!+~^+d`!;9T#IIJ4N&5YIEq7o3gLwznU0k@4W}iBJt?e^MAFV)4GBOJYPW?7%oDV7yfNLUo}&ZmM=A5ui?et)w}%yU_gU6u)`)l>buI$e zcv7mHvlK7pyzXS~!uWwEaaVOxR_lseu&S4AVH&82lQms8CK5)U#sIRG2UwOqP_25Jb0$TBKpz+cSXJ2uhdS_)?>y3U;Z8U4N-YblMIthe>jcnfbjgrv zEACPJU?O{pak?AzpaN7)9F@n(+W1#4RPb_Sfe0mJ@L8h`C%`t9($XLU@b z&Md7C#Xqu5K&Xdr9YRMg%lzf+gpFn`T734jg7@w)w%BzesAYu}$Hh3j`$0O=+9d|= zNz?43_Shk~l~Z}g*mGX#>ko0p)fbx5-ju&+#**v5Em~pHjg;y%gQ1SqQ&9lbkRB!j zWYX%kNx)rBJ^mrI#u_sLBYX63*{x0&&_HDUJhi26e_8^1+<~X>jyw=A#d+^INE`Vg zgx45}s-@VgtUmi42s>Vn%SRHPgfB0nH;^a;(z|K+CQ@GlCRUdU-cp28tLH^UO>M{t zkmxpl%w6jf4$?FLYAtd+;5Am2Ya;+eB}}Lib+U}%K;5~2A5~7mP}vXF zt%oETA0Qr0Nn+l`WgLfkEGWVxZ;GdbGKuRl;h+*^Fr_0w!9YL4VvATslHqR!t<#6P zILt(8=LWqDws<*96gk91O)hU14;LmPpp0`_yBL*8fBC&vk;*#7LFv>1s;Ps>II~!8 z9L}mq-gi`eK*XT#OGnQu-05+yORr{AvK55zVcu3X(aPa=S*}!jUCY1n3UVr{i=y`KVkm8e+S4d-+|g4b&5JkB3>Hk=0& zO%Oe5{~0~INt>)tW5@gQb4?S1pl!=V;6}7`+#P&JLgs&kRfcUr)cIC-U@Z_W$o|m`+Mgpk+*UlJFQI&hZ zJRsVr$VuBCd^Ob5<)p|dH^x_oDfFWHjEq(4-uy-SUwX9uymsyHauY(+Az;h+>+8Iw{~0{H+0C(%Rw)7lvd)Y=F!D6+*i_F!SdL8>+&Ob;<3 zCZc+crH9w1Q+9^X>?WRI6yGciS<-aHf6{Z2Pr^q^wCXP>o*v|CRVqMSx+cyD2*_1T8*!;f#QbXXKaAM_ap$olIT3LQ3hu z-jax3l+2x<5b?;CVz1SNPs2vN>OSz1PzlT`igM#hIjkIma0bs=O-wGIs6A$?K2R^# z^{8kGmf(#^SLhX#K3uXm)x%tzbLc|TjAbf#m<#VMyteQMK2RY`m~_9k%vh3(vB%3s z29j2qv=RvUr^T;K1g)E9(yE0uX1nb2B1C3l_@hJs8s}0T1>`@ZqlAd8U&+zHfxq*F z6GCpdvk}b?S1WR|t#hVZiKDEPIy##>j6KD0ji?M@5&qvhYh;UQ@VwMIUGJm+{Jon7 zTD#=rEL=Kyk_UJTmOnpn$S{gM*l6lvugEY$+ZmXdCr)w|F&7UdlRtY!^iLkug!ZL^65%v!LINKDCb`&&OM)l#_eN`7M{*(g zUF(A4h5O{@+cUk{Cwm7#8=i(nQJtAYhXlNAj3(%>ck<3kx|l&{v4$5PBgY3WisrAUHCK`m^P*ZqK-pDJf0wX|M5m#nz2W*sPh}? zm2Voe4Ro=FAkIFkfqn;1bzZO$vh~Iq$XLq6``)kE+~H{h>KG39Ub^LZ5X!M>Wv3Fw zsW~C{IwHUb9UnGBI=?CGf@Im+(b45=ipZpyv{Kgy-D!^Q4QU(A;FiKSzVAI0Y9G>V zJ`G@75TnS?sto|I#tz)%P-tqA#N4gskno@DM|cPjW%>g{7K-LEH{!# z$XRqU;M(@QDLA$53F4cNFBj>52C5%d3+I%#xB?P;Tv)|zt2-5b=cPDARwW17zIgR;Jp20% zd{BF=(Z+}vIJ4bn1TX+hSIMsx!c+WF;@<^{jPR8+Z#LLlxglUc9yT zySLcv(;+{UK7*F{)q^pQp$znNyRisx7<|5- z%SFcXf}Jyo?KI#{-@hX{d2y`uJDb%C;X#S%h0kuCqUM6lIqFq~wMS9^_9G2fTSY6q zCl?^CMIw+`pP^I~i8tfYot`+PPkOQ-Xl8r1X|Wi_C-akG8(F~qF_q!svvD93^RY7? z+&WsXJ&ZC%jiLVpB7ZBYj}LS!KINxX%t$pdZg!JM%C8M_foxH+UxMEjy*|G)6wc@r zEy61B%Ql#xVs^%!LS<<6hL=IdiGYxDBf9kDYFX2$sH)BAybOt+)k`MhB+?D=I!~}bdsYB=T@aW)Kh^jCi zur`3uN3;xSb!x!2pdO+6UwVOU94>&U26ZCcBzkex`wZfb7hs75_3eEp`gkxKn4%rf zw2W+JB*+(-byl_DgLH+RhMJ}dbm!0NmtD5qA7Z{B%1;Um});*{$RsD`$$jHl4F@ z!K_9)=HS1ZzoqpY0a!Vk8GbkOWB9VQ-O z)YLGml>VFp55xPLmkt=p@xSiHnI~bBnRmkk=k5WwXbr61`!QYizzA^!IV~guI~NFV zLO>_PdQQ&4_c`|%>_mGLA*Sy9@*9l*tWYja0c>kYMasy!lcaJocf#?t^5#>wxQ0tn zQv$9I_mumZECGAHdve2uHs`G$<)m1$7{ClFdE})nq@C*I>ge0%!P3%Y&AfgJJU#$f zLC?=Y2kJ;PlBoEctovn7TH(^si0`e%Gi4w zAoCJmuDVF#objbRRXS=5XW<;tB2%E0qEHX+|I}BAa=NT~(jBju=X*ZI;<9?^R zk6$7&L`#PKtNn^QN!9Jw_ptnKzXq14W+*Ok&$}>_#-mh;Nzl1(Y2r zYgUTNvr05eq12KEP8VA^@$2K`A%)aKh*SbCvgG^<8F@_C?umq&zpIo<7QRM^3wI`> zbaVP)9$k`(8OBk4ZkCWVR@h|-wiA#NM4qb)Ph7|kBBW3b3~Eem7)ewtQbzaUV90V$ z=1%rzS4nLUUgZ;J9@E=(MN!s6?2ga0!U2W;pQT}Y_!lOkyb{+5cna|2kD9*nNbEvG z4e&zPP1uTzQpkUyvC&rpJ$j)NbqiuD33irQA5}$;{7QwXd}-(PdcuA8@~n{nM)dMd zoEBe4&rA|4K!Bk*J9@Z$ihFYUUlS+4L_+s-dz9Ir`rrKtvz-*%ErKv4;a2dB+1YWpbor0MI6O1&%Vv=~y+Z+gE8_Mm)<_J$sZiTsNW zn*G>??zTt$u5DTxB++ylBl9OUh^J?J#38P*jsho0DpRr;UhB>sCFv|fxaM%9^$flv z!_x9R=EK+H&?}SLwpSU>KlLB=1-2-@^Cc?d%&$H5=<8yqrO&%xkxdnp!Hs3haO)mU z!x4>ggMaAzLi|P+))7p{TBl=(lFp>%a1tX$*d_NfCl+Y+l@5xQgf^i+XlcTc zy&cWE+QFMLgYF^Q+2^*v!rq>C*5{U}S*ypY9b5dc(;;!+diA?Qbn!;ld(vH~%`>Xd zr}6|0KW6mHiwv=RnD|po6bE7XDe&S#2IYIQG)in_Z3GJpSyuvB$i%yV^8j#t!~!}lA=PpdMFU-YvDRnolRQI#Uootd+3hsKHx`Hx zy;i-z9C!sC*uyuast{KlpnPM4lNx}P_Q>aHyqy-28>sie^p~QRd0^A@HR$#PMmuXx zdUCv}s0cxrryz?Wlz!!#$wCr0di9!|G&HSGoO9I%43)O5x;-y|)D*yQBCEP#_}XK^ z0b6-O;gebxT#jG4>-^)>tB+ETJ$P&_Hr>=NXTiL;_hWJ{8_mZ(cGj{<_R`-on4vWz zE>eFOYbXvhS=;Sq)n>{--NH5XAKjI-@6f`-% zG1~u1G>SxC%3L8|v#sm{1|y)pvGJ_s3ymLfutJe_QNik{!og%3qM`UG1N)BZm`M13 zt7qtBJ2E;0zcNIcKcX%`y&^5qVU|8eG6KPh`yL>d_X`3YFxDsz>Te-SmeqjPKUR?| zLd_4VT!2Ncy!+0G#q~Fn3j^1R9j}DTb`9wXWA=}Gb_B*W%sLfEOSYAOxV1O?(NE;c z7w2$;e+u-lRgE+)f?^XL8dNx^6O6|S|l9vgxpKk)pp+ZKmD(p zW8!G$DQC!1w1?QB5q905JN@32+vFVrBn#h00L5};MuAC%@w|oc$bgeL1=Z55 z)i*OxWgyEMC*{x$so`34I!vJYYkz6M3Lg8JDAETJs6(z=bmOH8d_o;9NnGS4>NN`S zm|k!iNl@1IcN>MF>(0A;`uJ={ltrJy<6j=>r)zCLwjx6P${2-y4dd$13LL_K5^JUR z*)qfgy#QYB4PJN!U##_-29Ps=P;o=%%7}p+qO7eJcm;gX2Ny zaOS&?J$AyG{@0bo_-!aL4nj&H)jk0tcnbjAYsnCNB@zjnI8)&a76tb*LA65Zfg4S) zJ4rH^X&;4&&EEe6S}r*aE#D;$u+HecD?CzhIR%=*Fb}j+mhe4u#9*P+Mn#3C=#5Ni zBCQNT7Yb?nXjT~%P+IED(uGR|N;e5s(-m>2~MF>yVLiX zo%Ei3KrBO1Po2W`2%|JS27!LcM;mlL8&uu8F{*wO86*$?FUP^`1S zprzZwiyW?qGH_~$HJwo=Yz}QCC28fm-fIDs+#zCUOEjonu8ympxn&^nCZiZe9=3Q3 zKmNVqKS}2sz&8ipA$oC#AT>>NxE`ED%l~M>z?u;hPu{ua+DF>t6FTQ?o)Q5P&`Glw(Fvp*E}4=O2{B*fu+7Y;szP=>R&G zk_ZhxE#}&p=YTp$8;I^%1nto%sO8}Fo>jzSB*{va-mR_cE|DBsLifTp!r*;h zI}ZK>#etI>>B~+7^1Y$ztTt=-KDY`A2f76o`NSYiMtC*6-p=K&UP>jPe0AH%2?9I? z3UtTHiRN!lxxI!=YLL9A-*isTg7#GZXd#K=Qo0~xd1Wd=5vvOf*oBbI@tFfYu4m4R z9{hny`~*Z%@a}J}tBY9SRGC;99~PjPN|pc_LcsyCwWF!eeNpH3+Koi~xlr%iTRxpN zn58S09sM2^`#&YUQE|8!CZvZuM{{U7w}2m;{U;3oPd{dqmj=i)SysoJ?{@z*-r6`^ zc8%BW&`+Op;Xo$h@#4E#d-=K`hUHo&I5Z-#|Iw9%PF($7;y``c zUMGCC8uJwsmc#QF2?)D$gh8O^vI@`x6DXPmBn`S8nfRVr*K-vUVK%)_18==FX9JHX zw^y9QB(^|oytGuVzwW|pC{X(yB@#iZ{ZoYEwqpq6F;(HTS)l#I6gyj79VFr$AM8rZqOy$$zyFbB21L;o zzPF#2T^-ln#IXc~4qiNekvH4BrFcAU$==L%q#j-j<9=cn%wkJq-eaDN-l-N0HO4>} zF}dGL*)ySS$|1GQSTgi>C&)FtaWA!xtTJ3hw3wpk1|Yz`wmG~qAL-$cugR$IdVUS; zs%xhmMHhUK;8QsC9zBL2Dxx?HbsjzQWTWpV4LJZrNCFj^IvMq%g$rHOzB~T!6sUJt zArsJKgs8Xz5HN(c!ukyGlz+5|G+ZV)ZkxjCi79&ii*{On|Ml8MMOHkBEkUs!+{N|4 zMNPJGRoc39P7VsBUU_-n+*YJ{T}s|HHeph_bl$>}a<9w@seA;(RXdQgy!6`)AU7j& z!(u(nH=jGmRYAtZze5#}yCZy!9=btN=%Xnt*$l;#xn2pfa6tU%L#fX>bV!f7+;FcMV4`>qCb{ne8hVCZ~FlmW~WeKpREi0^L9Wc#TYx% z#znhB>S#_HJ5VnK*hDIbWZx(B4Vw?mxxL=+^fAe1$;Lg{BF??^O1fbr+$>QGCdFMx zk{{163QTONK*BxIvMIF8mXmPBVw{{dg>bJFp zK5<{Hc(bPUB&d(d=IDz>`7PQTQRo_Txq3XC^c`p|P&0-EKiyGVmx&beF}=5@b6R?2 zQ5nT$hM-UKx#DZJk}!P4FS2vW8?&Y}O$ zD_(EoKyE6`nD9nL^{n(A+nF|&^{Z521_k)HMe$?>x;7Qj{2#V+KCQjHU5oFXQY^S9 z+3ACYb|JuK&93YmQlr^NBas=Iu>E!Q~kDYBD$KhV|mU;&(+@_3!hzN6Uykz z?&SgGKxZxOD5hc`lW85#^7TRHzjphmA|aJ?r>BpxDEJ|E0|f*?1UI}Lj{v+t(2_85 zSmUq7c?$py@_Fjei0W-#M=$k)!3Rd5ry-V6l$qqA5V+a%F@b$LBe=D43N_0RAtm@p zu^yoEUud<82KdBsYCGhXDp4-S0s0k@A>xPTjBEJ(ub@ND!LjTxh`QKMXo&$$GS|L0 zA2%BrCV?l|r+8TBym?^hOut#&HR`#u>TVZe_SJZ-0uw0EUP%i1tuq?yQ|$ zDq7tC-xh;42r!25O4Y{(sT3~u6>g1jeydG#_uI}yzIMh)LBpF*T%!)lRWVXasKHA- zPF;jg^-bNwspF0M2w4)xu_NY|PzdL61h*8+h=u}M-%u*VhM%9g;MC&+%tQxr%ecI@ zZ159oLvG=d=CI}ZoIwsdr3P|AWck7o5%RWsis4{(EFxY!R{NMhB`F?XdJ*ldhuGU3 zU>G@xf)lpBq~ZEztW%wXc;$%O&dm$kKpXcp(f=!T6jMkX_s#wr|Ah-UFtH&BTtGH*mnWAX<0AAB$)32+#+b(pP8zSHX|7?!%GEe9u#ed zH3#;fu7ZZL6(c!X>7WJ8c{2a+bP%b9<;`01Cy<n^G+#r8sX3@vc{3UAc=rAZPY zlPo;jVj~{BAyZr03NV(au6nIDN99g*PaAik8#5m7cXl_oty9E&5Y~52(j&mfA zE#=Yuh{QvT9c$%DW`o~9QYtxI8|uBgZbQFPPxL(d5v4)-xOYS+502JC#nlT zn^z%~8?zihK`7)SZk1{uZKc4Gm|`V^^L8S6Rb!mExwB{(rzPo+0aF%hZgbF~f>>Le zB!7lk8Shw8c7Rt~k#?PSIwH(OuE#F=gfb+W`s6gCw;*naNY&-?!Vs82?!Kl~mMFLCd_qk(@F1tQQv)}JZ(5U04n z0h+PrGG5>8_~tS3TU&(V1Zm}tBG@b zbl6zKYmhZmmn-kBUZ>ze*GzSG-P@X-Eki^*jTeT|Et2oxC^NBT^d`qwLxP`)Ea_w( z8D`&x->?N>mI(e^-X%3^xolL#qDgGJ;yd~@m#bdMH4#4C{b(6YL9J(K4WbGqO`-S6 za>*kiV-ysIT26*+=tR7F#~)invv;fsOABr{X3>HqOnWUJJMCgxHV@A`D0tFBTI_IA16ZZ_mxY=?u)ZT`HNgy4l7R0^j)b|mhc1+(S@ zzq8(`$ubdF6-w|f*qb$5ycK*Wi`9xIQb8V?XV2jug+HDGH&8R`dSAHh&NXbZtic05 z8Xeq4Yab5ozk(~g4Y2L(uo(8s+Ac%B9hKPTCxAwed)6_?<-3zbUP_EOJ6u;6=?Mo2ee|t&1p%)}shCm3XwW)_trYvIr=UJS*z;%WDwP>u58N=&d_EJpM#4 z+^O{clA!igf$iN_Prdedy-{<2$B)A_=@bbC@im+-x006^N z6}z^US2QvO2`t#2N>`2z1}p<5LKwNe&yh)RB-*sjVkFCU)#!L4c8ta^BUaro(Vw$+ z{pL;`C;s#!DC0ME$-|fMKyFK2I>=0*gS|i8pGLztK4ENJ+7l zBWkiUO3dn;!ope8KM#GOT}yO(O5Dc2*qaEXg%ywZ@zqfOYKxr0Zn?@d1JawO=;0V^ zpbV@&kX!S;!W-guCfx$AI&wTJc$;?KbrZV6(`YP7hYSPw7^^1JP(AvlVR+^!7^rl* ze$Eat`GGi+egtEPi)pZzz))I510wGvoQy@2Tl0N}tsi=*K6z(L@R0JZ!oMm}!E|Tp zi)J3~5-CczZ57Jcf>?=3X9S?6pQ9LVdSV6m4!UU8n<>?zFESo^Uge0gk;c>b-_@Ty z8=FJbc%+e-Ym}u(6T#-2Mg8as>k^z|Gp^YD`&`{AYxkog!MT4fL+imKNUzHk2-`kE zZw9|i@M2qVdX!eVIr8JO49Cc()yfYD-idDOo}(KuJ=C#c*wiC zA{>EG`lh9dgZ;Urd1thN7RsVrz4hKjzZp212lq-uaUe~TC9ncNvq{ziWShZ~=Ult? zSOoR7)yRbVU6Nv-D1*@JfcLD9NiLNoDr#Hvjo8ExV4#H53`eN7J7_qj1z`Zy#n(7Q z*K&M?_cP9;iXoY=E$LXUPv@A=7P!QH6)NooU2hb~8Z1>v2C(DGUFjlO44G0ZIh3(c?!5VTS&D|^A;Kh zVj|+5Oc&F?pxCpRABIu-v?4syAo0{ar75TXlTd;z{s3)IZ?C_HK%6_1yC&6U!y#~V zrl^%4oLJ}4Qx0zvaoLfR~C-iWTLo>Wc8_!po^-poanxjA28Dq&(lSU&6r3?6nS6_P-5%k5U}9m+28?ogy4#8Hs>Z*)(|fTW8&VE~1Xm z+|%UNXPZRAP`6mhM4qR!W6g2*9;todvSP)!oAp(Oo8lwiDDJweBE(&o{gnjvW!1?T z_OOpJx!-hb{K)#S-ne+pz@TVY4pF^SucJS%RPpNmn=Ug2^+Cb|NGEs7w_aLqw&oZM z(tbTbz{d|_rIrgqsqVNR_kz5VUS+}r;O*I3I8FP{9wFWGpqKzbKVgd8a8cF6xe zR#?#ngm`Ub@Z`4oB%7YmLPUUd5VvW&hIdo-4jWY_hyZ6Qd4LD(Tl4Fv;~IfP|6!d2 zmSvN{mLv8Pd(YFnx@}W`m)bcx%`7!j(HCI(Az$t`!MxMAag&?i^plyVTCsT8KK}X6 z6}@Nr&;VHsbr^?{&K@tHN1j_Pr^H^t5JYZ- z1RPj1fo`@Tugsk457v~IT=`kTk>bIifN)znX7wGS^0Uye!EJNFHziiKHw_lQWlY;# zg8UBXW9?~j3K|h0J6p#1?u$e&G-Umdm7mK{73NBsN@)-Nq!2YSI5#Q8?m%EQdiv9O zu$!#6*V{qBieoE7`8NocxIxg(l25qib*-VM4Z`(yo?1LxH$cwdqdK^^aZaN4Q-CQ- z-)N;+;9ZAADq*VazSWpBm@-y8($EMs>mEB^KE>FAZNt`%?;R8KXmH&4iqc64^c6s( zM3Q`p83{m7ZNau8RfcC2i+NvVfaWC8r==xyy(gR|44fI66lq5aWTCaSR)?|53nsK$ zpgq)tpcS&Ezo}HzMG-eaQEKHp$cVe^m7}ih}I0I;HRD)fFjfaA2Xa^d_4eNebKC zrz3WPKv+6x1g|?}{YYRnLmI%+L)X;V?2d4!T*irGJ6AlQtX~sfO$n%Y)yv1T;up`g zbdtB>83ZN8P#Py^3uPGZfl(Ji2cC?Aw_KA0i}EpOy`>$ja3b}hwJDWikJMjd!Yvp+ zstb)!5ypV7g5DX?j0G4uzh(ky9eH!!4y& zO)az`h8h>neUvOFi?014AHgU);`L)HT>&^iLu|0Xg+1kXi4+^@c6c{WyVQEMdVR!+ zpV8XpJCydcynTqBQXrD@2UbggkCp#10-Bbs2^Gn(7H@Dg#%(aeX~~R7px87BNp6@{W@5$jTKEil9BgSA;V7S<*fgVRoLU4b6QoRVw`PIqg z@a$_&{{5Kp+91h{cN9emdWPr-Mdsxo%<{H_@7v+n3Z5||ryx~#X#Hi#r~b>&$>Z&d z9O?~(CF_qpwObn5Utnte8|53X=TP$La4}+KOqbasFqHmbJ_VbAV|Z-T1q~M*$=-G2 znTQ#@lzF>%k$rqPj=7$o#(Q=Xf8ISV{o!%7Znhxp$J zN3}|Pkz8DK6kXs0D_0-|>TMNbmyIM5)H=Qi#C-y6cG-s9)BC-X6><~cKZMe+=ITjJ zCV;S+>szWehg!An+D}mhkj+*yJtt@(fR6omlX$Z8t8l{;`n-s)lv7Pz)Nc|>M=p2K z1mat%Up!EshEV~y5fVm?W-nMg<8pp?K0ZQNw=fJv0c3+4W9%>r18fUR5$~Y9V>`0* zMuxJ8# zIVFvjkZ+()fQ6nHL0KMaCj*Jjzm1^$(!B_oMae&+bnvDUuh+SE_FjVR%6%z#YE1jZ zF+T;!Z-_kVpGJ#e2qS{nNL-*(0$UFO#T2F_GGNA@Pf<0L)~PR6fj{M4QZ=wp#RI&@ zod;76A9!I_MLMLpYj%C6S-w?YION-lwyVfn4bTB$^KCvsq$5^GL=iaxgh!BeRi*eG zdVLT?;sIk3;mXwe(uh<^79v_=6Qg^3FqIyj^6AS_iX;jL@PBv3^SXFBh9X2EE zh`68VriDD5?dCH`5Xk%HHe?^Y$}T?e*sxe#;_o@oYDKXE(`YHRa-nf8yduAipg>jc zvk;J5WTzs5GW8xP@c{FPcay$Hl#O+<^2pGYT)+PYDlKm>rD1M~)ahb<6Me0hPFbEAR0KK9%?!r!%IP+TVw z*au&!?Gf=L8ud5hAD&p}b0)%LKtdvC+^ zitfxnlS6tgJDcn#u<~4!sO@L*>lyt&)wQXaP?mF456W44>3=Nb>jPfU*c_{s{Uoae zxhntW;SPIt_ZcN*I!4%WcrtrCBl) zbL6PkSUG+CIX2La3EpIbwXBqn8^#Chguono>>YWyA~Tp6PlLx=K@p}+m@`T&;$`la zmfXG9>_UE^z0u5#=M!>nEZQ7Zx>PSPn?KE15IiK|GTd$5=-$*3JTBN1)ukZQU`)sq<1N#$X~Ubv|3A^;`^E4?2Lz$q$L-$>8Tc#KeP?Z3Em8; zmA2m*fr~)WRNy50>E+dEUMG#9z}-1+GIU@xO@Y=5R5GpQW^9xc16^12@e{9wa9OMv z9-Ong(KHJD2{e`14^ou7N8;Z6BCK};oz~@^r?PG4F?_DR&AtEN>SNU0S_P}+tPxd4=q8sok- z<9$y{=nX*MuC@RHKtm`%sbHt*#h}(LpTNOyheX*PUPg*sWefRw4yu`i)68($RAWtN zy%FtwpP<9YrI|>o+-l^cN6xHvkhfg6e+n+~PTV|9AcAjB~^A%X#3p-HfM}UlE6%s?OxLSG>=ByYM^BYE%Y^=Zi_#e z1@$L&WQ~hhxOe60V~NH0N$U&_?Hmo%%s6-V{%Rykp>&h^TJ5szPjCkSnXTp>p#|bC zgU}a1xUi0nNSs43xaM${RUqJoX)%qF1)d8aL;s{;c`8-azGZDg+bG#yU7rt(^Z|aNlIIR7EuKaODtQ|P)lHJg3;W&dw}$~2TNali7HGv z^**xc%{zh{*A}OBfgSH?bIwtQKEp_&M2Y=&XCKU9#{8Kn=vDlwUN8O!B$OLL!aZ8} zM~J6t4t1n;72f(6lT4IoAd zW(C)1o<`OJQkpefg&}(+&hi{p#t>>UhR8(fQ&3;{D@^V& z*_rgr@f*FYYy`*ot*aha7?%sMlty-GN5WtOLLj91?8Qdj{2>F2g+w*HMAaFGQYA;o z^(LsUHH-r_UfbTHUt7rP+1ONi8Tyvhmn9MK%%a89&DWYosG#m<`HV$|;GvUyY7@8S z6k-aR+6lXrGlV+&zSJV;n8f;^H4)ZayUb|-d3)|EYWe|rMZJo;~nB=hg&wuT6(i{0~ zZKHv{xR{>Gbybq&sKxfIl6|9z*|)-J{iw=b%CboWDtDMO_CHGZ?@`z~b{hgOwZS8V ziZ8i_&01vfx~68;x2_lf@o92o65PyaioLQF83QzH#Q>aB9@r+&zv$ll$B6s`B6^5N zQUu|=HjvR%`#ck_fl^oAYZ2JDfB(SVlmfch9NK{sUL%XiMP6)3yM}FblHE z%r7n^|6v9uX~N|tl{Cm3BF}P$9Gbi(sk+mENZgPW55WIefZa#5CjvV$VPjp($hU_f zlatCNk8hx#l+pgWGNbDrQ5_48$mMNR%{kEDaCTV7tD5att-b7<6I%GHRuYTRVd@s3 zjcxG^hf4I~)v|Rp$+esUOgetN@QXiR<3+G^G;vCkU1W6pF$S88>tET9*fdV|{#`3P z*R$lZG@()?A1zUVK!v|qsgajq*FyyB_&?vkWtD9>2m$r+?-O`c{GLf-GIiGT7M=r# zX>htTUcHP|jw`U3U^avuWh$g$JLm(UpbM>Jz9;zrXu`)u$Q=hm_f8P3ZNNOh>ld2> zx2-qmQaIwlJFvXOOBEeB%`Pa>=$JyaxvLDi+I`f_NEQn)(DbcJ^iDfetY0gOqAEoqa_A2ix)Cnt>;F1b% z-wmnIY61aJM7H{g%Q<#wg>8BWEErFY~z z7RgLc*xU>+j_nfI-E!jqYF$F6i8lT*s{16Mf=Vl2@$zV@eecXL4MPI$Ttuu5e^2zu zl`br$&-yr}zBw-W2)@>vfwZRv!K~|HovOlQJtE6_suuwz=UE{$E6+^LSaMbCgzxy; zpwW=kI$Wt`%Yit{aG8vGdI=q7C&imxXjLL0f$_ZWSp$XlfCM$V2&fptn(+uK@tV9t zc`8Nx9MDW=e8g@fjGlXbuTU@|REPEFL~%S8MriCQH7lvgAcX2^r75zi`;eAx)NFBN zQZje&dc{)8ZyHgiMCUw8N4gC7>Tf8V2Ea$@a$^B7uRDHDcdx%Ac@#m3yt4B*Hfs2eFW?%Rld>zrW=2!8`g*n%&8SPc>rWv6 z)|*_9^h&Gjopyy+qW00w{#S^GVUFeaq9==2_)+E^t+GgX8+mk7y zvo3~XaGq7Rz^BM3e|cxV0dciP6*+$qqTy55M`)kncIvpnvXo+InosZfdGRg?sqf;m z-~9W?#a+*C&tA}$J%h0X@R7Fevg+K_{ckAu8OctwCuRz;{ONp}|1vJ>v^Thr-5xwG z?XkFVP0gIg1{RYjw*8PjW;tDN8IKa+Zpl z#OoHQEQhOQE^N9tzSgO9oGQU>pbD>OB&O@GoKl z#qboK_ZaK5FsyfSG>6Y`1E|)NhBj-Byi7+1vS1rN*7?rSGApgnExQfJ{wY1mYC7h zYCvkEX%JO|JLpGV!sPIH%%IX-zbtU2ADyYR!{#7$0@H2?r^@w`DKncRqthLOEVsdo zP>~j`!%cvP2=%w++34O6!SSe!-gPe&6_-s_*^{j;qUHgrFLj8m`ZEB+!>AZP$Z);)zxGe^2B%B2OHBpZA`vc=>;V{qaO?#)&cm(Y6J^ZSWrayOhlu%n^U*d3APVMmaCEWdyG}Bl{ zk0s!3OREhzD7KjHjRgtfsaI^~iF*`Tdqy*q!UjqOdOhFGY8i&CQUroa(R@uY8p2gJ zgm7VaCd2tH6#h>?9W#=hLSRgWkB9)~jCu5l)d6&BTtGC@OHO;4I*1J34Gw_To1c++ z;7}f8RoOe#TBnuLRjHUDPRGJK>r4=6Q7{%mmwfl@w=}b5(c?oKNQ5)t?sW;9I9KEr zvL-TioL~b)QYdamqf1g054z*JVIj%V=}h~vws^^T#==BMalL>tAcfmKqX=YVVSY&) zH1F`m(@HSNx5iXjZZuzPzcUP|1KFiwWsFsM368j=J9M_LelW|>dvS4~JCIW-6LSV< z%sjDH<)HuCt3|`a*ALFw!%e^8%HSNx&RBEwH3W!Gv;V`(Al`@Q6AUdwTUD#*nuoHv zyxqd$>K8{GVrqFQfXM6-kh2MCHl!LkYLJCguOjdHMR_N`ydpHo%V5sa@gT>imBex6 z2N#30WepkF3V1AJj~=Gr`7{%l7IaWP?q|Vd*j`5bSa(6Inz|@5;f2;~L%}(^L(SEDXVxcMI zgws{w|Dyzwtb-pAE&0PJ%LES94zdb2x>Yn6N$Y^atJ8tHcfs?H?9s%)Bo4U~bK|xP z`cASZ(uWg0^gk0a0dZg+XF!4_{Ag>9A2E%@hcVln(tVR?!Wk^jmj14(QYXKwgh9`z zQ>GL{>*T!e<4d@aPN882?(#IfumIzz5o9Z|gQ>%_xP^QPccwuoY7op+lz{Hy+G`ym zC(y{G9}qM=7^*ngVfO4wS3{R&&W3M!QmOW z9Fr>|kZWS}y@2k#ozTl*H)M&}YCz;E+a(E{k-M8R0-m}Kl{j8*5Xk}tQ}ufdX9E{7 zhhj3LiTbMQ_R9Kkchlni?qQ zu3<7f1<nM^j(&`wnwyd z$2btwng+#~%+;GLQIk2^<91oSyRzi2$%z4Rt@5+2xCjQM)ua96h@PE_?Pj%3$MW}T zCKwVs%zh7JS|99kyd|d_6dP9eM}MH;mtqa4l-%cp`s}4>RA}oke{XwckJl+&V){&O z(^*nGb(PN(=^s_UfkqgVVR~I>`lUq^4&L2?WDN&nmXqmHA&~d&A&!fDX2R(+ zY$*ZBr*fAOEY$BXtJcvUu@!b3HDn_j!`dJbkF5QRGDC)f|6wnp0*>D4>kBaFhB~ z+~Mx~g1qHE?OPi=SLuW8Hj^_ZpL>1%eD5@wVtbA!4HRC*e=doFGXQA^_cdlL=I5`Y zE4*a3<0?p zzJ$V=W zsaI0-FM;;}7ur#9ZKBk$P$|Qxhp7inM*AEj5x*OHXNs!Cm5~jgdX#>Y#QZBk0TBNk z6(D@phc0M^az_{1W+m+4aRNOtpn|1>I1!T9Q3Xw{HcuWYY$cRFQdRhl-zuwR2#q+#wc!TjI{Ng0yw+h8v z&J%_S`5+lWoyPheO086EVykUSlwTl;zh?#G7a=NX?lye1+HQ_df({;Ni_aiefTJYX zEk&H`D|EEmyL@gq`RqO?NF;t6BNxSgCwUiD0?M)!OhHU4peS-maKzuk7OpqcuuTsd zA}FlznMk7zz}9D|QTdB6f7Bw={`%ax{g{?lAl1QF?+PYdVO< z&3H3PWpm{uf-47`S0SlrG4;$a2E1R%QR>jmCt=FIJNlsQk~Y=NfebqeJ8a_QxQ3zhDkAca2z^c5uMj;uLon-v!`(?%e94@!Zr78K(3r+m>Y zuZR{$J1MJgRMXSOg4*`Cge8+_C%GZ+F!^e5U%QHdT?}Y=+%2EVqohm`Xwbp6pW@L- zDV9zZSK+I|Z`Pju5zaPTS_RFCLz6(*(nbB+a!IBir@MF}E?}fA4?69tA{_7D_g5ea z&|Aj$t7(HMA4rREN<2s3txz~$qN@7TOO!@(U{%>0D6wZLo>D`&J$vY-5V`^Lv%DTW zU=|wr1c=jrX)Y}tIZRL>0KUWf^P#ZB;69+})nt-MEj@N@m)xR|BTJzwEp!g!=O=!I z-G^=XM&R1`ts?iFV?JNV0s~YXG8rDzQoVQ_ez9xb&G37ZZ#C2zJE0UYyHQjIC>ZD9 zB;#~w@rB$TU)py0L+UNCl+sC5jjkBdzn`Li!bR{YBNjbq96%b07#HQX+uVL8e#3hM znT%v>We~04iG-Uf3^~o;nw(5v)u>Vdp$C_pSw-xNO)@5W)AYB*=hu1jEF~KdUukyH zDjFG!(hhVsJEEsVq`=Db$wG-@Vw{UN_x-QXnI_1AEhICeXEe)u2uLwoMIlD+`2~Yy zu3x~?Si`X9adx(dO@m|Wz&GA(ARZ&M`*uD!32C%8b1~86rKy}$ag(}eoGnT82WZ~( zsOR7iIvD`zETJ~q<^=tQg0xqwx`c&D_^s|eQH#S_dz5eQvZ z;u_GqulB6~#WVV+0}8J(tCZb_x6c(G!=iE?mBDMkd%F*hT1yr|+)4Ev(Rp5TT*^#x zEhL^oyG9nmViP^?arQ&*_zo(ehl(`PlSlW5{rp6E<(#|wXyrRCBJ6e8x|iRwmg@!b zK}Pf#DmRf}-RB-^-_+A61iMk(;mPt@dTmJorc}VIQGV8#s)P&~6u0VJj zxyKLY<;~qwYuCzs?Rvb_*gFR+3U+Rr&HT)E$Y0Mxu9SOw)K5@$z3=^u=Um(C#hlbE z&JEe!1rDavaG=dYwgzmaX6<5L^QqM^4t3OkaWp=~{%!i=%(|go{hN5Ndn_~93*Iy; zTmOoGyWv{`8EC?>_C2w!pY(YJWfLCj-^LR;EE6lwAS3SP@2|&iVR`xX3|p`Ak&e@c~A$l;FkG$i_j zp#OO5|Dq)a#vX{z2L{60%+ro6UUGUoe!rP`YT)$*%UEr5lN{?E!^LpeY?ED9ibOt^ z;0hk#qy~Q7RG6DUXzE82g?gD)rF3A4=cD*KxZIuO`BT?9n*7cJD&880af{REaD^l} z(qP+=w-tB%`nvfpdGX~00HQRrMXzb8PAMZ3ibWRhPfAnX2ebZvHvNTA3ZX?$GBZtI z8uf!S5x$%z^mGEg1AR`wMxcW*8@I~6INyVppD-Crn(D3VaXS5zNjeU+DDlUu%!&xU zrW?@a=f?=itFGJPet|thoQ&akQ`I>`)vhqOiu8;C<+gkn1&*oA;!OykPIO;-R-*hRVTLd>ven^Iu;BNvXl1`pxWL5- z-rQ@tEMxt=C+v;Om@q7jn2-OBhP;kJgl7PnR+G7(+Y2 zkYhwOsUWl@0SHZ)lM*8gNUiTG9qCYt zFQ3yS;^G7E0UZLBOkTF70Y?|zHKJsLUqzFqdZpl8Z?EYy7#|dCiaqxun)o{;WRA*X z0J-?m*2k5zS$9)2aZ8=N817UbcUS#_F*Sk{uWXgsq)-mXt2jv&e$GD5mKj)90fs>KH{fWkTuBwg0K*6>Cvjt z!YPPdf!^X6qu?n_7+P(#&X*B?Ou^HNPSA1~YCx=AhFCLkcj-DzkAM}-Qw zhN%4#7|Wk;SIdr}v@Z*%AO4f$*_dXyjhBT=O z8#;=g6ou(pH9jUGQRDoqjKKFAPxdzt=V&2Pu5!SPk>2Z)ICu9k7$u8ucQ7MM;36}W zfcGB_)oAB^@I(*Q3NT4`Td>0#Xr4~Jd&8$7kO$8?hu+_k6)4VA2Rd|Y={4@@JOh@g zW@@QoHi{5S&a7w={6l!Ywd|#7hGmC5*a7{E)R=Xp3Jft}*b4*Iq$9g1ioo_+OPjHY zFu%DioJU1XlNVxcMJqH;#KoWA2KZrDz+PLmOOP}HV~R5n%xvLh3M~En6b=*j^!gY! zyYnPj>{XUNq@!~d%eiuWyKPVeTq`9)%kC+ArH(eF5ic5wGE!Y3AfAeNa0oE8L_%Am z`(MB|5Or`4WLe|-{e0@tQBe4(G%gzv#xbaDc1hIGg7DONrMNGtS~mtDoM`s6cB{Xz zl?=Cpi8<5SU)zIn7loDid~(kSy-thv^AN{Vgmn(3A6;6s7kpRBfh36muvBiBFwEgikMfi z$0B=SR`uwS#lLc2N5ld+qqT_ zCBYkYvVc^PO+DIyGNRh%`YfxO&VPlv9eVcZRN!JeWlI3N)_-Q3-ON_)KqDXn1HIuD zsBgdPjEoUQI@xEO|12Vc#T#O<=^@HiQA!L{NXf-BboLrG!MI=>seH~-9HI8mCwCVI zn;E|k{vY+u+`uc8#)4Fi2L3T4`1d%`{-0JksX>oY@SF%O}DDOOJn z3QFKV^vBL4_mDAc;p&S^6casZ3(iZqrd*CJBCY*g-IYK|8X$d1reR=Fx-e^J0RLcA z+7dIS4;hvNe}Dpw@Mel7MXANrIuD?hP>uehmN7t_J?#4B?k}Zm>CUEgE1AUhzNzW0 zVv;i@bX;7B_nQxA5`8I^c1-^J2WOrpB@b$y45J}p zTZ-9U6~zsBuiN*DW*36eKJ(YjzFE!fje=8ys<9RVM86I8C#Av~ zPvSY1(-eZrsNiU1%eE|?hyqIo@}Cw2vxh6PmZzym`CCp#&MxNe-z+#VwU-j|2nd*- zLFEVMTXtxC+zvGT)e?uh9{LcTBe1%L&itEY2;f{1zgV==)oC+%=xr|GK3MeP)kov> zs8>4J_DgjBTvMX~yPg>C!ACbeKi+4T_kpyW4lSmr9jpC%uw^o6sDqB)~ zi48$3us9?ibT8js|k+pF^Wv7yLhl7-ddB)uh*;0HDI%83~GeEB{j-49iwZuc4^0W8=lg?;Tc zNf3pavrD@l&Tq{XIX`RdIsnJ2;m}2Zx+JQr1u~PD2y zI>XQxPb3ZC86JP$HOpO7P4no+#YMAG8;J4O@o0P*UxI3L%~wCFjGlX<{*&~Y0}kAY zNzW(M@&4R(5p%J?A=8n1I)}lV)k4LXM6@>wI8#ppVkfZbP&h+p{js4!?DJ!p{X#z~<~pn|SL_2sAqCGY zhO~-LB8$Pj;bMd$Yctg{P1%u&og5{72d(UM7Bh9)k7WVgi;k>f-9ac@fvJFH8t#~T z?S*WzyC@zDbfR@9E8RjGK!Ga1{`D8;MAh5y^uD?=Tr_!GmNcM1;dqPvd08>Jdyqk! zn&^K?gpM>2^Dup3t0mp=aZ*YQ2Z zioYW_D=Qp&0{$ z&(cQB*A)K74q60oi?2N@7WM)0myT>C3g5eOXh1XB<++FpkzyIOh)pk=j?ZePI{w4a zK|z4qQD8id2kKoSb2kG-TER3%xElD%%O(57q-o_yyhQ=Y9I1nka{Pvl_~a%>gu)U?ig)`d!z}xX>j5HD ziOJq0iM@=o)0#2@$LDNC(Y5O1IbYo^+42q5DsJ1E)`T{=%6XBUsX_>5~#M zXfr(ZNew*j<1b|Op9RP8-b%=$?_^b8mvp|{E84nPXPIrA(bDyZ&}if`eH9G67S?*& z-r^l?^0yyo{UM7jw&$sRq1I?s>-bAV(~geNM+8^qJZi|j5*)ehks33xtV{G7Cc2W4 z8)uS7q{EX{zO4=Lc72W!qbo)=;03?%LhC?OyD`iMPk%1yFt3_BM#+7Z zeXMdY2JL6YC5T)HW$m37Y1cD>UGS+)2t<$^$7or@lYd}2vyy()2Af$RQ~kE=3feCw zN`Go1#k|oGuEa8P!)BFORCj;^kQQLhQ4VBa-)ODJ?ht~sh={9URfwr1a!NE^Y5!_~ zsMDYjbM7`)rwKvbnpYVETk7Q@bItQSn|1+6q$-ZJCwJ=$R; zk#W?%2Rnko$<%oc5{YQkz1IBl=7U-A&x+BK^3lPUfAFnUJ0E%AfC~^%W&C!CFNMMI zPNMvdxW$TR@<|KeHZ88pua9~ml}t#`-poR6VDu+qSbBFtcC|Onh_6FL@e6~RdCBwNlFHFaYf;P?ID?Hy|jeZKyH4)J?HqX560ADb^wF8SkzjkF>Q3Nx(q>3WLy zlowt@|IXGCiFTR7V#lnL9rz&&~|K}rF1A$-?O3&D$r@AXxQ47~Q=Ktiw*IBS!B_SqH7 znA!v~MLKgLVR*fkIRePeuUU1%1gw0aO8*;BlLq)OBt1Capbdk_jm`EbAQ1iUP@-<_ zx7alMQ>r!j0#MLm#rE}~=*o8zM7$Bn@kenLP1J4$60S?JtOMJr~aZKz+aeFq261v zl)_uGJ&P>Rsg%`vICf)ZxjSzCH&Tn5VzSruKA>O2LTxRf4&AcFr2JD?QE2cV3Ys@s z4{TM?(sVXS5pLQ@UC{l#{6y%>mF5c7OHGKPsQgKnvY!>N9ea3Rl0AuwevO=h*UT+s6l#;JqSdD<0cYi36OirfKv`&k~(=84Zf zv#W;(WFoDF~?T)VI7ee0_jZ>n|iY4T;hot?t34-TnHmzap7Yq*_ssnNGt@dhS))!U|e zmSZJ`cZO+PI9BR%*--3n{SWcw0rOSp0wqFead5_U@BD z152k0dh>+&g$In*%MzmKZ_@krE*8l_^k`^fk>C%w;G+ZxmiB^*HJDEjAKNceTL|J+ z?Isl$xQ@Zk0bK~nxN{FlCq#ttZL9igL={Ob=v|JiQc1m_mXO$XJvCZC!TPoDH7p0s zTIv!Qf^tge!FNHWw^bC&KxQR#%bx7hwv7-TlYOMxH~J`P*EL^Zg`O$xLvpVl@FsM^ z6#lG;S~&1+P3>N;tM%@T7l92Ral&_ydd9l|LX!cOj%Z4Lumm8mku@M0a z#g9Qhj{h@@v!mJz12_%3()s%+^E@!qbhn5qX0-u|bG0T!v1$X#0BLkgiG>Qov3aaH ztK63a4`g*HDgH#O0y%Mm07k?)q*p`qku9FE1kXnfuzMZtoqV-x#(zYX?Djdd0^EH8 zZ@V$rwx2)(&H8T)gw%WRdR}V;DdimKG;=9F9c;e0?vTY0 z_Y$KXObABftu?Ku>k&UR<;q}CbKanNq1p4|ttP;=(M3EJvVTWI`c%iwUb3Q{0P6td zEPkw1qrxWVOe^6Kta#*Vl46GRZ03OcGEY#5B;l}LnnV!U(F~QAG#tyXKo$W(iG5^- zTDx-A^ikL)&xI=Ha|+WuGXgs++~d){Vog8=;3+hTiCrQQ8?LF+Zh+OR89_zk^nVcsq9u&=L4 z@CFI`9o_T0V5jvJsr|u~%j!&wEKErWiEyPx--v(>7z}Uz+A#na3^l{b=Re@k*hy7A ze%wYbpbi<>b31H!QHBe)#6{(BjHq`6YYChW7%Z9`zYZW;YRM0oxmo+rjO zYf;20U`74!-<7rc?3CfSX~aU8H)Mm4apdd4<%^y7Oj$lI{$vM0uB6-FZ@@m+LLI_e zaV^!UNu`t+c$G_$frQ9G6lGDVz5QEw0WKlhsc8)XLM-cLB_yV~qhhW@8dSS!&Gq|` z2Yu@%j%e(1>OM8#p0>@+LoGX&44xyDj#pl6eW_R;)(z}i+4{&T1OMW46N+at&H>v& z;6aKVe%L4|GhbC*i@haY%0-M`GTeLg2YwGB)!r&DgAu7L_FwlxQwXJKPkcC;Cc19; zqsGR{72*iYwDGe-HI?cnX0a9^@aD_dhcKRo$ipsoSJTAnKqF~d=6&(5EV4^7&BokR zC-kz0C>H1gyQ>UF4$qnmHZ%t)$VwMJl2_YVfzlhiSGSh#KK}la(Cf{QE!vqdc~-I7 zQ%g~BDj*XLd?Tlql_GH=j11L36phuZI;lFLF{4P~sck|6l`+A3QS|uv^>H7(JZc)i z)UUAdCPfzYETp~^7%ic${*`g?dakq@Iq;?nX-?4@a!iP~NDZ-AC*0*9FnJ2MPHu(I zXiW{IjnlEQGFXOm-mYzOi<5T7$t2rQ)Ghk>K42v$?t3HrxmV177K%4I`xN++{C-ob zAgdw&7_)N7w9?vlzucd+y4U@_<2sjx)Mr8C_sn$t8~s31s*IaaQe8K#hm^`@-uzQK zFbrCI9Z6TgUbC*%gX^?{C56RR1memBRZsj3Sy$4#$EZOzvcf`EL~QOs5oLxi@qo$N zx3vcy)~UeK_#~X$LxTVXNvQ+EAKNLB?ePg*(Gtmv0 z>fwfSu>`gZXZY5EAD8E|tA{4DQuC`JC@bD0RE@&mRgojQ1p4jn)*ib9_0G^_LXHcKxY2~p`wjNyNDv6>ZF zsa1xu)-1yThq&ZQx|gCp^YNkP=wXREgrL*qql%z#&)<#c{Gn<#w3d_=gC*NugJU)C z1*|5q>~6MfIDfz=zPoOzLFwJClvg5!*_{Q&GZ@XPU7_UUW69?BpA)e=PP@Uxj*!Xl zAierZ54s$yre+r7g<(-qs@vE(ml>enGBYya2ntb?Q!mN&HTgKVUSp3{z&pbm1gV1p z)NAEjR3FCga*T(n!a-?`^Ku=aD(5<>8Rj^7*C=v(<0`~FCmJollZx#@RsJdKfV)@M zxs;5Akw~$Y!-MJbTB|C-U-#GdlNS6ij;^(#36$lVtji^qXr=z3tll(c;M4l=82n=0 zpLL|oOQzfn29U!ILZaq%duJtr($bDYBgDYQG1rG&XD2~FSqllY(SuMKe|SAW(>rY$ zBPu)5&&JzA1tFrk@|PIIUCLvbo5Ik2=L92?fh7dR19??^^>Ia@!aTct(7Jj5R z3{HsBvaG`e%z#2}vuFKpUqcnjM+HTd!-MtE6X2v8ka8*%+Mxj$AgJZUP!9`8%oU;At|8l0a3~3}=}vQIBB57=V#!bNqwf-KE5!@% zC_!Q=`9Bi2-Vx2R4DI=hE2u_}BFw-F0R%4;1_Wc`Uw}g~wC0r)f@D&NMwnt(~G0i366FeSO(adLvi>K(VcBFk3SMBN5y<(K8<(w@gQuxPD&>}UmzFBY)FO$TI|+d;l%pVtUU+Q z-kk4Z@)@FAPFtZh%K$gN+AmkG&pc2v+^H+MJ(et|``p`C zh7FBZp307RK=m1Z!XLBzSfe71jVPdGU99V9@bFIkbwkO`zdV&_C&A8`_ZwY}U)|IrbNBK>h8jKUeGA9=wbtvqKpr9<7epD{GsbZ^_TS<$Jj znx8WReq)q7l`lhVM+7n-LcSsHeM*xqX87960Cd#we?!0UIz*!=-yU$9#g0T&)9GuL z-z)IHC!Z#A3KcDadxA7f^tn_<_($;=YzX!Pie;y27;CQ#u%UF5kZ)1oUUV+!l$e4E z%S~i5lwtv|jfw-x_CgURVSUz?9tf^?b^D>jmH7`a3j>~3F6+BWikSzpP&o#9vQN*) zfC8tizzU44(OLF=6=_g zY%vLpvlwkxe6Iz)mxL2##vmR%7BD0nj7#J>=?Z|@r1dj>}AB zC&!7Ql10Axs0~K)Bu$^T;prnbp(=$Y;#7Yp$AAu>HpI_5WONd3)^bI3e)w03#8O{3 zzfd*$7RQV(nMq=rl5l>oR@vb1ED;3Dwdg{;68+ah&-3h7#QSgniyPRyLI1y zH{Srr9TW+7d7+7)HFL2Ll<6YH$=5OfXo#lE`%B)rq49QF$tB-LDTs-hK6XkG;n)1p zMcIl}wUaqi)d7}|)y{ZkW4HNz0YQ&t{>51&vVG7x`~Bc=EZu}-kpxS~9u5`F z(cYMbXeiX5bf`8NWo68m4jT8k<0vj$Bs_C_O+c+3**80H*oZ)}m{T+pV85rtk!C28 zMDsInDE)E}U-?r5$Bfa7m3jfch_kP=L1nHV;!M64TalEFJh=>X*rUe^(#R_5!p^@~ z6jOGRTNPX4;&Ata_k-X+{bMfT5@V#SfX9h&#X|d{ueRJr#+tmKl3vR+`?XGgN?# z-bpS+9*$E2+fAIr_ie*$sG03GWwxSi5b(HR8Ll&9ypdA9FDf=tLtcs;2%2!jX#sQU z6{K>jN8)`nm)hk|;Gh?uK9|%rH-E9NhNy<0+iJ^nSX8Ghz%O&=zwD?ZvG$8kF3*#v zha@s%@1pK>DV*YN-O=q3;9+4DqIOA2sYRbnltJ~*OEJCgP#QqwXIP!EsYgn~-&)MzPKr#g)~^2T?kTK= z;(x2v-F4c+>TINh#dD=$ebhX<<FrHW{$HqPq_J@NdM@Doh>E%g|`p(EgH~oOAvw zKK$NqfIKe}fmxPy;#I`wv6{X~Cry7L4BLk5M>!hw+=4G{nxp;&#nS}f%jfAq&kAlb zw|MM#6RYhmt8A(VhO|FYQ6Nj%#(+F3q=bLm@Ec7qX=W$`QS&an=%s+2$-=pe(M_+m zq+_bEGjHYJ!jHuJ@BN|RAF00VNrr&rs{{LN?@UKI!$dir9mUSe@%GMmh`U9(DQ_|iZyLXWr)JKYGR{o@`B$!_&>6y}1=MrCh zsJ1upD|@d)YrYadxy178tL&Hg>gr33&XIv{4tSP9M2ST!oCq^DSBmSl79F%HnWs{~ zp~ISOPliEnX1?3XhfDVSGp5WmC$Rw~noguUj)Ap%u_2FC{`(0-2T!hV6+g~`qhA0l z0=e)E@M5C5s9Nt^_~8al>|-z3d^w3pmvuLE zXw2ZB*j0FFz|w!~aI|0<9AV)(PGs!p?l6f&_}(zf@?-V(Kpb(;JzYiR>_!_XpPvoO zM>(_%hUgv5 zNTssiOnYPN4IJWwrzr= zyx1&DQq7l_RuVU4%p|JicnU3awW#I=fG2&+^evn8pivCChQt0?C^uB=1`Sd0bY!5y6jo&Xopsg4x~R!8VmcnMyRWDc25KlR7&weQ8mv`vB~ znd@T91$@B&gZk=W(0HTnfQzcF(U$XF41=n`DcRYsbQUS})gmHuRGurfWq%`W{1llm zb$>-J%Ykz{;hkYk`UkV#;+1y{BBvlBmRhd+&cv%JBomp%cyFIdN8@z#lGd?6J{VW&)UIfW#CC;ZBoRB_hCkjErI7i2m^9p;voME z*`RHxcWE7LswMog3TkBu#o}%wI=N!iwL)E0ji!z+x_q5#P>{lz=RtzXqj#u!EkY9% zgLoWuWs9A;k?Iv3dtD$pCAtWsSb1DFTFI&K8`gfPLu}8a!d>qhk4mw!OgJH1?=|(H zi)H)r26qSRi;2XT4h>zxB4W&l!yxPp*l`2|Y`?$&%(d1!0!3c?JI-<}_r2Sz&xAy= zNIqWGJe%@Q+0HS9>2V78Zr!#|cLm2%d+eT?W!s;NYP+~Dlle3ZTFY}kU6>0gUT2}o zGCh#*Ez(g9Tf39CNjuZt6tDLQiKI2@Y6vqhiyKo;Mtk_%S(x`17boVq4g9KZ(L*Gs z#lVJnjpJ9&4InYSvfA2Y@}#BG-@LdJm4p{$$31U<9_b9O%np((fLU>wVWl4RzZ*y1 zyrO2pTv*+7DRN?Hg*yvaJFP=>{&f7{zz63gZXxe+?1IwY7F=d(M#a)Sm(SS~)6_`x zjBqXyspV=%gTMyRxMdQ}BTJ_~awEr~A83X)9s{$9|GlXOq{VPCN_vkL3h>R6;XRhZ zk8?Hk$nn=UIej?eTGXnT0OP0dJ+Y}R+{^%me#ur$)V}-(dING~H2XC^RxL-O=P!Zm zuEG^NiJIeey_ODf49xx0zrK59{#<>!%f(Yj;We4l@BO9&Z-|SaSa!=&JVXyb_)=3e zQ+Y{DO%c|dw(aZ53UuuxF1N)y!>=*PXX|p$J-6PspJ?i}!nGuaK4d1%sBZzxa@c0) z59?26aEqP#3mPI~RyWKJ6J9fEChj)DZJutVK_T~(4%JXP8L$!BkW7yW$!M**a>u|n zH^q5uo=kEj%kKS{oiCT}G8;$>t(~-tpUEF8X{JdN5-?x6I@ZPOFo>Z?EGi|W*4K8s z=j~J;q)I zya?0&ZEs7t1TcCo&~}!6T7#jtc1rv%rC*QF&^wnk^8Ho(iR1irz_I_5(eRfO1`sM> zO=LLqvZ|_Urjn#__xFoMQbj)_6)M3srkQaoKLtGl z@tp-<<|1z?3-wMVi5VpFiq#IDIW|u^Eumf6lo}0-`2xM&UR(`A@#r2Q$UMI*hMC zi7Ao9$;z@y9?w(W<_hLQN!VZRZX%!D@oq5A#K(=#LG&2F=uh}znT+U_=OF&szv|G7 zs^F`Z*8(R~-&uRH0B&XF;C+hR5AfVSOPajm%Sx3HwK|Xq8k8gY3yg9m;m+=T<@bl8 z&Ca266X8#tD4ye)3ekoa;uTqQ9v>9KG<-u(qbP&iFISbLOhq&^E4V@|-EHvb3w8M; zMi=&6L7w;EF0JV&6**c1_^^BxgsMwoV`NEaB|L3jBCCb-n$c|$>I!)pM$9Pd^IZ2( zc5vuFk}q0yI5Z}%hNjCrTKLUI*8}`O+Q{AHh1yYoQyPP)s{R_%04#V|R@^WJxbmO} zr~>S$^=uGr3gJ2=i@T1u&+^whlCPRI;TjxlrI-u|EWAklLeJM3W1+Jgo9K+oRQFBG zL8)mOudp-93X>W(g$NvR;2`yH`=}+v0>QTm`>RXA65iCtl>$WJ*seae#m+rE)}g*q zC}a(Qyg-vLwcjVzOgb~x20-%9mrMm0YcX#I{zVYJ529CKNzc@=v9fL>1HcPEqe(uIO-|G!h^Acv9u(x^&HPBzWdO5y5fJ9g~h z`yXL{HdyA;UmLSjC;8RfioZA<_~?#AzN4^-fC7e3>uEgsNZ;#S=mVFkpRklGluK?2 z!Z|$CfZpN_chB@wtCzdAC9FqHGmV)#y}~SVsH+~6*jIKB^y=MAw_f>hFDmaW2!Dxk z{-TW6opmc-5q4z&7I~_dBMsge7ky#Ee>djV5He#jqVuDLckFnE=<0b}I_$~)8hbzk zBqyAKgOkEaBN*8LYAxely{2myzb;wjwAV+fp$x^9vvZ7?%G@cC%R_zgCRhGoV250k ztH*`!JUxXS9NkSFyf)Eua9e-ryKctL;M;Mc{6)tG$ITKbO@p2ub`!ARda>JxIXV5! z(*hFHS|smnrT9CclA}SLutX`Rg94N+cL)j%PEdbG6Cdhvv_jCf!O(@(w#SjpmH0OP zY|s-FksePVE{8p28EtCvd^WwS5P$mTrhImvV{(KNue_~=_Eso#B%s)&wE(=@>#(>g zt-?PNYa?;kY=Tpx!Xfr_ROWP{^Q2SDoLCUfnFp8JA04L8^##wTShLK#_se_#J!cD@ zK-rX@X#j?{QW2_>7gfW3aL(S@gjsG6zRNN#rP?a~+E+B}@oY%W-?hZle2l{qvFwHx z)j96?f8-WSx=34~S(EXc%iLuQs+!d7NINotHlv4n^}#(6z(5mcNh+J%HHOXCD9NNq3+Gl=?`?BPwtaJVBWD|7Z~FG1-JYSJx*_AqIiO{Us`E7EC(k%4<1oE z+ET+iHVj?v#lAE&l&r})_J_TOK>WVFQQn3t{pn-k11xWaSV&m`*a$7cv~NH+Z#q(qlM8#v2yIcBA=8-PAtkYh_5Ez z=1f{lsfdj$-OiIm$f_J*N0BHiKTgpEUd9N_Bi(;OKLT zKW1$Br^yyu%i2zf4hH|6)$dNWfE}#2L~6%EqsZP&1@O;gzv&q+$>}V& zN*FzSHT_@lA@zy5)OF=XQC0Rp6{7f_hV(DI>W-pVD0=|P>($w9i8%0l3|rs3r5?9AuI1WgE*9CQ#%;5kC@#HVy)GsA_9M5XZL z-OXn>c7PQNaYJ_JPX6BVLeT$-+M)#~pg9e}2j-GKrPcJpt?<gY^iw!Qp;NDWxCyp#^|Fq0=c1V{SBp|(|M@dk z>+QsgdnN=t8wXoGF7iM4v%MeV@j71;#1?Ynr>kb3=j7&2UDVE3C4(?1&1!DfYE+c} z{tYogZ`nZ!<|8YJ8H43P&B4<-^+I{$mW3Mq;@o1;`G&m{m!r+C9?2!*QC{LvZjOAh z0IRTUNqKnLRc67xh!wsjlwMt?u9$pBHf`yTS7W9)S}B@| z(BHr%C)C_XsDeQ7^B>if3-cuojl%Zm_n|G-)1UjMKnN)bE$1^Gf$uB4gm9#jYpQ&vniplTePA!X* zQR||$pj*1ERZ(Af!CNUy8*QqL^H48f4}_-F#Bws&m%sz5X5yMAM_@lD10uOcP=9h; z!}}Giy4T?+4)59HL0M`poLpos#8+D(nAp@?BzFcA79BR4VL$W;oAZBO6^F@_V z29F6!uc+qTL--l!iVMB8;HvracW~G^iiu58>Mr7>kc}Uo(A-4CM-ilZq`q_zFQ-xc z9V6RY->#nut;mU)+%fCZYno^dYU~98Q@~>I`naZ|ql;M%2OW?$L1ys>07*`6Kh^k2 zS@e!2M+t3abX;*?jXQm-C^8NjFi%#sy`M~*#-#4GUFXsiwCX5nKypx!X+o0*(HLAHYngH5he(6LE zdg3#$SJm6<;B^cPbfpST&crWMEY3$QbLJImvDnlTjh@_Vy7A-?3Y~2#?>+;FIC8EW5J)t(6cM;yzmgdK z`O0;%c?=_~HFG{T^kZ0gFFZUAFd|?JL6KCk)3vA!Tay95ShPC_(EB>ce#Mh9P`ow% z>dNE06d8G!EP?9K#*68!NZw;vG|urI?wae`fPvh3Q`%{o^Pp#czEK zJ>+IXJSq=j{S41-Y|CW|P7uuwLl`l;R-w+fVKp^@>U{PS2-`~<_3Mym3}WY+sgmN% zfpAcru{EAcE_hIzaHwKluZUXIp{}F|>5#qXT)Z8$A^fwJqxXYZ4PQ=TbX3Ed!9Nl{ zO{l&9TX#~zfci_gd2c%vI2!Y!D6h>TIT4Ji?uCvCr@^JdESTkzG&_}w~h z-6H8vRG{kL)jgaLgB@wV1jwZGAcSJ-YF|XJ73SVas@@E94!Scx_MM}Wn+zRL2!V1l z?Z_x3p0UsnMd~PL1GWp|WYE*jU&E2?G^j1(`7STq9DE@fp|kSmW^kA(>}@$8#E~e# z?Q%E40YeP}YD!uNNeeiP(h_0%^(Nm1udZFhx4sQaY0$~VgOi}shKM|#7$O6X?C~<%@i(pGiv=x&(OxA7RUoP;^&{dzruEcbL8|6zrotx zj5We*`ZGxeP@;7EiZL3;`VKE;rjM}Qke)90;CN|*m4~(L^}=K$`gEgyefQAb=(4en zY!FFw(@c4F;;%!TdyV!%AptK_Nx5YUlkZW*vAiek62Ksr*w^HJ%1JL^;H>M$B_;GR zw&8z?*PCh3!xLH00ZcL;P{HgU1;$tCAz8>9gDX8+y+luSfYA`+k55$8XvMjWZ%XYM zg;I25s|NaHjw;&?Ba?cC0MUPJx$+wbVXO#}g>EbBr6$LvDzDT#*k%&bM~pNiQtiY6 zw|h*{VQUqfENK})x`~ceyn(s~q6oCg111XwF1XJ8Cnra-aY(MbD11}jq(2n^G0o(S zR^qoaskR_oB6;-rN|qxsT(6kZ0zKcQ;=QTxb_*4nSQ<^Zj1 ze!I+Kd?;-3%F=xF>q%h~xbz3G4bdPE1V~3)Md;EhVM)-xBM4E^e~`o^mME z%#3d@gv9U%)czv0>6t+Dv&zF)pI^Zp<)pzH1}sQYMls5|`P%Q+UPT0z(3W^LtY-VyjY=oiJ=S;W41_U&ab9j*7Xm_EF8mB+`UFH z-}JsM-n1c`YSlAOVGs?{eK1?)bl&bcsZ?-FWyO=*Hv}dlk#Il1`Z8x)kv=@aQFOpreI*XbmtgQuu`r03;0B5ZlCFKVm*1woZXXYSmooLH-dI^w8O9FB5(mlcRF2%gn=5AM-z4?@ z;}*jG@q9ik=%n;d3ly0L_nHUvi|I+YE3CvtLxw>y8-9>h({&1IKmrf4x5H2$8<%Hn znanE|HgDu9lg7@xgj% zrr#@yQKLBvaf5;q#FT!LwK||Hdo+`tN@YDWpYamwy&TqZprd-%fINy3+DUZ=zeFe* zpv82BUtZ6F(+?~2exk$L8&Vu1CK0MHLT5WDpx*4XH4U}F?ke@Ox}@3Ms(asX>w0}~ ze9#Ku9VfliqSEh4yI-Ro*3yXk-Bgcij`Wuh_5&oM+X0oYfCI+IZk`HpPFseKG3dO_ zA}W8ZN2YaG=9~v@I_y`VE@?4IoEAZ*tZrXWs^CFgR3VJv<%1$4dhT=>GaxW%!XdLF z2s*I+!O9cCX7)=Kk5-MAhsf=vI~#yvF!{zionLJs|GT-*vu}bEyB=sdEkN9S>tC?j zXIQOI=SA{UvF)&&3(9pWz7)T zZEaS>ZgP~JaA2~Gsn>lMeSfP*_1+~Py4jJ7DkfG!;&z`{ewUL9WFRHzh=S-&ET*x! z;)CEk8(osf&G-#CDY4%EKRa|fyinktu+YoHz1L?B(s6rPr=v2RAY%v|(*z9*ELqJp zF)fDW!HGh}(iceEDgBILQ-=|=V9PXlX=>RfJ5?_~D2xz+*GXp*w{>R&>~3E~d+P`86zzH-S24T5F`h+X0V`n^&jE&gTm5cC*eaOU}Y>y>YYg zlWG^n^F6FSt`l4mNtqHfrp}_$`iW(TD(*7|EZvmaB;x4S`npMtYw?^2kq>jd3y3r*laJA{qzAgO9c(;5WEiV-pI-5 z_Q%0zr!K&Q%J}C_7+?K5zw#xrO#eeUJIIv(`qLKlgJRh!=M%pOOE|IbRp{#3&TXJ2 zTs}5N{#~j+6;ix}Yh~KRp=FNp2&1Li-t>`qVR}FiKiHowKt>pcKo>GO4Eu ztHg;h>>PS7tmTUYlM;K^@ZrO#L_M+L*I#SCr9`SVqAjJuw>B)wl4woGtDNjEOJ&<= zyjcy;D`%k6s*AY$kDK<9h;LE}yK@Oaf*fcE7KPC`&iy5& zZI`JXvYoT3K^6H-#S*MJcJ(7m&@ZBtZEp z1(-tAF7W4Pe)DP}ia7yG^~Vlq@$VM>#4OQ`Y4#led(VXARVif`LdjmYZ z`kjNhd_J7?gVwA+ajP^rgU~<*`{X7qCkZW}W&qUM*QFHf6PXffb@*!qD9EaZ(wRY< znkOU#Ps)?%ue(9t$xB$a8>V;!_L=75l0VY$)g7Il0~dDJ$8{if+{|O^zW#qj^o}-W zm^SzW7Hw9c+OCzQJ>&&_^sj=dir0zzRLE$ar)xToCESeT6H6d*Y({XNVVW#z;3shA z1G#hEDXY6|u$g>o@+{Pitvws2X2daj#KgLVAQcCidb+554lnD9BA@mp)ZU*biMk8d$`JfC7?)||C7KyJS4w|2pRt6W z?N!c0B7vc!COW*3!?OfVnBwI+5 z%=VB4?A$6`(iLiLT#M(i8OuqeLO3l;BKHn4x^7F?x7ZTnSwd)sl{RRPGH3rk7jNNd ze{BQ1s(FHic0`eh(YcVN6nF4=ek;8TtdKRtmQ7Rs8l!9D0n(Xj;Mm$8p01KtDV=t9IHYC3oAZZAxY>+y9NiKdYF` z)&ERdXVUs!5gZK_uOUMoZpWh;s0E$CR1{IQM+T_fB1VtK#)%E9Qj>h!U4Q*LvK4%v zbj(+;7&`)WgSgi!gb62Y?QUcACi7NxwKd~z^Xz?4Da~lZ90pqER2_#GNELK#x zA&AqCpaTsfN#+k;^*YonL{zIT28xT&cP2%XE;6JK_5<`Ev*ToY*(q!}&-HH0hj_oq-Njv8xA?}Dakj|XI?(@Xr`BAb`lbi$~9X+Gg5A^ z^s{fB#Gzb%o6wuqR26+dyk!)uJ8?e^xq)$b2ozJMI9^G+kQd#)bQjDcvg7(`s#I76 zgDS~s4ms->bFB{2dL;YRC$kBS@cuwcxmqSs{JGty<-FOi1VO;}5o=9Y*=#^Fec4nN^s$Wza zuy@XWBQf=Vi|FSXY5rc>FU^)K#d8s*AfgmSJ#phVg02us{!Zf&sa7f0C1Vf|?ccPH ziWoSd*I}W^a7*k%#Wpx${kdT~eN=_595XsqhEGzohKlCw^32lxGsmIV`0Hmi66P@R zsA%ez!$-B_91kU73gZGdy7ild9kO76#p?G(e#D5@dGI}UvZ!3BBr7dJ?sMMXv#hZ*OR+7+BOE{3>Jjpm5b?UB>@>In z3dF|ZX6D<14gt_f-u^(@#{g4s08(!Pq9DZD@TGo2@#%``XwCKd$5V|LRt! zzk0qFb>Kc^Z9+o4#NPOtjnoU}hc>M`?~b^|j6uD0=2Oii4J6meUG@T;&CR5Feprfd z8lD?-w0!WgULv&3&|4SJg%$(!yguUaexbt?6gPyF?a>)8DYBg)HJb=#c^z&Vw9Nad4^apIHJerOPleM7 zMXk$2(-A9+4*)vsgCsk5CB=T}e_)-e-xW@3$}7?)e7l10QPyAyt-(Ok2+NnwLv_vC zhI(>5bnh}$zqYjT2&e1$zABg z5gVj>YRyvY|>7zm9%IQCc$pQU$Q) zSTvf{lh^5mOkP7$SUgH~NS2xSEIUwZNhNV|A*f90B(^cW#w6rnBy*RB4!)5xJ_%Sh zFC5}Ev4dt93fhS#%~K0tx4@{oWbpE=;emw}9_XgKr9$79%R zCtITkse{%rASD{CoGZa!j4v8xN(i2dBzxViia*B#Y)w~lswkUkEvZDa#l0e}rEZAH>N}bdw!BP$?xtVkbx5TNO7W9+BTg&1~2C}`YDaqEGbNOzOu}7n}+pvAq!Fw1jkX?oa zAu{9`tRD5OU<)t6DV{(=0vwRN7w0?>2p3C66Gkw!sD1l{*e@}zw9?<|b2GOiYI=rC90*2NtVDkGY}!DN(}lF*;wa%ks^I$ zb2fxy%Ovb4K{}maYA*(P^Q%~okC*Erq9>))l|;NQ+)`Zx+n^P?&(qt;Een5t3-rT+ z`kLVGh~IbHbT}7j`9pb2iJu(=^6WAtO&lb?{9>w3j?MLX5-v+APIYV}@Fm61T?S>% zAoeu~`G9|_aIvu9Oiw+{7|l&`Q7vbE4|My5XvxL0#0Y#Y?vRCZcnE;l(i8y8Leg}d zl6%;=Hahes`G;*_RsMd)%?%1~ggtOVKj|jjUBqK}!jIqda&|z){x!WXz@jN}QfvHQ z<yRlU4)aTr$$-DQ|^EF2L85_~DbR<2<1Ov#5Gu^1*LYC^Vh~s%V7! zHCw{X@IkpJLpT1~nd1n4j+9jV6S_}xKV+r$0Wz$Leqm7Q(1WC&BL@NJofMN(yea4r z$_@U@u<3M#O4}ObH_BoLi@LualM)%Yy`&&JRjk1Xi>IdJjQ&LozuZ}D4k^mLEMBI5 z%XA$GC)pQ8aJ*`TorI7T5OU(Y-1pN}8-s1oDpHg!=&%L+=Q~rek5T`-2I(?N#qr#s za8N=(s`Q7tZ3)oXkuvXAQ{*3X%qf8fB8DR1|3tb4w(2{%BcEgwNddRO9~4_l==(Ykhz{d%5?V~uLmP!+$mJd;S2Z6k zE|<&GM|z!$7DXYbW&In8a+j)>Wm4a{ADJv&UE|) zT|Af5P9Eq#FtkytX{8=vfmc72Mm#sqmn%UXnl_4LXnLSr9Nd@}JMuIT`unBdONx__ zvssnvM7rpI9xoU7b^2Of9h|>9#5cA3ov7JNjP<$<3&#&b!48&wP6v$vMQXVcWH4On zeG`FVq1iZslq`TP(DEB=s+Lro-dPs0ro6?Uce9;~j_*}JrP>FjJ5@o(l(y1t*+yU*m>5VygOdG4}4$bm2^8kYwu6{hWx^V@sh>w`Nt}>GBF^-`jQI)4B>+o6w7;2kI!o>y zYrfpCuo~o5(|mwSY9OVk?c!!vEUDCuj3}rII@QuTerf^ z-1q<`3tn1xRh|We#5m{geeFBqB*^BHe;X#lKk;T2WnAs}?@!;$-K~3IThD1|>e~$Aj+)oLH!h$s3q2wcFpQSdKAIsN zX>?%=PdvuSPSd$o=Am_w^fT@9V!uIsNqxYadv)#pgn`=NJkJozBJ~W-PP$vykEN0_kbEvPLnaB}mr8&Tq5&u> z@N5bni+`*jZRRR3ny|y&!MaX*;AAcLDZg#BN-2uV0C}u5Hnoky;9mx&WG#kf&!=h} z6Z+zhP}ckD#L=T5Vo1ki6aB|E8{Xzy+rOdL;-CEIjlrDmSr!TKONof) z$xawFW=i=A`YuXZsHU($;*84h6*?AedhG---lglJ*azSy#^#ghHehm0yvbrRtUzSmN z*7C$drHymR*fUy%mf@=@XKIyp!#cekNZf+sjuQlIo5EhX4LvU}Z1Dd`HxCW}zRS6R zvBzdA)n2VzCa2u&o^>PQk!>wK3p6sy{%5!3{r|!9YQF#DOojZY(0v~36(?q3BF-+y z8+Fk{^(;Klu0MY>?Gl|2n=|?Es1Fz~pogQ+%8hUUQST^^8Vg z{yxQU&VYW-FB19qXmY#s_gCz+;62}MzF&%-2M+^_bABr?Q3Q#TFFxN^?JFM;TEw#( zG+m7JUCTYVsI<*w_yNtZ4C}%nA*N+gV=${i-&ToKzB=~s+md(gsK_CcCtaxA~dNvd5AL4#>_Vi!0LCZQC4 zLqNWsWzaX`!js93!_4C;)Xd6ip51PVlF(3KC{;hDwRkdb%IeYPlC9mKJBg= zOqIPR%OjNL!`t&MCOY{fztwvRE@St2iKtM5DoqHz%s4iPW{wPP=Q$meK_YiA?n8^(oXl-oqKat zVgyHH9{$kp;6|a(QpTEOHq9#*@GVSbEUKJJ&|eoes@R|wP-7x4-qCR^m)#g{Oj)j{ zfaKw1<(AZxeTj$s23;I~0?S{o>yp`{Iv-NEUKz}1sy^QRETf{W*(2n9>R(3e?W=y| zik+Aw*@CkO zxG@Ucc!WA|i`zhO2D`F32au9~#`%&d%Pfz+6D0}zLFfg4WMI7acc>h}XT5`iT4jRF zKzo}=_x7YD9@SZS*Wsos$*bpPN+6?%`6V)Nxehgq)UBtm!rGE6MV4k8274bA+$V7b zYU*IQHk*K)xO;ILT|=_3z`zD+;if^n)~=y*6#+yKqSstX>K_0^R878IZT`i_aXwz4 z*x+(>xz4oxRj}(O2s4=OuZ)D%u{pm9S9-2A>>S^4`F$28i`slDBIp=`R=2a~CiDOn zg-=LsHV%E*9jNDs)zJJY16On$kk`zIrQedT(fgxBs0Zj_VzSJmZCrnim_$GjI(^HScdBBIPP@3*B-Nn>O`Y90Re?iS z9g&@VP8ya_RrKBw3&btSkIn|0>`L^{PgY}x;n8-!{tJuMzUWY(dEjoCxW|)u-$*&m z_Ie1K)pH69D0$y)p^Dg zK32`G1}zkX!9;Nnw>*%*3^%dsbVvyCien&^5i5R!J%P8`+5SN&XICy4j!Dn^2e zFImk1n*5~-3=5a44(rm zRRmv?=_JRau0W8_ z3Q!;pM!7%`r${)oAlHYymKpKmylJ~?#`V7y5YKLS)44r}X9_oxe+%`j>a(g9$J}fg zPs}z_f?|VewuS(ORuSyLq2SF?=DG#MN$Y#-O$RC+U&*V>hRQg_4yaBq@$k^AQZ8eR zHiTLy`320YFTbcon^cz!n?u|Xdc->E$HNKgt}^Z%IOmD*GII!d{oA3hN}ZaSn389D zpH`JvwUkOz4K^n#p|IYUqkR6`cw1tgn*Hy^C_T}}%J2nM2&J&zLfd130?N!~o;ueg zdwv+Er8Ql2bmpyos5Jk>b@F@8Th)x6EG174Yi2^+QUl9dAJf_p*Iu3d^4up{Wj#G< z2#1QMT_9@p%zk;IK6Hsabsi+ES72r*A<=^VRlSPjp!IsKh2VWT(>_T%R{9xLbd&j}j zW0Kp(LpcVME|C8HVyQ|iHLZs?q}8O@&H*wXbpJOnNm#>8HB}~Ql~&)dN@)Q+mE>L< z@@B1-AFaBn?cn$5*5xGixE+(4{xj+b=TFZuC8t$(aGx8EFLec9he8oqA^YO!R5Y73~@2_IF3ON*LuD{vk(#Bww8JDPW@|s}*)sK~;+CPUnx55PK7_ zXuZi+=rM=U^A6-xh-%3xV-0%=Dj2*^l`_8@(fC>w?&1 zC$afW^yE2^=(_YVPyvbR&bXdSL1c75y!c1^1t39Sx5+m6X`)D(4}NZ1xi9ZsiUeH{ zniV!l#Ty=I;(F3BKm}>~f8oWG%ak0hEcmD5#uoA~wC(GiKNwnxEtv z7y?31ohDy43UJx*nmxfGJw3uclgd&Dh)KmEzEbgqS~L&49@X<}m?8&A#9-yPtVcqJ z$D1sz5r^PGh#-q+q&+ENdC}ku3s=vVkcM$-YsYf^Dj5&1T0LWkQj74CW49_U)zAW% zcni^MWCzu6Rm@qbk~s-Z0msQv>7)i~^!GD}Xx7Bs&9u$7wGj-=@N~PucONm}l6()F zAvIRC8o)5?_sxHd_;aHx&eQd=7_1crVEV)+xe4nL`7+tmkJ2=@pX}@{kbmvePYY}e ze*k!P9;yvJ5n{(cZ{WK0+5CCUCPBl0wf^{5hWfA4N*|V*E~4fzHxDC9^$cKAG=)+; ztm5i;hQ0p^tb!$f)a1}jc>QHX`q7;oC`>;sIw0|8w)xm@9;*ewX;fgH(E$-Vs1VTB zMXk?0ob(*8sW&&9#mF!?a0Ss}*mx&%g~r=rP}?(4AHU8{V>+;EOXJ zOEaWwQsTF?tMlchLQ_y0xvB!(pr^;HoFxJyCex6q=ypfIoc)PE!dWMIiyAGWM&`?= zZH$buf5oA0b5=WpMO(#D=#jqErbW4=ox*izgqc>evuBMO&^;8ZZ7Sc1+3(gvofr@g zD5}16Je;JhV8}<%Ar9Tv$a$qYtAM$DHPEfH^_i(T%ucU>hYVb~&q7iw#yKFdwV2<% z%8)cGyj4J^ylx5id^r>_@U|7^hkJm04atzY$|gZjo~uN9H9BemgKX)c9XXcNDu}|? z>T0kf9Hs>;>9>pDNo0K8#c^O?h?3m94SP_aMv#x?_aSxkY+ALJm=vGoZ&@2yVp1u; zASru#9%n`{D(!G^UmUvd@>!3?CD4rw4Oe-NyD18Q!#b4#Pbrm#rne%{32fZ7O8$Fh%ze>%Z&&gc$-5{xy>}; z5^$Nx{!)iuQY3fTBVC%AFl#HiCdeP_776vm1|K5{3LWDWWJPA2P>@12hZ z8C-h4$0W%b=-ke2k|*nu@>~UGe{E?p8U`b27GKz4w?rEHacCsXdEkpK;a^torX->J z{qp#xcQ>HbS&E{{lPT+@hhV$aI;LKy;*Vy2r`&38P!+RdjnWh4=_3<);L-5D`9|NP zT{6}yw}xA;EyVgO3d4YS-@{~j7EHvscpZ*>DJ!MP3DnW{E}I_az*qeIl6h}eif^s3 zHiJ2mQuBdK&G(uW#AcGdbGl>JN|M|gF{^)*efBTcnx-E)j5o$M#fFo7Jpx|f)(1`(IbfPn?2+wY;vj<9L{7|U zE`QPjGak9@m)8K|uCW@MbSb%rpZvis>K7|!lOdEJI95KHW17-_Pf++Lqx?PIjvl(9 zDrhKE1xI`8Oypal-_=y?`(*IWy_yO-@i2?m1+vxw*q@qFu#**$90ELvgC>T9g=opgqRGH3Ed+<*)v6!^D z1y`Vd)RkTB^J6AS%NzGyr{TFer(V{}J4glo7=tt>_$4&Fxcr3v!__7ag!aWdnN-de zW%b;%4iAfEGBMq0oaIoUvTE2`fjRk{*bjQkBPe=AT|#@irdwhDgjzg%#q4Jkh5gmBztK#hO^&_7<-<~ub>pYbkmEth~YR!Z2gU1_Fznk9q{ zk2HKcVopZ6+u>hU6Ef`ix@!E7Iiw`L3cG$in@B&2KAWIGcm~NLqg%jfifS@=O5h-7 zBRk8o>!}Z=G7l~GIZ8T?^ciVlx4+lrSxtkC_9iun{e451ZKD5`1PaxGvnIld$@Iu= z0$B%mRR7=%;Je$@j3>*i^p1JuMhRIpD^Z9Pjo5Jq1B~c#k+(RrZDMSr2QLcw7E{-d zQEC_#*F#TvsCLlE+J=!6B+*R=baD86@M6yppr=Ams}Bptiz1!^QNb40m<^_rvx6`O zB?{hD0BFcAm0OnYCM^@Q!nw|hJ$SX9d0iAp%pm|aZuGz*efBzedN3>yE&=2U^a=oZ z1$VfuGF>T^P2HCgB)}?ram6D#Sxf7jQCUaWFgK`Q`5(PoPiqQm7ILjjZ4Nh{6%2uY zRYg;BIE&b+<9;8~5Mx?+G7zH(Ik*j5GQsZe_xkXp+o#!;iVKy$<)(xC6xSF-A87Z+ zJyQtp`{ta3FUz-R-AY7*_FRPznidxHSSe<|K~-y^7)^bZZvx}uXIRY zar@T41&8CNeS@u6mBaAoGr zF~OCXNJKUlMK*M{HSP$N_o?r`1YVZ3$=E}g;P~uO#Ml#!U^dt)^0k{89qs*4@e#e+ zD`qs8&-L_asTP>lAz1w>xM>AtY@o7Xe3ySe+In*&(^REw7^d{y0{{5U zyD&3Hz=JE&v({*cSCWTNsVgHFlz1+4jVIwA2CqsM$Sj7scL57=+L}7JY4_g=Bl*&4 z=nf$NTZSkWu&Eb7zVwG`qD@?_qI=P?)`e5FH7+e*B^JMLWzA^$pI9!S7=r)WqkXsu&%WxnDYOaU?g1Ts0v;E z6}q$Z2kBAHf4VBfjvby?A^iJm$$^EY9&>yp&1_0~Jt{I`)thmM*#08}G%xd|c;J^H z{ua6MD+2JI2D!Bcfi_F=N+^W!a?#w$F&OpWP30mtl$vQ;i_vOC*Nk?Vp(j^8E`cZA zQhyK$1BK`Cyt>I4^NCk0TMWdOHb}nD$?c+-9+z>i*m0S)PDemoSgQ;0>7sUOLxlA*VZ?%It2&3>~xuHvrsDNz&b~z z-tb%p2iv-Q$TCBNb1-CnzX(QghNsq1-82>7E@T3Y)*oC@hLd18^Tqqa z`^gZRSpXu~Piv`crBGzKvd&KmDWWY$8`rBKuYvg9l!qJ%$GuMUEt2?#_k(``t4RF3 zF2rl*0ePR-%4>?gb0U=BaFS0ez9O5)6M^qjia@R^^IMjm0NvR#rRn2dME;9NVMZ?PM_?9 zBLoMaIJ@pnex5a}f+HY7b)B6;>Qi-c*wfUs_uV_xZj&X&kf7*#N(j{FLvGszIfeVG zfTG=+-w_55`(7|_NHp#OICy)dv|S1utGGXzRhVF5a3Oj9_)t-X6|EH;rUque}B%sR*pA`-1ucJ0%%KBLkYV7;@4Y}rDk?ol- z%O<1rTx(NA1zu8-^jDzl1nVX+7+fo0*qc`ftCw zaoK*i`uwiiuix%6?mVvtxwBif4SN@fUB#%V$|$QLNapw%&vQGGuy;S|&2FOBSQIn1 z203bD4H%<)mbX9J51`d&l}F-d!>ZbacqnKXDL&5xNQ<7!|A6ro?1%WU_1BjWG(*W= z0U>4#r(B}Zq|TS2-4};$#WN=Z(*0$(4y~olfVvG|=O70KsU5}sVuPdB`6ei(Sbp!j{ zqkdSsJT6(^6Oa+eg41xa16N;bw5r845f4wS*Wytq8H>%j-05(P2 zqUF3&(W71HZptP0#UA{LRhyf7NG8jjw)XEs(nL^l3{XVfRfVe~iFiFXjGRNOPOh^D z)(YF^#r6SY5M*n`Q$Q z*Czd?l3CEYeD)#a5#cTs5?|ga)DI-vF<`+>U8NF}=`Zw;7aI#CHMyj3bcPu-7*aOT z>juEyeYb_)>NnU%dU{_k8El{H!;fHAC`v{jmKD3UzRolF-p}sv1WzZT&}T@3FpudE ziw7!+{$nl$A}Dl415Ux|vc2!+2gN5;ZchTJLkz)8GyP+c(C&Cv8EC6wL_3&Q7VkXe zHcL%v;kb*vKD7ZR!bzbovP-Tx1FBK}GiYh+pj-?!#NDk=P*E8nTATk(xC~`6G_qJ)BdIF)syyK>DR<5Y`j}0u~zS(cynQh0a+6__xAI6n==}mlR>6? zQ-6(As#_trN>rFy=V31KGtOdc>29)^fQ+;IE6rSX60lzZ7a%^X{z}+~I&BI#_304ZV0}Y@F{*TR`P#qdhW7NUJb2@v zf(|_7l^L&tlqAhPQ#k-y&B(Z-^Ui1v9>b_`&mDS*=DQg)3vqrdSy<(kNfzB_rFWg8pz zL}uD`g{54JA>*{BJT+sguul@gnQ349+SA-BpNL$w;TB%+4i{?;UoQ+Xe8~ zC2H6sTx>h@%E$ftAE=WV*~jEZM($RcqIW9x=z1x{PTXaA>E8d+rwhWaw-JvI{43fAm%hel|J{HqZd& z`+=k>D%!SDR_uN)b7B?D!})may~#|%*D|)Zq+j&>FoiHP{J{E6i#0Y>mA=X@qh7Kx zNJ3_8OCVo0;K~)Ed@-{GuzIChzt3E2PG&LYQ4>MpudCfII|HP`A`T{_Qoo2ISL@|< zkmIUsVp&+}UR{77n;IDpZ8sW*Lmim_A;MexH@M(ta@;-_PeZ z(#NBRj4C>rCovjP^=;R>^#!m2z9Y=j>mmavi`7&O$nc@vYTiIFUV8`j+nNJXAYbx_ zo1&Z#qg<*7q3lIPEp&6@9*ZIa(AuA-4z{|SALMV_Yt)NO%N<{BJn z(h5H}hqx&09K&mH))2I$yCv0J-`*oL%WkuAB$|OCTw{!o`tmBspeg3cH>b;(;rSWa z#)e8{vv-)q*G~y19d0L9!u=gw6@po8dC#%q1WBEd)8CQ9XfJXR3BQli)4FgbQHOms zpmz-*vcqQTRs>Yt4UQw(Ke*wy-E$tEg!;i~LE%bapt1_aNnzu`Ne^{;m)X^CLvj%F zl(JyirZmb*#yYIIS!FeP-4QBTU^a*mk|l{#?ysgN7!{B{9N|z!Tl&>gk-X?FX_P@w z!B77(Y)K1bpGlSP5fcP9N=*mcHKoQBgu|_+aJfJ%F4NZ9KcOeu>nox*4l=X$hb8!R zXc}P%zL}?h%kGV*-9EeKr-OzWP+-*zGOQj@H!X_7aeSF>_43^dz#+xjwZ)aoCKN?K zuayGL9Bdmk;HY`w7*3gn$Gs%;b~P(IQrGrDpPHMER3ZqR*i`=TmC*O!uRZ*W2d3&Q z+z_Qy1p&rv+W0?J$Havh;2QS!C)-g50T*8{7YSO;AN_udS^4kT|3Nc7Xe!)wLc+7z%e^=+V2yi^Q7Y!>XPK^^e__>-W#HB4A25hg{9w2i_lo^z=iSnyH z9)~uEeo5IkILw1#EAyvEzcr>rTPBU&|Bv z`vDn!DVT$h*!c?Xl3%$=<|bRZFcn?W0m2Xsbc63_OKecY_CndpT+%RM$nu+Et}wgU zm>j{yK(B}MZ9n>Zv8&~9W)-yAK%XX(vG-k_HB-A<7^+tp)JjF5+fJX{B{8~_T#YZd z`lf?Y5BvMT|A5tGH=r{jv!1+qnLS7jg-8*WJT9c>N#z3rd_ntDaI253%8W*y!n)wJNqwLX;rnBF zHdK-n0&EkNTME-(#jiHIsv=jsov8<-RO>V1Y-Z)1S zHf<1O>iXXB7A(4QUveU%kn8O<;nkdq%Fp!s@?aOE#XRg%B42~NJ3Jj0FXnCEa;9Jm~Dbr+1S%IZ|o>=dr=&+m3 zsI0CbA^zeP!&P_C^x&{*Q$y2qYm?7qA4eOj9=utsB`Xfh=Jr)S!>)haLJ)L0^$Se{bO%DsCU&@L5VMsA*g%@Kj zgL+-KCHC>bKg0M6{D*u*vjg3y@mA`FPpJ0z@DMK>q~BeIq3Fvw<|mSG1Plt!WA8y= z85)vTq1lTteO+hICfq^#XO1jHxC6ImzOFxDUC@n)MBzPS?qu4w>c|{mK-+oaNj2qL zg;1e`0jQshAXMBmf$?wkH3MJ+>JVTUA=By0D=lnQlH@?$u}bQP)cgqxUnt*6|4E4M zhx=!gqJl>=4FWsnKRj7wUgQ-VRG>nx@vV-}NSpEm$4+qSTL@aT4y7fdAJ8+Glbs-h zGKLxTA1oHAEp%>jkLk~wS8gZNi`mEBWa*go-Q@980p$qb!hS2wD9)_|CBFRAvxYUx z3p)?l5oTp?vsH$DnuJeyMWc9@V;IR4?@Ezbm+iA3Mt$fB8v!QLOu%ebUn^IA>If-1 zQp0X8iPI^|XNP;;oz+~x`SZIcSQ)GY1ZB-G70vr*gUs2h0!|GHgA{24ozu$QU=%S& zRizdyV2WAk9nTKv4ilDogYdrx-E^N$P2tusp?v>v#?amdLBSMMCPZ=!nApI z*^y$Wr~r0z90pp9t{Xha?U(`Q6FpftG2|2sxYHu^>zrY)coWh39CVsAw3|?_=wPAU z$@@U7v=0nU(b?#Ay;vW*8A5PjiGfsPkVe>*zSnH!r5rD^B`JRtW(RyIkX1~H(;=-9 z4Z@09CWQ#sJTqtuKy?zi1=6tr@w|2jmfC0fs6>&4$!l%6KChwH52O18A zAtPA(yxq>q7;qE|-r^yM#v`{zdb1rIBT5$pOZahZs}uF=;{1|jgzFD+rY;bj&H{katC zKmH8Q1Q3?3d9jn)lZ}40$1vor;z33xDePr1Uk%DQ!wtx#;#-51;R)xMCW0M<+hUoy zeGt59o;rGAP0vY7NrL5T4ZN;%0MG7yYdM3bPU%QC5ydq;ab5Lr8Vq+d&cRlB9+F$# zXl4Wyi-fO4>G4~s%ALP>l6UdN*LT>@JX0aJx{aAk!lV=kVvi>-^{zF*RL#3UL;e#SP`rAGWKned?PU4ck;-wkyt zICIiC`G_8_V;NpAZ-!1O{o+WSY%B7{&#Lq`?mPXHZeA*m1sZXpeF+Qw!S#c^UuzS1 zMASg-6Z*!wNWv=x9RDNX=Q6o}@ZyQuE|1sBB5 z6rKyOiD1DDn^I$;gmMo_L@pvv?81;GUK%=-SK=L>b|_@px^z02dm*^n5U>aTM{s~X z$c>qXNY1C=cZ5Q5H7DWVW0jYAX~Q96mjO!tpy>%{9I-|GzA5t)jBy3fNX>J~;(pFK zXb6ZhdmDA@Q~}ZP+ezF{{Cix17o?iwou&nDx@NLwv7Md)$j=1H$z`N4p3r~&(Im=4 z%Z*)I8Ji|QR79H2b3+P@L=iaG@1}Yh z%D&M>YbyK$0kIfajFMa>OO~G^TTH5=i0X@Za==SEYIFS#A9_)?L@yN;lDw_z_Md4w z?+98ni9JIN>hI^Rx~ibi!1PWR@B=s^9$}$0@O6#_luD5wTYgxzA$omEZO3AEoR$gO zq7Jmu(V(}de%ry)@3ol3b}x|`JV(?k`WPAU3fRJJfzne53F2%NQt19yeZ}i%S-HB= z^}|Kkrlvvj@i7@>41V%pLg3i|q5pqc(_uq*qjdJi&eEt-(52N78@n2(DH5`r2ptc| z;95PJMd6q(;MmhU@Ns>ZSejlKa9o1F>j2B|u2DcRB9AiA#`?y7Va)j}&tg+88pc$t zft5_@F4!hN*Rl5)OR876T`-Uew$^HuJr-IUO)abWDTDJT>I1|*0*sDM{YXlX1vsDX z(?P9fedsp_Q)ji&Xuug`eTcUxO(W?Tg8-G<_cg*2?jk;sBkH67Tde}62SfXyk;$;> z$u&Z;N1JoF!UZt^yYcd^;wtM0*BVIdA8ilVUk1+`!fO4}oap$TU+^yF(O}cC92Ys2 zYOCl~;_|QKufZ^&`r#2zaHfN--%@WZ0#Jh7@2B4ZMRAx2kbh)6B9kdo-0m@{N23sU zz$1Bjn)LQ+AjkrQ95%uu+wwE&ab4WQ{F`(l$+c{rTn%M^AbWRQdt$c9VXa-!VUG>6 zUav#ZriN~8o&M=>N=+}uS{C+^2z8U*$?fWU(tbjaJn}&Z!Qv=imERQF&}!`^Q;g%y z_;67jjzn;-!shVaO>|~dJn+FrFh&<|HO&jZZ)j}+=2${SDNur)hmky=Xa_HuqRDWi z2Cl^ZCWqdK%cL-bj4dS2UG4SvH%5g6D%v~B2+K_N0RLyGrwHc@=X7Z_1l0|d%c}aE z=3pbW&`}1BM-SLS*sZnoNIiYvTXI^J({1vzdBD*zeAL&23GW7AXdKAJoy}BI62-f> zc_A2WvP%P85Gyp6r#}nkuZ30gg#mt?9A8_+aEJ$L*^#++rwYXOX0FqPUwCBDwGUTE zK8L=Wax<6EQKY5mwj<#~bUBtO)2FSH{wVOfVFPT>^sNEXFr(J>tC)ZvN%yXx9!GS; zIfD037K9=hLxIr$TVK;df6c7kcgi$Ow{oIK!_%19a{5E}GsM*>b=gX?43y@?TG&*x zlm9oNR71%C8>0=Ix%kogg$E;W9*k42ZKhMVwjgualEQL$_+U0qr$ViNK0-`#Tk!68 zj!vO{$BB>WLipZ8W!M`XUIMOj8+HWGH3B3&b8al1^_XmwP8*Y;KJ)Z+*SeU&9Z@rP zsS5yfESlT#>;@F+HXR!^apVOr9@5^R3QXN5^O7<|ib#Kg$OmU=n6uZz3JL-0yrN7S@O*R!ZYAdB!sS@L!|?6VVm4%s7L=()+pnfF0V}k zY^iVp%@a<@9g+}H_dwA!ws|*iI`{uXeo}m3akhkiVduK+F+G&t=KI=isuAS7OtF=% zkJ`c+(r)&rnzhg!@dfg|!JL>PZL)EiztcvABMU_?_z=CHyB-RA{FB+^b+z-d!$S9{ zfK8(*_1f9`=myBQLSdkXq-SRrP`x@v5P zwWK0-Z)Hvui33V^B|R;WiFYt^Vpb9hAz%`DyJtqMTs-afViwx($YJZv$3j|(6wG9qQs<&c9zYeM9Ux11~3c4K11IeF)6U;yFJFhTI zS339?u;`1|JxEg&7KFoCsFLyc7(eL=e&|!W;F)VsaHbGkYV)~;kho7HeTX#z%wDjkB>?4~O zQgf>nWXML@w~*uKz!sLN)>5lswVP{czhsQ*k<#8Y5>j-Db8RmNYPlU)Vm5s!A+`$ z#+E){Kqh~UF}So#6fg}&FUWm-pZW;881pht(h_SbL63p_6!kc*3-<@^>!YX)m40Ky zR4zr|_*x}=LH^B5NyFF}m}7Im`uc*xUNF5rl-D;CGc4J>0Ax)78~9>(^|= zFo12hXK%oUonbXOVIS23jLS@W&ZmWDeaR35ONUNlF@~ilruDZZINT28O4E1tKww3? zE&3(n<$xN;9^8&{rG`4)kw3@WL748NSItiK6nm!5Yne!7QML?j)u zpulZr?{+S#f%9}LHH+|rEJFT_Vlc!mpU%*DiB(CGz?2qAHf%7`(#n6{n5(b5Fy)?c z?%2L`-Yxlpqbz|iZ9y8HW~&;dUz&Z;B&_WNXR@8E6v8wee3?~^(nf2n+o@Q6YI&OH z@2^apaEPm&#e&m;%@)Cc^q?Rvm}zGA;;N)JA-sEO{-7k{;3$f*#A?r(Qh+T)NxK11_ZZlN$W233WmT^PQG+1ESTJC3ab7-l-eW z7+7oa@bjXf=Y!mGDWl`E!;`?*Ef-iHBhY)HqtT-Gj&(V@a-w4TS{w_aW_&r-pvsqz zfK8yDk8A!T!fb!!Iw`?bgs`6SO#0}u%7_8Dbt@QGLVg$VApK^I5jyNw?L<~rTNUYH zVX&yNjHxt93_S&$1*ok09A!^pY)v4C!Z1Roti#X2+gWmgIHdj=8?SbEyIWJhSxZFh zO95Q~3-Tvagt#Xo7Epan$o3o95cSg?CfDc+AYA1gDPHvDvo653AHQ)7q*&Wgu**vnkGzR< z3yaLTs0sjHpJVgnu~gqI^d%~%$jbJ*{fEVu1>N}VYVuiF*~&XL&zkyV!9haA2q zsMXy9v$o|N@ZP?Kk)u5ji>wDmbuNvib-jI;a~`Jmo0KHAQKC;t!Uxw zmWI!txehFw1>`Q)s6_vn?Mtk7avdX(kGY1x7@NTazEX=V7r$bECBc+Zog#oz)jTyRr$I6 z^LJc0-h+KLV~!&zBHJyfz!c%1ol4dO{w+oKBgb&GHgs?pdohCq)t}i~m9R@U8vh@j z$p{+spjOJ=Ze~ezkG1`W_RNQ{!NDzqiR`9*p{b>`jA$|GQW=is!q483pVxDH7$4@n z916PS>#nOr(>6CAlpcEs-p_ zjQ3O<57e7E@8a?&@huM118rad^07?YsK7c<1o-G91(p6Fm}k)jJ9Hq z=ec?bgdv$uKPDB&T;TJt||NXtpUh64B2@Kf9y{6X$C9T{HF04P26%!|=32V(nJ_xi4JfB03zSy?B(jbj31gcoUV+tm9X@*^q1oGN1>t3Yburz?+Ve;E!x*XV{3XGQQwoit7CbVy%g8|GD zflI%^Fn3617Z31I*AqP>S({b|8okc*%#!Yhvn;b!BN|iRm*0yva(dX0qvS?D0#|`d zwy8mvrtj{TCLN!8tl~0-r=lNe{_LZmlbj7gZ>Q?_?4}^DO^k+F`51JJp`Z2Ix@pr= z_@sMrmY#!M(6i|wIHowmjurb_iS;QUg4$zhc;Fqbm2|pPiBec(ogm^Cx5;Rg-{({3 zH%{A3Lq?Uk=_+de2uYFq)9DB2=$B`5Irke!p=Lm5(L4BDb$6xzG=G;l&+(fW$e=3u zMHByb<*LDd9Nzln*%;Ip6|eTJN!+c1miCBC+2D3cX#l)tOhla+%5ZWkBcCAGC6&bn zF-2?yu~v6~DXRCg2QIvaVmb&a=}o`*Z~0YZqldwdC7 zfDJxr^vonL5AoHqCYG|SSh20o#G~I~QKStVP1T>>TP1(o?_CA-9R?p*<5*6CoOe7( zy6<{lv07I*=9D0P##m~gKA7d>8-do}^xhB~slLzpgAGv6KFK3T2k-ph^S5O;m?eyj zMv3Luz(U+ap|UtuhH}1$-i}TVBmgf!(7zT_;Gg^blQD=C@uJw2hYOiTB`r^5hd-(& zdzArcIIsLC7|c$vb#bzyb-5K77+RS5SV4Y(ICdal53v3to&?yreCL-Kfq=KV!nbiSD1r*$_^u7g1_HI?kQwwW7Z1<+1aHqU zQwnd74(~y#KilDIL4sd*f$Z(m3yG)^*t=x@#=ZIO@r?Yx6qbh~_h9Z$vg&hS4mR`x zu}~Wrg?@&({+$TTJS_3w#3At{kRJrH@>0Lc(^Huhd()O0#yM@g0D#=;RO#G4c_6!~ zarL3#L-64Xmu4v307@IMM^JW_fBR0@exDGqOtr6V9#tM;!*V#|)k z*CstLZl;VpnUTYki~Dj*Cg0GykjK#l#aUxp6gzmj;R_Xyu368`9g=nE>Nn}d(|(}0 z?z?-8pi+7v4!lV1sYeh~>?J$VW1BS2SFc_jdpdHLUsi6}I?w8Ks~sOTPxu*Pp#5ZY+X)6es)!5SY8 z0*s_qIB<560(@yr3F)TPtAN1FEd5G(Qw&b4(K=GBGK30G;`NaUtqx`t^Lb}XZiKCQ zm5%frVq-J!@I)r)Gps$Cd6-Zm8vcW?)=SKtYBOBwR9|i_+#-ASfOL&rbG{Fz@^N)z zA#V~$hQS+GgI|~>o#7jYp+Br7o;ZkZp?Ut$j&K92Nk9)I*WZG|9f%_TJn-WgZV*?)ZSvp$=pCF#tmE=+fV3s!y|ZtntZ3i zj6q+0qw)3CMI}}MSrYAlIyHTwF(!I1Os%H`GPUHdDEFrCJJ;JS&oM}kzxeV=lv$A; z;gz*-in)-8N)xbLG|{yG^XZI)0DgZNYx?9D6nGU7iekW)D^fC3hF6Rr<`mddfu6ub zn1(g9;l1beWNPOcNyxjcB_$OKj-GF+5M*EFoeWtd$^mNfri7#Ti?j*-c2X;m)3cR~xsw7^PqD+>6>CT1@TF%e)`La;l3{HT{o`YxfJ#BwdzJsUgsFq--i z1hlL(0)xjxr7zE7Gxh4!MyzJktgh@f@R)0!2}8&||2)0(j9U9i{(96fRUfzAqeFpi z$5g#(YMGW|=0Ao`N5}q3Cn$CJr2jU=9xxfh=|*j7akoz+?g6W7jeS-!S#Ew1ZL^~* zu2!c2l4!|2SEp)KwJKlQ-)}P4Ddif9c3Li2d_H@BZ~6O&JS+DdbS4~sY>f9`^;Hze z73+$a(pl8csB-1{Ve1|6lF_9*XQ=jTQ;_9)1>G(wGd^PxV^;njkYhOj*yb*=Dy+*| zqa?J#c2NC1-&5NuboSQ8S@qDO)U4UYXS3B;E3ttxRR=|g-xfcJR?HGZa-S3__RyoO zB-#L{#4_U^lV_EHfqD>qY;6C;p3e!a7EPP5{;;0en8SDnCqol>Q~^i49#kndmQ$2o8N&JJrPfjitCOS)`k?!ar5h^`;-3k}J`>O> z$7Y+4mXs7SX0LXVpp2_8qC->(FnUpofy^}=W4Hk5?r0=RSOEU5VZ-L#e8Q5bTdwqZ z*!~u;2K}bnq?kEnJuo5V%yX|JhV(mHwZ_VU76nLuH_|!VlU84Sfm2Wkr+{$}34*|` zHdR$2Fli7(zT07M>h3Ld7wlCYtyNAI8udc7irI2nuZL+g{*>*66qD ztyuH-QsMF8rtI8DNy`=h&?MeYpom&}4C;EytBy4Ga@rIU$Yq2^%m0z`ue z^lplT>c=oI-|YR_HQwnR*MJ#29D`6mtQ$Gt&a#sLdP^cTi6Q+C6LO?Om_)|dyj$H7 zl0gwE8cZ;QGWTf^9(BEGsWU>}ep3BDc&PncI!OR5x3P>FoZ2l}kqpM~8=t=nsHU4s z!r1hvF}hyca?CD4#o__|4U4bx@gPR<`A4xVU#1l4w)D&8laEjkd6BP~1>}U}W%_KE z`R%0`N6EXH=?slrY}i6S!lZIJ`*f zR6LA64!okFF1%urLxyruGuVKBdKs5_xr?0#))iqk#2n`Ox~c%@^CZEt&k@!2bf<*F zxF>ebSYd@aA~l2?X%n!^aWwW1k|Ao%1745={`345^5!55>9Ua!SKT&FL-VG@dQTw$ zL#!B4Rp?14C^A#kPBajU3G4U%dPC1;DI(y+kxGS`iNkf5n=@42E-N36+Q@}HJP>!7 zqX7p@HW(0OY%Z5kK9MNevpv}%B|#(-J~?FRd!L+O>}W7MUllbZrl!**E@~$9`c&$I zdbf$VYxwE3@=>xRShA1=m>pz5)T0caHZ)61ENf3VlaUSj>weNLMR0ihZD6;TYTot( z6|JtqP0S`~bW#U%jx=r*A7RHc+$>Rl8n-}cAe zFiiH%qny4t!&-BwQPnNlo&DDb$*HjAZ*Ze1aHf6_83mKH^;D~lXLA#y@x9-{)tKD3 zkSc=&Hep+{PHL{RRf|p~UY}D@K``XVp1GkO3pvC4Ht~XU@>Iodqs_WFS>K`>Jyh)! zDFo6njwpyAGD?@YZf_8q`dTRWp75#XqkKDG)eS%@;;Pk(VeC{A{C&Wid)5xcJYk@x z3RaxeVWnz|b4IsI^dClAM-J^+p8PEd;!2u2lkI3f zQhM5iASg%Z(NXdu2?0Zwy|) z)k~M$&iI*VfzS<#x8AK5Z)a)cm1^5Vq_RV2=`@Q|yB z@cz)BBl!*mklkt1l)oys)(nc;STxC?;c^7xq^ z9cf?eL#^*=y3(BaQ$z6dCQ|Jf`a72aLC>^+r>#PpF0jAEi#pG4EUPpnH|i&v^?*2M zSBo=KrGd(3>p5+jy;-})JmA?zCY7697jEs;AeH4ZMRLq7_$^W#GQC>e6SNJxn?6L2q~^c5W9b0&i*#0VVY>E-6pb7Mwo``4dxuxvw=)!rxahaCdjysg+#G0+zp-YfnL+BpHwc{nnz zpxa-Mt+9gkur~4&f@_jHJ^RT&BzZ{hN8-i~hc32G7kgNFAy-_D-v16w0C982ZcdLph=0d@RbsbLC5PAe zIM^*_{m<;QO$o(G%kUKnKy6%tyzTOlBm{h2 zh2mDgg_qL$s_bSse$4PpPBaLG%lQ8ew;}?IiA&9}bgH-TVQ@s7G~BDNtpV0?38A5$ z2cZa^Q_1~7on&z7ZZ>!wp=}7Zrn-2=eNPzC4nME&Ks>PYR&qlrQ#9$ZcIb-h84ob&E=plS5W)s=s^Ud=z4UgQyDl} z5=2(Z?+~h9SQH4Y^w{n$QwB$}2?9f~k8V6FbUPPOf2ArO9S8~IT|kMGdpB9d6!jq7 zkhKe#3B|aTf)=M{xVL&7n44c+d!VBYISEr%B!K1BhE5mc`n4Kr%4`GaF3i@uLgPZ1 zGZm<;MSEqbTuhizkvY*C@O`5rfG>R*wyvq$y*Aqf(0Qq;1pA6;+>fwj{p@pGMc10% zOBuyD1L(AV55Lq>EdjvJpr>FLm%e?i{#uQ>61LBr!&(@>z~S$b=nR}1ugwnuW^rMQ zuaN{J{*S66%X1;mMyjk=rvUFzM(w{P0+ob2brIFjSMQ4fP|UbNG*Ev^C0S2Ah06dIuQ_75qk+M%+Hdx zLpQHH&EloDk-DSd8|D-mG?`zibme(V*!zzcideyt`U>wJ9iCPvMmTuP zC#}_va}jVHCSIi5VBq@$swS)iLw!$BDGaAelAnULsgVb`OiJmaNojNRVo(X0z9YFz zsRkkT(OSW*_@+}$;gm^hhKs{o)2`1MN%ioP5a3T-N0X9x18BY*9`bY!V)h9n4j>MG zJH)bEg8lOWpvhsTCvA;R!*fNq_?_UbeYfRgDk<^XW%sOTCFd<#P`!6L*>l=K7qiK3 z&{&vglx{yfB-NVpv{BhkYp{;c2OHy+smLhg9=nrmgg3Oz7gN_;W!!`=Z55m&*Gwmp zb%6n0Af3;20nwE{c$kuw_-dNFe6QNr=0;0-b6iyx@YBckNqU}NE4Bh2Df9VV5kK>- zx%!TbDa;(>GT3{Ep(hr(ev_2U3WATes5FZ3^|Tq-j8Bm^lh@<+yZ0#EW4PE3<@kh~ zJd;Naw~HHc14m+oYv7Ii`(N(RW$ZOs)hB>bnhTii4JF*_=u9wq?aZZ%C-A&MK#S>r z0gS9qlg!gH_PefecwXn1v#X~xNVeCH$$H#<`CjMlq# zIjfV}3uaom&;SjeNQcoCw`?r`!WX8KN<6bzwyrR+D({x_&wADUbjc%TlWbh2QW?o_ zS}aS@~`**m(fiJ0@58~eAwyiRf5nB_Zd@ByrqN1P{C=7`F@XvCae7ZV*>ua zdSnGI;ze?6QxefM=}}!B)@o-|=qIGu3+=C*+{~o%)=}1BQ$HTzf=cba)vo|SWGS}# zx*)knJ-+#gIwVMBx+r=(@K;#41#PikEmYz=+_q5T%T-VR$mLH>+h<4lx75 z5&%UYR^%BHYf4wZsz*jqypthS;X6yzPJGMT>cJ`}Y{1h+^Fydc7lJx(Zx=w4()4U! zH)HXsjQ~ppZ|D$SHxe3snQF66W$o#iu)K(8E}Ys9 z_xm^CM*5+}EN=qR=1;tW8Rpc`lC{TG8Iyy3j1u5$a@y5Z+FB*VLGo!QV3HdB;&8~KA+*tX% zQYAV|7V#9=p$$tKm{B&;IoJU*sOV4_VnMV{AE31UMhpPm51Z5^A%9!~8mrUsSNpf; zZ6P40AbBeyCmoPkHn21&Aq9@Xjd+uR&!EkxDVXI%N8aGJ`eH@Ol)|wz35tSu1C>PC z0m$BUt{&T~!Nr1TuPll53qMsph6B1A|F2fpsJu%HSSuY!TLm{X(oDVx<&cc*m01dW zFwzlgnb{OTl?sEDPDOR4WxSyjR4c&tYOmOhrNup2FaIddebA`BV5fqnY~2|03`r=( z@*N)3RH4T%Wz{mXt{n@ggo1OR{!jZ~{N5zqg0H>21~KeRciR0-OmsGw)M9W{CE0xu z5u=~T*Bu*v`F$t4J$70b&%WUiRB9WVk~RVT0bGTrTE4cUpzdxcw%@7-vymu=SXcFk|zQ_8L@HOi?G@6kujV%%Gy z>)AD(Y6C^_sz5z=uvBG)49tme1$v#^ zVEYmXtvXF56jzmjs3Y)Yi7PRXPLgg=Q07+RSO|B&kGWB=xwNw3n6Fyl3?L_G|8YXV z!J(cLIY({K(^`?QxnNuX)>E&@u{M2|X?{5Eb9@ajLLg>ES7aDPJD~*Vy3bBvut63g zFhn&;P#JKrvxy(Csu2ld3@2P=Jbf@V8<@#zCQwsZB^U_wSt`&E#~g;fSQv8bG_Xb< z0N!U=JV$Gl=sjWGJv7(MotUi!CsJpfI7g>6``{Rlenau#F(@7|ktb-^uPQ8&8v(u_^BJr*%!P?lE-2j`T+ zy?ita=LAAPc;1oams5nYhF(-=`PjQ`UgS9!B;Ka;YrT0>Ju~>p`>@>__NsiI(r=fm zDOOAXoo{WtS5?&>@kNi+H>)@I9CyHZ{XWVlx9*gh+N-cZ2as+PoFRb;DR=Z@v>VxK zWj`Nctl@TMa++#2Wlb|S8YI^e+Y^UrLc^8*cSe$!O*JH9`sLUs8~w0bJSi?yU%&jt zQ$Ur6bE4^S{4_iWMLK?+2r(s##%sqCQN6jUdCQ65r{RVSzSHA#6xGZY6p0b~K6pphURU2=mO_|{ zNGDlp3sz*U9Hj~Ezz%GnPZ;DuGP9nhH|#AFnAmNRez+GtgUaErHMQ86Snt-n-65^q z=EAq!dou3ECGB&X@^%1EVZr!%yqzI9s&#lq67f5X!#D!)>(V^|^wcnk#ZL;lC|@~5A?lq^3L%jMjGNiyr4>Q!cQnMpoQPmH!tJI0 z7Y8ss%Y5Rr;DB4KgHJr50##5PYb}?YTSEpxN>=g12|F=_^W^0>)kI1DNWAAfGwwrt z5!^b2HN?!XD_6$ha^{=X0&!er{l(oAAc#Qt;YHQB9d*7iBqm<%x?agB^GPQ(EgDuE6+bCWT6(%^rANFa#UNR0^hz;XkjwvTtPBTp}4iZIXP{-*$RMz z*-8{4-Z&v{C$aFKc_&YpQlH4+VLk5SLJN8q^lL9p8UQ!3|=J#K<`7xZbIZG7k7%BeR3`jd+606diiI1L1-`k2j9*+`WKLo_878pH$=Z2^mnx(I0XtN&SNm$$_0ukb`&oWsyJ$nR z$HHol=?xV0?B(GmK`9wKaFcg2ZB-7-lh>ov^w3xmspN$Sl{g6p2FWPd;?X1LB)A_g z`fy!#-W61po*qQhY~5S z2296aMk*j0I++Ht7d0?a5~C3_nd$v)q&&T7zb_jWCz271IC#{607#qZNT8|KFtA@R zMph+A9V80PO0nPWUK?K+?F!pAh;Pt2xpR!pT-Q?bwP$jJXd0CDe$h3?cdO4^4Vn_0 z78t*@{EYgHI7MbKPsCgMYk9bhyOBa;%3e!k-=0uoDVxqGt5BD}5l-yqBkUau44t6o zO!y0+yKmOZsh4#HEz|kIpTE>>h|{06U|rm(5REq)K!D6EWN>Ceq}aNXx}$O#V6?21 zTGrs=WfrkgKSN*l(=Zz}13#;u#4^zd0JpDIM5Q)v#MycGU9^$eyp|!pBL?Z(UDtFN zXJ>WtTn4rRd{Uf;e(*y=0LIs~=li4I18tCr$~-5fu0-kvx|DoPoqqF|6TL9l@O{fF zscwl^v-o~xkQxsPIH`QD@yo!xp27wdSDdwjUIznHBGaEK?d0wcneBTKa;062b3eme z`yU=BoqnEVGxRj}p{oM>KwSMUn)lR@FVjpp$m2HV(__Y=j!zXqniA0;nEz~@wHxvv zRzZAM9R;Si5_Uz>dPj)&M;9=UR|nWxQz$y}{uvi8lKn*XE)UZk-Y@3kd2bI#x5#}ZUF z$t}tIdlYi!y>I5pRj^eHFG4y{!Axdci)!%+6M<}OAmicJ#7Ip!<{cT=x6CMvSV3R?&u1{y7m<%4MGFoal_xR1L&P$1s0@&=tmZZr8Umuie5%Hp z&o5Xl*ptAlRLNQWez&KP5{gp}r~RFa_kiLH$9Txwn<#Hy*#WBVJcf=Nne5=Ps|cLg zOtsMI9MHqzYnRbQ_#&Pk=_N2imn63Ga=`66vq$gugSrg7Ch52=}#wZ+7M9AfqkXd{$c1ecSr6AEWu1i{*3&*SV zo*l+?i#7c5?#ADYu#`OfUzm^aLMYUreVh6|-@P+!&Tj2i<TlB z-f!o}uA3H8dQB7|;BpA-ayAO-aaK9=|T?6#~YfVWpR?CN5MiS)Wbc;M3Sv{)IczbCG1!d1T84vnAd@tQ8q)yai1QBz#hD`Re`do3lq zWNz+2I;iR(7Kw@Zcjg;_S1--Wqe9$zcbM>Iy#V&3rDB&-K@+GktFpjePvDk>&e&1a zP*v>s?}l~0Jj+_~GF$3+5V=q##;iw~!FI*N83sy8CS%D^j>cGUW<%cp(NocD zuWCcf)UntaT8?=OZWFHQxX?zq_1iK`QJR3Dw34TLm?Uqa7hLu~o=_QJB?Gg(37I~z zi~3I$rwQaI7=&h1-TIF%5&nSE_eXON)UA<*cqb7rot7|-OROU53Gb!_@8}xhdUB7O z?L7*P?W?N7?U}GW;I8h~ofs-1*4JW__%zBQywOpWwi#?6l+&(XY`i7<^8-N5WXi*L z@_Z#hv8C49>{aUBB6BhBDAhLP(lK=_hCOpcvIwNgG0ZiG=0_gc?DD~_2z|}FjDY27 zHkvUSb=?ZAhqs&s-60-=SOq`sn+&qvz(~$sRB$>TsQ8pou>SKi|6**~uQ`v*PPLbV z%Ln%T$qL!171aWn)|9n!#UN5!M0X5bpDP$DoVAZcl zIJ5S<_H}kW3lu>HQnY$U?9@4g!5F`;r1Onj$fe>ZNWoybZo+U)giN@Ce!0zYlEKj=nLUkss#^zOM=l$y>_xR<9=Y>HUYA?ujYCc&R#FBMEm%H_)V0MqQgU zd)f)~>1ATDhCPtp4LJ~lnS&o6kAL`8K%fd<615R?(TxvVDQ z9RF+mwo&^GY2;6dqxv%4{TJLK0tTkKx|n`w>kacwj(UCre7W?=dQi(<7*z~+eXKMxLUh3yP-JErSE*c zg7a$Aj=I5GGL{ibK@<|vAsg9!9Pql)FfDO67Zo&Adu3pStS<^Be?_uC0X3>GZhsTf z5BYltnEQCW2L`kOba1Ika;kWvB+=<2K)=`QQqPt#Pw-aIFfUgdMj2nzSK2a;c%33y zt!Q9d6O)nA@iEfv|Fi!EWp2N-7IeqR0E}(C!~{MzR#*!v3KRGH!+Du;aR%ER?n_%w zy`a|MVN3i@RtjY}9~iVRW{JlhBn<=`jdwI@(k;{FBq`?&zIa_Z)>ogAfnFv{UhQX6 zy;5iy7DQhQkN%6jWi!krpr23Qil__%7(8X0WgTVW#`F!;`|V6INYCb&DrwMbPk#D; zQE`jh;^gGK5j$49W)9ZHBJba{ zX~e3QxCbn|-aJJi^}A`F90i42b`NrJG|>~8sJdA@|7mu$89>-@;u^Pi(~QwX4qHyt z)XHa6CI2LQ7KM@5w)CWV+8Dv=;J|;wnX@dCsYF9*6ngw>!7qr^!WNS!6`KWMFd$%#ng4@%m@^|_iQG2p6;d?^z&IWbNoGy$a z4;rU4xT-7Qk!U70*ukJSlldNU3Nqsu#=qjk1JzaMZO8${QAMDGT2UhafBhZcp#0>Y z>8N3&DmnrDQxx0YoXXhhO#RFZ%TV_aPwoKN;ahPQs{aC~V-=yYU}wM6NIElqHiC2I zDfnHNba5lyt;xrcJ!g&rj90w|TMzeoH+|5nD{HtgefV0jSWA4Jh)maS+=>$7*TWyE z8FyU@@7M7r7gxCj^EPh(~>cQ%V+!9mSTsVq%I2*}$m?4KVd;Q+gGjL^+oSE5FUaQJy>c)jpU3`yV}T;v-fkgwqMlCKra zj8xh!7B|?x!ovZIBk0=ABRti4*x0XWZ=Us%~ORwEn6i=w~l>NU9G`^C^c}0kv2_3cwWA8H) ztx<3IW|*Et^%+^|Pjy3NI+jNZCoQC_jK2#v;m{Up!zp@+1 zXL%9m(JgL^>bZY-Wth|)V>K_x0$IzU@NX2rv-6BO4SFFJ!JUJjFRe$yURg&5ndWOh zd_zb!?mfpKstS)+CGiv4VCPlD06eV@dLj&45$Y3baYlB`#NSlOf0v7cVbPfZeI?5! zF5029P$y+ZF5^H<8;4_HZ`@l?h*DDzi%GS-b5yY8jCHT<$~o@@+)qT9N*h$cOKWS% z(j+hdDnf)=tN2A!yz;wWHhR!J?Zwy+nZDyWl|cp!-R>_i zG$;-jY8Focm`FN8x2#0TG#z)O{J5QmVW@c91ifbeZZY8MGaGRbwId;dyqlPW?o~0C z@_yB0`2Eyr+ksD*)uzC5%P5DQVYfxt*}6Hm7^a?8hKHoS&B;JAAny^4a%ARvoAl>|+LGVKpPU*l?@g|ZT9Vsb->0ssk+TV< z$qtOD^lo$OeCD1S%r>t=U%{kRLWos8sk8wgKES68fJOyfN{UW~^>9cPtyou;MU>Pj z-_Jpu)8Ghhe!yirAl7$O{LZCbv!i46X6#{$|8{I2E;1xHoyX)?Jy3_6NqaivQ>h$`f?r+`o5`%H9*M5?P%c0+tn zvWu6OrCpbL;^(*=yNP?fcSiBt8E({XHEXPD4+V!9UO_d|{|Ki?vpm7JSz!vKAQJ(M zI+mc6m4@)6T|2p?A*t0(Gv5yInLzG;6NZBl`upQ-(K{dYu5jos zvldKS95+{ZzD7{rC}CoxN0M{I{?$P^`(ZR60AoY#Bv;mAVoACp7n~uYT?g16JsV0? zgfjV_xT(b##I_;C`m?w@Jau=sc)jD3aF@yb%X3eP(&)A8tKtpCcac9J=&4Rn6UuR#IF%2u`9sDx9d ze+~SW@Hx$}gMcoPNw5qfEU#Fl_@)KM@C+1L2wm#|w`e@HgilAJFR*W`t$?=yd{W$g z^UXh=g)WUSOzl+fkSTAPw;5s{fPL2Q^;Gp;_K8{PVQ8p99)Wz^~fr5iFxwa)F3K}{xdyre1>1m+V0`G_npK)LDIic zPe`^6%*mLAAgRZ#1oN@A<(aRE&bn!E4>Ub*{@1Rt>0l&Y#pc9 zjktXNb>oo&QLO}TqfS|>lYaGewCl4T-H9sF5U1#StX}CHowjLI{EKa|%6;OTNAR!q zrn4D5a(HKjt*w7pd<1NtM)}#;I6m3HcQOK>z8pC?RRV*mdyziIy?Si#U}X|yc;R~t zaW%0JnaQxO9SjXoQa>3WD6?3{0%QK0_jkQimH6Nf9d)KV$Rdi#5!j*uTZ_BJpppF! z>~O4DLIg^{$DSTnb|RzUul6E#jzC?ltPt=;wM|T%z65ns=g}S#gS%Y~Kw8Hzo-?9Q z>vAOk!fEyY6=V`NY{+j`64!x*w>=;!QxX-HYb0u{G8)RRA~%h$;b#}cKq1Dtm7TzREK^i>C+(GOF#+!#jt39Pp+B1lM&Cv~Rr~bg;eUa%zm>WcWz?;O^Mv6o@)0bNfqAqWBC{zBhbO(pWCTk(m<93@(>TaUbYb69} znuam=hX8LX3fd6l6Do=1z}v*K;48!4y8(AYqbDl)7sE zk9?3h*`zw*Ms|$ZCX7n>%RY46S($OzZ_d_Mh!g8=q15~QpC(TAAlr9Md( zKTmtBalgdEJ;0vjW)||UZE!Bcrt>b!Ok$kqP)$Z>l~=2?U)JSFiiEL%1*rQ~c1oN! zCS#|y@hYXMm7|0x32W~?N|L=bxKA|KA-yuMbW|3Fr$&5qS+ZOrIP; z0vw>gM?*v-LsY1yxa)7Zpu-?`GO26PFl|+VIo1}nuo+vEvgfiw=CtV&D)FnjrU%w` zFht)zx=1qT8)*sD0i1a&tOhnj8R38^C-YB2Bt?Bs?|lW6J7o1?`g@ie*mi2( zBjp&)%tTR^KQT7xKyU)8S@%}h?$$|Mgt+~^r_V%vARR8!2fOb$dl0H|50eDf0r1R> zd27?VyJ*GTDZlbXoP((Izu-E>ShM0AD6~j}X{`5(?45G3A zb>bz)vWt)utVii+qiWQTPa;2DjV~AiK4lnU!pKH2yV3HD5S4rZ*yKik{{(admyDcB z(YW-hXoD^nSOXe78LuK?X#4)bDr;mwK9N4LHM=ttMlO%X37H-R0}s3d@lJ$Hxe)wR60HrcixmycN5j2OXBWa^jTb=vnj7T(JCn}=)JJp|4LCU zNPJtfB$IJU2WKh6whO0Qnjg+R3I5z8>L$ z4Zxxp8JaI!Jq&>$5XbwB2PCazL@UxVMPK%t=JI<60W3#kMD^Yg`9XH5V8%%4(CT29 zs2bRoxhta(LE5y`-CW?)`6$E`4pI#RrZo@0+lzkN`TA{Ge%Ypg*rBBkp8h#zOzsvT zy(69A>JrqqWg(mLXdbG^t{W)-amgchtHVnYslazdZh?rxrLrJo6PyMVuY%?^Ce619 z2GhWbXghxgV{*uPK$4-qeW)9|3s-;k4MP<)goPV_pwODeKveCnr%M`^ZdMsZgwZS~Q%g=O<_z#WSb6qqO8t8eJfS6>Dhopa%@ z7v02)UL98@SoEv3@BFGx$Qqxz0AKTHHMR|?!ufuwmQ}3he0Yqi8^RA&vLC5{C|(2v z#3TjW@vUy@05Y_I?@yOqDcoO~x(oNrhyHBf5k#FI)R;h!Q}vw2zWM2oQd-L|6T5R)IP6wK<_#3DzOg83pa> z4)SB7ZQpKI-DE_NWg5s=&L+%u2`V5$D_w?cJsGQ{bg-~K5i(y-E0?B&H*pk{%ycMr zV6ZZJkORc&<%!h)mq>k1?(qy07k3$LWHS9Nd?IEqrN^+9J>IHqKi?fhMJ<6S=I{2* z??-sa4OhkNsR$I@-QuddPE! zqZ`-OTR;#CDUtKf0ktwY_zkq}L^$TrH2Y5{Wx0m8zwo9$+!Ft^g7qhI4}y1)-7f(^ zHz$#;mh_=Ks=i>xU(KxK-0wf|G88t%>%drF?;(d>f#w)i^KTRNTl8D}VGEzZWoSqn zL4YNR?cs-F^QF<$=+Vc)eqt#O#LZpdle5LBG3fUB!DFg5>U%>mNz=SG6R!r=JI}2Z zwYqG4|JxL*8G1U;#8`F|kg|{nGtMqGYY>3IzR#3N7=HfFz4?6@l8U+j{&@l!!Rnjj z1H-@&`b`GcWGI>8RpFGD^_6ApLg>?kq5T=6L=`vxac}iojzVD_1z$Qi#w^kW=}A_o z@fKy%t^s|S>eBBJmmSVq`we4r_nY zH!={S#MZi{g3p=SdwxjQe;$ z+8{IpI>SA!{tXW~Uw#Ci$=<$qUzLWP~voq;lgu zd;FFJI7U263bmV_KZLk+sc(~_PXC6GLZpADp!cbn(qHqfL;_t;jf;Da1VsqMVh!p% z@m#9{L!oz@Ow?NsUlZT?U)g8%jC`(Yj$Gy`;o%1sJT$^#RDTg7yK2-S9RY+>BxS1; z?#ATorZNGo>DZ`E2Ek4w6c$lA*& zPg_8YDeWyH2$V<`srXr`YO(WQ_mQ^}uiV5XR%IQaNCFnSU0J^%FfKZ-qS1(>IVnUueQQC>Ut)R~%>yZkr6MSoP(Cra z17(pZP>G$ibEk!*|w01{8&#au!){18S8=_>2s$RQwkJP?R$zWnKZiOg`xCu9 zy0&rjSeSqbwTkezDdxpOi{~p_(qj04X7u`3+3_)-RM_UFwqX%6jcjE(_Px&suQDcx za^uy9!isI$7o$@*6GIFuuQfpC-v{c8uolAl(N(HGI;>feu}RR(Hn1$%jhtGzMoIQ} zkYTRIq&L|}{amn#1$)uQ6SMxryO@i7*=2*IFD?kUf7r}%6gBOB6c_~!EtMsdRsruc z4-y#v6iS==wxmHlPo!)>(i$I8&T;5@v8gh?@)R@uOtOCS5n+b-pyiQ*czsu`5M=M( zVgecB1OV{^bl1hIDK?o_xJCTgW5(b>Y@9JgAgy4YbTUl zZJjPS3IgIm-qD<|rOJX?D?E9>tdJeV8RsZBLK&l(2VqsQ*3bQ1K7MWZaopGAtx9P%xp%x}* zL)F3~G&PN%{4-7OH+ZcF$#KBs^Qk7ucfo`Sd?pmaTC;2R+hUj^@ z?sk*^Y($m>iIQAk6-0g^$zNO|!32G({>PC1;2^lNQ!$J5%sT| zCi^)j@73Ahr)I*_-^b%d|FG!$JM!8^aT+hRwTOs+Tr@BG=s4B@>3A!zvhU~sIFrBK zkKr{9A5EWRM3|%(#Kfb19xTPM4kFLGV4%5EbZqqdc#(Srb`8t_WdCyr?pHfP!Vki% z&@y|+B9lx}n&^Mwhe9I6D28VwcX+kMU#fd(0QeIPsYQ|djjxq1j>>^V%#H&q?L($| z(pfgek(Ciyt%Q*XN4?OvV`~DQ&6J_Rk2Uvs4ABgS*0e3X-h;Qa0qaxlwov;=0`gF@i~DcC>Ze>*=u z97|SE}k?Nx{-i*%eRQ40j{f7H5M!dt=sxz+^JnRzknUty`PNy`yAalSX9e zR3B&bZnRcmgf8MMb*MSr!&~FBRmazJ`U6n;j$?Bj@dFC-r$5fZc0Kmd<*z}nLO(TB!c9!7tG|7fG8TbU%< zXVVBH*tEHDBE|J!RzhB8V~L$0DXX!&(zQ@$&d6`FQ9!)$U%v00Jl8(`fU@? zRF_`ZmAO}r8aS#0C{LiXtJ9i^t22=gw2e!qBCa(QB)JRXWh{LbTI_Z~Ma=eNCFj{D zr-nao7`piBV~I5|^5$6FV@Fp#&hllUht8qNmGM^`nE4`)WENPAUm-r(4M$=U>T*4? z^f;IN>scXkf&bubP$*ry_Z^F;XK5+3)w+B)>F}_gXhN0mT20&Os$Pk5RI5k7cw>Ny zKjm=RNHH(ZIvMvBj++ytN-%_41FDUg@o0c;3H)_3*-iwa29DqO27V5xyOy6^k&(`L zZsju!O#gnRmvw&(A(0xVsjhOj}7?C(I(+#1?>Rj=t2G1)cU5hd}dR_N)kwsW&U#v{>yFgZZ8Kr&=;lh=<& z*)@eG(+WdZVf58exRF26F9mG)G&R{Y-oI-rL+3jrG@E18qvi#Yonj8 z*@Rqvscq^kOcb*05wWV@%tfEQ~ zDhAVg4?qRun64ySY0MHAT6obMqmWxW1la$M1Rcu>*GE3sG+amlg?rL&+Amiv&2lTx zF0a!ZIH;7uJArh*sV?x5Zv+Esp`UqbKT5?>sSg)^+NDOm1ZC)@9A`!LSC6RWy| z59ETnncSo74AajIq}NU76IKl|B)a3^M$cBYjgRDg zr40-+-f{8%-rR`~lJ$V{=`;-W6}WxD5-lY~xX1$lhAl>Dt47tdf=$4<5}IL^b^yHd z8w$rp$o#@`JV_k%aBAdXwh@CY$7N-d-x>VkRi#!~Z!!NM% zfU*yq7nu0CAaCktL;k@kRMy~U5x29TXeGfpJbCV6L}Cx(>^|-yY1?&avx;6JasqLW>R(Z0 zp38wU#GfuZ4y-OYM$fFqIJZ@C1?FK}h zpRWN!mNLn>5qv=PM59(1`dsH2&>6JQRu50UV8^;%g1*ImyL>_AP7j>OFnCfd2r`s^ znkHh5-4nW?(+mmKgM_r=yGPAZ`4d`_yl40RjPY_?{wNXNGCG0NQ<^7Wu2^^6U1I@) z5f=M2nyNn^gf3&jzB)YT%wnkEn-*O|LvO50R?amXDty#hj$fD1AY=x7hUy>}KX`0=*zmTprt{qfCCPH)JG zNpi3tOOQFQ-{}pu@de*W&nY6Y=2_MqZ?;}1V$kv--FIr+o?3qdg|5DJU=s32D#-iY2hyGr z5dZsEiIZmubQN{ywsvzSk{t!ke!)F}8^5;$e>HIOvtJiMNq5SOmNS0tu zLTCfvcgTHph+dp*wfo5|KhYm?0M?c{%69g~#>fV{u6lQlYRp`{T{xNlIs}J**;w7Z zo3ctt?GGO@qhI-a`;ci>SCR}A&j?Kq^Juuzn)@7GQ3;gesivt_XI$X+4~Bc0$cz64nIUKFcD6ou={F0w$KPoiQH^HTX*OVV z=NxO2EkU)Xc_L=cPENdpqNZ=4Y)59LsBu8*8MBj4)p{_%<+<*`k|As`xquCdR0q|4 z9v@V8RmeJsch}zG_@zXTr(=88nwL|z+z=5>%g)7puuLa^4jQyY9vbabS<qMPqAfZz{t3Oj%V{YDZ7QbHoxAJY_s9HI8@QcZnWtZMhr~;J*9T=iR$4ZQIdatbIz0W0|kkd9eY7Y zO$j;Bp3q;n`VI=i!LiNN*omMUWBBvC8?r5Aa*?|a*X?Lbav0=cFTlM;rm4~*blgo2 zaXLSHj(0{J28~^b|*LD#&fafQKgU>VLsd>-^f0{k{n0W?wL^PrD!1=1p>ug|52pBI=H$ zhWz$-%-cSDJxAez-6aZKOV#2l=H;3%Btk^8l- zrX6ihLC$LIwY&WaM^hFJ*?E4}Lv!ixK-YvtD~EY4OCn?G0sB$!s&022bHhC4B;1@o zlZ{QS@LZeSKo*s=6D@77V~QNF5k@3fwLUV>hNMd~t1G_FzI`>`MH zltCVP?9wgZ6np7NxN>ky@1#Y>tG0m9+A4!kz?rr*XW}u?aOy3f#$Oxwsc!Cpv#cnG9i1_`^&PJzB9c!7Vq1}`iMPOj+|JubVo3- ze9MmH?|OP%5aW44cE$~#2@0I*lE=M<6w`bT#j!knnFrNHj#{9vqi)bgzueIfu1j$~ zsjy!d#jO^M7T>kZ6XxR9iWPNX!$3-qj4Q2g0PsQ?;LQDi!3I+?uU=JD>oxGhSGX(s zu>`(OG|pNS^I8dSy{4J1p2AI(ag?E&bANR-oIP`Jx zbx|FIM^(`SHFWvY6rH}gz#V-7tkfF21wrA9W((q2Xb#;FM4UxUxiRnDl}j+f{)h*k@iHx3(zdgbVJ)5t)Y#P0%ilNzFIrAtdlG4B7~C4HUjlqoYn8PnFW=-FD4TTUM7mi-%Z2*I zQkw*|ElHHC?eAkVY>e+SuaehI>YNJL_{9RMIX+E~bCxj9{x?yPXAZ)zs1-W1BtWfo zW?z9R#H2D#g(&&h7Hr>R-;aU*Ly7V&hvh- z`#0}YM}|d$t8PAdX6>V%pU?4Se2`~_e$bVVp<6CFwxp>2Y|Z%*auRUFR@`v@ut zuK!&2I(>RNZYxT|YSBikih&MFKm7iK%eVx5-=|%zFITt_O~rEo-OtlbTBQ< zj5_ilJIncg9A}I{=0s(%bQ%-)o~st#OIjVJuK{O38zH9Z0z@C ztf=fN_{5L0-bP4R!+D?tFxetu20j$hh^*F+CPp$gMBc?@J)h(b^7KZ{;Ds@Yd?CRIN*=hxT3Z0fUB z12yTnM$%r$?1vGlYGxmffJZ!Fw*Z?_{fjCPb+c2fRpeT?d)q9ic2E+SSL~?&2UBHF!Bqt@~yfE#LGN{WleoP^oJ;-9LAE_&0At z7efI_P_=%ye>U&`8zZ@dL`aDcE|2pdOAk!MmY@`h0`6e4iDs>@nvt(nx^Nod9eL`k z|B1LEJRXwJ)94NU8EXf1U3tyx*L$Z%7%jZ{oSBoGII|H&@t??x< z<8%TNTU{Gq=3M*Bo$1%9#n6{mAT)|ZS_jt=VhpzgF)&%~?9xLEa_LoA--WaY3?EH}v#x8T z6e*gVB_b7Tih7TPFe5~(iBBzc(z~sjiKW5$DQI{WiLF#=tL1HR(aoqk{>FW zRzuY$Lk)On-65a0;pkZUSzPF6U`Ec`elT7hk*>BsF6e|odMy=A*mbPy(|W1y;!SUb zFoAx$&_4rlyiyZno1{Ds`jY>A`g5%Q zc!`|^Y(Djmvb)997diX2;sSOz+Ea(I<25iUixGVEmEftqF?q|J&$3JsEdZbYgXKo7 z#=4et-!^wIY4wO0vgi;UW`?NZP85nPnGN5j1)Q%BY6ajG{ZwOcBU5tC)>g#!U3lx9 zk_Z=^6ySpJ0Zg)5Fry+LZuYBQ;W|DrQ*2^FQY`-lZT)q7+T=o9R1Ipn0AhMBMP{C? zc{pyI)9|Nz+Bz3-6`;AMupj$P#==?0r1+Gn%8g#wK}ancDSq#8+VHtgWr}{K<+f{8 zys{I-0PRhYB$HTouq4Z!aM3abW~n8?Fqk4X>z!axE z{u{F)4tVEoS^5&xcn8?XN#?;z*ZB%!JY~txwA26B`QNx@eO2d*#&Ib5%0+6s)Z~On z`G?e3pdR$#DwjIbwqc;aPVS+Wdj~tf+`q)AXf}vA`<4LcO(f$0ms%zd2Qtl!ly)-x z7dvL?=tHf`yzIjs(g^0_+o<<)Ov~1EM_=)m3_>=0_Dr4r{<||@EobV1fIzA+enK`K zeYz~;Td@rTMS(U`-%A|ZpE&st2=n?Xvf9%!spqSN@PumZq@FUovVLrvy3*s-39_SY ze`f{G|97pQ^+n6yW*i;e008H*fXj3ha{Ia)5y;A`I3~OA!O~UM3b|&(JD~EpL3Ey_ zqPOJH5Gk%0+M`2_nU+hQ#E63t3RdQ8-FQ=8I=_ zcN%RUT|x=(xv)K#))jFGRm@9 zJ$oIJZmVf7*>c#I3t6qcQ&BhsB?5Uw^L)e7tw8Yd6Jrg9)^6=0M;9iE;{rTfaLb#D z?>K;|R4D{B+XT{vu8HDoCE!H={$Nf!8}2pWXbh_>~yY&oavDs3G1n##US_JDd+xds9a2&SzZAWtk_v7V(#qcBOtU zYWF%EeUy=iyn>kSAV3!QQ?~Hoe=rR2oU))B(4t*Ym30B0ndzUDcs63Jk&j}nU5s7` zU=`9~`6ke-`T}2_v;=$)MSLJ29Vtdx9%)*+k`T8sCQjPsATyNLk-bkr_0ar#HT_Na z4ntU3k&Zs5DRLCoczVjwL-eiDx3PbSnK0OL?2lz>El=t$PErbp38+^eR%umdfh044SgMT7w74;IJ3W*HV=126htu}sA zw5p}<>&oWB$l#3Y?s0SRML3>MD(X?Jq~}HwO18$cZxDbv-%8tixWbC7HF07u(GUa5 zcwi8h@L;K&9td|Zierqnm3C>7cRIr1Je1!4RiYUICYaP2l!R6$6?U^5Wc@(qF8I&W zb|I~>sD!t(J8yS_>+2mfis{bDr5Z`bP6bGlkVkd+nE-b4z-$DDN^UcPEl++csc(b} zu?vhRl%Tdniw%G68-4s=6~3)aK|`4Uo84pPPSwYMF@PbK#WZz(^KfK z_r|zW_ts7}a`HmnnO2$=BdoiWw!v<020Q6(K}3vLE&8A=`vjJ_O`WD+D+84QPRybF z-91y!t13+XNgyKXJ*w+4g*W=i-T{2Fr($P_c|r|y7z#xve~nfMwdwHMEHFj6B}Qt1 zPNc1!lMVHbF;cLT4a5XQ~ej(&EV3(s>sFJh5O zuqmzv!C8Rr^LG{DRK`f5r@g{K@>H=@P+0Y+{o8K8N9D5-&KnOmjOWol?&r~i-e~Ec zUS5&XfX`ZbPB%g*2dEP(dO{?r5+M9fj49qp$V`$mKHjL_x6}qFWPvE+^_=Nt44|*9 z*qJ?FW|v{_3;4GK1^N#>$1Hpr_tnPkpYkfsxh$JUIdpOm;ugReX5dXunC~&UO$C?p zD$A2d&&ypD*Ns!<4=bJuo7^USIMXA&KhcK#%4i-Wa>w3P89IVhsY{6}cN}N)vQZXF zDCETPfJlPbTpz{7XA!{s5KFfL^701yC=bw$x+&K7xzJeCi>WCSDDXGTT6aSd@oNwU zeX9UhvySofP@+-AY@p!Srve$D(to@Q0m+b44HR9?eag@;2G#9}&468?rldD>sAWr= zJ<8<4adRxjocrk`fQ#CrJCt@J-PM_508OlE;ts$%JD7U}81@G^-HL%tpgd{lg?tKS zII*r{-BFRYdNO!~`6LRav;v!81TqD6j0$5vE4H+q()>3IBR2AT2H{GnzaFg+Q;_1+n(riB#N;{B^yX3_T+ZS?cP zpe&8u6VgJr&8?KlY421n7|K~BudP@H2dOc9CJ<7{>7W8dJ~oVA-~?8vTb54Na9q}5 zVUc%(r{Ivslt$R@K0by==i8Ya%ZbOEEVnzHR0}C^BkHYo$S+>!>$b-F6D%vOizZuE zRdp~j4#rxGXOG1gGAAs9B(bYp&Ov z-&%CWX6!5qb)eUbFU3JHVo0UfOAX5H?e^pYs_A2R6spNu46> zy7-znX3wWNJRwTD@MnPceKDvF8%k`Dd7sQmq5RaslqaME7?M%k3TJ|yI^n)w>UKns zt`JfZI`y4^hoM)1z`bwbIts=Yo!IW1t~Ri5MNucSZ=Roc&0rEl;m;2F;D>=C#a9x@ zQT3*Z|6~HN;2#s)J{|nL59e$3wal2hj8V)MLE82LA+|yMWP+A(p!l7b@qpbvbJG+G ztJ>>%Jje%&423cB`th#X zpU?#tcP>LdYXTbQha6J9x;fd}p3=jemtKJ>T%(O?L4yTVh4DWRx?Rss6K&59tSYVX z(Z>HT0b+LSdU6-u*+tS#Lx+FkEvsUZ^`V={#>iv4%L7sU$_)s{G??4U9YzW*Oynnj zE++d1d!vynwKl=tD`?kjvQT*O6$@t}JTIN4{C_0?)3QD4k@>4VJFBlT1T+qnl$gc% z^}v0^Uy}_IPi3qX@ve)fvk!lrc}o0%k+=x!4F=1pksGfoE-I#rK?`Cu%T-^H`Nh59 zix2kdfrDfme!WBN3#kkCO27uhi=|XmqzS&w9F8^ewZ~shWO9zLw(5G;=*ju~i2d57 z4YpsZf=`GtJ`+YioFMhv8u85=U11q&U9|9y>Fs)@F>jdJif8)&WqyU67+F<9BK5mBLY;g(kD(fKcg1<&*0Co)V{ZQ61m8c{eh_$opYyWf%@Iztq1weM;|t!upy z!@tb*byos)!y)sfWRi8Qe&rc^5zHIyYLfRx@ z0vN=r>`3Jk@*;$y5N(w`hi)H|><`{e==-Y)-|PmmDm=MxgaH)Ym6g>);F>xF0B#P6 zn}W~Cg0>K=9(2b%kwl7vEBV{xGvmRo#xh=4qy%o^If8jZ*Y2ye{kQ#xq=pn)Si6;p zy=KMi5OL_bu4$AK!S~Vale|gTXrB}9oTYFAI-2l4f8Y1ScfbCxh?c6Pn~?_|o6pyg zS+htRM^Dl$;869KMj}&c2pej##1qE^JYuYHT{1dN2RKJUnm@FaC$ccmhnfiBzZ9}v z;OL(N(sFgx%h#Mn(X?ln)xqEetasp~9fGgNFN!mPT!e471l-8UkZ;r}?qvsLWxrl* z%0dhSyzjQ+di{w7u6KE{$#2=8HICH2mHy4BKdltZR+O9=cgaOmY-XQxf_jgx;o-U% zaDz}hD$bIf$88yFSAwx{@#8OitduDT@kL_}{JV*Gv@S8q3oTBI?ia`1VXSfXS7{C< zYy1t_O-XyYrVerX<}B#Pa4E6BBkUu9lVK!c~;BwN%LmQH--55 z6&&8Q$+^_9iEIpPBDuX-E>O-Wdkm6;t!k*3jeK5-8)y0#RQ6*#-a1sRTJLHOClImO zaS;i#CAbI@{e^DE1ew~En3ciQ2}tZt*o(TW*mZMU)a@(y23$M>Q*=w9YNU}|LIu&h z#$4!dl)Up}xjf9^pC_N1@8t0ozu*OZ(kA|oK#(~gfO&C0coW$N?R;;uM%pRPc{R_^ z|5?b*@8&r_aacsOvZ)1$@)gMe)>KHoKJ~RLxYs@ZT24dDz&D9L)g^q!NOavB2c<4i zSZG$EguKX-x*Hhj^k-{R;^_;K zXUQ}>qsoTVhCRGpszu93dD&*7E2k_Vn-1uzPT7+UbO*$@>n!WR8q4-xUFGvlxNsWz zpA~_B^I0Yo9i3Ooe2pBuU3O5e?PYr3c*UR2m9Kele4eehLqSr<9*M*m^2N&jTDg}6 zi2UQKfm!EEw1&T}trj%T3t%qqR07B$0ABJm^i-tV z+-$i}Z!juE;jDG0C_~(F!myalJW#2GZXgT>Ry^RA3M^Xsn}dTxC9!Bc#MuK@$_+AE zJrqt`urug(pKK@R1je+Q5z8$LbIK)J*Q>C6Q1Ewc7$H(Zr1(NLXk)WxQm41T4SLeLt;bjVXfSF3;dWl{IzPt_;AOS& zbu-1h=^?UJdyVrv&d`*nC_;1LQD?c?Vc!p}f|>%D3{NPAx<qM1cAO=d(i}E!Kxlri#Ef|;s>n?K5dh=25??}E>cdgt^qy6OMh$yH_=VBcezo^ zO!%N^V+pLAM5QF8+_9ql2v@HGm)z{%MrQ=EU>mdSYwTp(G{u(y|9!w*MHI2WUQjw2 ze#pqKTALgU+0eC>js$IuwyxQeSRACUKXAZB;?;cp zNutE_*X=Y7noO67AESe@raEwmP79i->ZZ*ulJC#VY@)mW>OLjs&~&B)#8uakjJ-9V z4o_`G{B|(*aVs&yr29~p%x)Mjp5YevmVz!ij=V~>{@utc(*EEtDSHU*-!_(*ve5%a zqsQ?6oSQ$29|FuoWWAil3WlyUI38?8U z-Pfb1BaGRd--MgH&M^N&?o{nmpZjh-JF0IG*26HU45v&JFxiivIE8HI0duqN`=4Zq zPf~Xo*#LXAZ*=pmoA05UXV!R=hl9)=?K+h8)fkQ(AT|_AQ4-&27&YEt0vPoYf z4j!SH#+vzW2VwY2WE0fB(9@s4Y*gNb;gJW`(F-ScGj~!d3~cB!Z^DdCLC#-Z54sq` z(-7c1$uTh=siJwXxdurrQyI$i4(u~dA}|~#xYfr*wai9K5^U)X_I)}i_jof`QlrH8)!o@k2bs_-+a6u?eOo0N7jr%EJO8`&rfpl>V2;K?SbT z?@9bH$4Sz!=yJ9 zO)@cvABhxv5g~4EE>tx&o%Xhvmt@Cs^Dnh#W>lCXKG<5%mE+DQkiKNON>e)-7;E+% z%rBQPeE8GPu1#Cm(T?1(wHWla04&B7Na@`^V!B(NRY%wtY>LojwDKoo2 z7ws*NYm>U+Sn;T*g){&&DLb4rju*)@$P5glf+3%Jo-iRzAd>3CxqV;L9krkGVysgk zmnKaNQx!q5R>K`xyVGbpj>H>+lU5gVA$y+UUSKEN15y|ugp=tAF zz4v)7SM}8Q^whO=0>Kx$S-E^T3a@`%aY)Y$h(h!98+ls|ECs)uWJf&6gBiuNHDK$@ z2#H%LJ|8vn#}5o4goY1jx)@6iXoZ>Q>Ri+E8Q%Q?b# zd~koMhi6duAw)nq>ccxYo+CmTHR3~Xdb@$Z7qTAvMK!MeOqvNpiaf~!t95ZC)uf{=n1?4T1sL7IwZg(7iPN!5)HP>dgM;1ukFCjQ zuD+6}Uajc`ZfL;;N~Z{I6lj$ySHPKSUwwrR=myawuEMag92kMgO0>Ci5dx1}?k5eI zM9X$oOJzMODcSxj0F04sZ~Q#F&(qW;<}k&XK6&D+yH4ess#s;(drGXs%F(2}4wk7~ z{;{EUvSw+Xy==bBbb1wNTFBRR2`jos_tjay@eZCtjTM0T6)$$zxu}x^_?f6%yIZf? zE<%;;2RZDt;_wC}0bCe}6K|dGL~KDwSx(ZXG0(b5VjQqhh(O?F6*XXJ{N$CIRyVKN z8Q*s|XM+pfcB1^e3uZ<}#EPRHS^CwI7VVn7sxBQuKukoUmdfd;0HJT|8$L*_SPL(g z@*~9b?rbcw{oSfR?mV>2oxF)C7U-?n=Ka;_|BMz|>YNcqY8G<(=YR5Mf1zcuQXRnQ zCM2=)q$%FoIt>T-qKD zEGNj4a|E!cQi(^}WLNx=-!Vdphf}ectgi~l#6Rn_@6}&Il=@1SoL=yucvwB_sefJ> zW(Gz{DfHfnK9DN#ld8JLK#ZQ#L#;ntBLFnMr_b9EJ z4kalFWyp#kcnk;fFx14;UrJ-H7) zY72j9=W8G9=S}ybVQ4K(h@yB@#;P@_lfx3MOV2}S6$U3l4+P1SF>utsEgmz)Ko?Xga-;OczPAA&bWKEgnQO z4q%ewLDl7Ob?D@!-%9?Jwl_F!g1c?J*3G6B{naSzZx7gmx~@T zOV!m3Qi0f2Z8t+@k^>_&y}R~jJQc7xO#1K4u^UP2IEN>0xE^D~)%bis%8kssoZfWa zuY(Z(C^#KcZx%#K=4vOg_^trv2f|qv>aPW#N>qy*2m~WN^@JljcvD3ksUtMJfnrYhdQ<1&z5FA8 zlS_*jz4`QpI&%o&p{V|@>G_+P`C0e?T_ZkN?;(1w=Y~Xi(Jzg8T8yQSLS;KS1{cLP z2@piay3$eXVPY|h%zY?{0ruoBfV?O0n=QsrPl`3vrc|tPzJ9~Wd95s;ox9w1d-N76 zK@dOMB?_kmRB2L31($!=c$tg0Od|jUjgpE3?!039OPHczKDz3`vC~oz4;liJM z@6ypsR4O`M!v9qs@Q7Mk>%OEi& zpAoyS6V=6o;leZfXkV&Baw<%K_QHF1G!!P3Qkh(+wbcl4JH}Iw4W#unJ?NSbdWcXJ zZaX+aZGzA&4_UqdsT4>_5A=vxKJLTwiL7CUO-9Y!FA5dNv$LCxS_}&uoeRr_Lnr$y z8R(?Li=I%Q_#VxbBj9U5z=nWHw$fTFZ5|m(GO+oE#JMoDqd6zvf zQXa9NWR?^(ap?I*UgoMG$vvdsyt>s@+3gCP=6#~~dC^)SdCYL*2YcA@47aj7#t)0L zcaMNcwzfM>yg+nK9Svvc_waDK0lw)*_mqde;~xcF!JG$k(nlDEhLh3x%^U{ck5&c0 z`x)GWVF(OgLELJ98|7T~69)k-MNWR~kMNF=s+{iZo@f!~X2o;&fO_g88~S7u3+g?O z&E`#n2%T8KrM?}#{}rfucY3C~t(^ck&zX4cO7GjmLoAzpJl6M|`YHKU|Lte!KzTuJ zA%cxDypZ1WaIq^e2qg3IG?gxKk~u(FkC~Z?mx0%KEIQ0c{RB`F1vK=X39xv{wu6+w zw7~i-^-Z&bXh9Yn5P2Sg5GLuome4$)O0+d2>KFMEAVIBwJUv->n1)2Oz_4=Xev^J- za@D{Ec29dv3|75+FhdV}+*5R4D;I(#P~ZoCxXxu3g9(k71~`LWh^eB^-6O%ZY}2AL zH=~8kgO`1yz`lAo`vs9c&&s zZTbgD&*B^18V&;0wyVi>>QT<9zIJgpjh98#lq zK50oZc@%V|oXx{K2YJYb9K`Bkn|hrlbL(C-<7$HgGVp@09%fQ%2kY=-{KV(q-rUCzICnXCgJp9_ibCVRB`R@I| z9#1@NQ-EJ8i|j4oUig6Kyg5&BX)N(cnO2Qvs-4sm>iOH&d;U+jPy-DsCUGFP3@b4! zY*t`?;8YW%h-MFXUiQ4533SD^3FT2J@yEwd(u>j_u#~gWW;kV^m6MMwC8+5`$XO|K zEnkW&B(OS;p}wsQ%2;tQk3zDAO!d_+(&gaB2A6G`dt0lDty+x!emr4-nE=@!PArPA zpZ{#^_K>NTHIB>_*8ESIku_~={AvXl1&*;rBfP4_AZ{vB3Hx{yUSr{u$Kho!<_QpU zt|#kP*Ep8#+Jwr3m8Gl<8NA5}*b|BmG!0LRb~6AX25Mzkl}^2qkFB8nhjP|`0Id`O zuyj(U`f_zvn8EZGZLQpCGZMzR&$MRZ{1_#T1!3T9UM)eoZO=T0!aWPT2poL_u>OL> zn=xFA>L|%U6dbLyaA?ZZQQWVAMU=EO2t~^R0JvumEW0s8-n#ewCh1j>`&L@G95c7r zGLg7FZRhl9EZsV=m_n8=&6RGnLr-wcZ8^H}Ro>)&2>NPgu)|j-!&AUt_~% z5Zgy|O*^t$P?5H$hi{s=&i9Vrs_(N}OOPB1;~3&ffB_U1;MiCn_=f#?Rs1a{et>tAlRNO$QB7(_krnUxY}UnyZ=GI1srE%)!p zwVjwYJlA3X)y;?VOA)m^qL=<>`|x~S*EyOt8v4f0{cBiVY1&V8&+T=}CNkWnVsI#AV#>;$touV5f!C_`CtfUSM8M!bw4UkRm zUA0c2WP58m+The1A|IG&l&L$R#PTjOrtOO}gNfX%#v2wTt~I2a0~j;MZ0@8mGgdG; zA7Kkk#64hksflgemG!A7a`4X!5AHICiuiFuPA(`G6tz1wz}hz(BsK2Y8e9s$h+pLp zXq#js)4$b8GVYbye*~P02U96})I5*YJVaaNl0P~Bov)c+O8obk>DUV#d0N9w-VW;; z(-rMdAut=zu)Cgh%DrKGwevw?L0!h@ScfNVsGRb>0PaM4h=cVLG@Eb>xp!>MU5WRk zR?>4^+M?DC4^`-}ZPl#F_44kbk|;;V4<)Yv5T-$stGxF@0eD24DaRy#vf?}Chz{#3*LT8;xAW< zwnVp`{jw=%3cEY6uYFVKugFevhC^TL_f&hN;G%YB(_?YTbUU(+|GM1x*D~P`b*;k#W3o zvIH@!h9;2DxkdNaIE^8SW>RM|{NN|6SFV{B$vRz%&CAlSwMx5yY3|i6)5ts->VSB_ zU6%-boIJam{8S|%$N$75heW^!5G~xwn-s}dXmy|2}&o+%x|3?%y4Fa(B zK>twjNmVX)8eJFhhbuP$WwRqP#_}g4UCTfvjtB<+{@Lq#+n*rhAB0R#7}E$vntQ+e zLyuwfbQvB8$ya?VZEG&dASa-W8_#&u%fTej9ubpGmku$USs;!YK9YN1Kr+;kG0Pz? zbWQw_gI^e37Lheb8iBV9R!&+P`NmCqMav)0~t5xaJSt%2l| zR3)a>Yp<|phKBwUf+CE(B0N@x!7hJj#su=X!-_+=8PTe%l)z_bZwTlmJmrmSDPS`i z(W~xalWk*=FJ!Y64!fr$cZ@0=Y~2v?*kKjJqtC%S<6o!KF5rRs zGGtq_z5?))GQo(?qeZTS@A5O}{|Q>3q2hIMGbFG0Rh=H_ty^;POpo}5lVwBQr_|{@ zGILL9ChmAZO3z!q?JsN^_-pG4P*C+gbf8~WWQ7fC!*LOqk1uFdc@ePOy|YD!*a%cj zykCKQ;P?8-5&{8j#Sy0?`g;mu7x^uX24_OMRyRiFp044#OLrrty(1%^gZO$6<08^P=vD^x*jo0d#Z1S#i>C*mkw65dcRSL!BslC?`09s_42>r6HE_FYE!D?=^> zCWZU1STn=!%N(seTS5T4y7YGooG6FLd(BG{^kAmH6x)xka4_MzD7daQ^G&q()-jLl zB-s~?sEI3MF&-cYjl}bcDs($778F6dqH4PH#{T@|07?L(9o>%fKay3}11#3UiqS{5 z0SS}3x=Ysk`3{+w>~j2fyYHjv8y&t-OM)q2jYwHT^L6Wr=UV`d-v$(sdXVRk#`eQ) zEYvIk`VV|s|3Q@{7CH9U8HsSH0zaQN#Ka}@37?<3-`6J2mwp|#L>R!h--kwz-)-e7 zFa1UrrZt31ViF5=b8!Fbq7Ge+VHw@!Ew^`^(!;v2xp4ekEXzQ5q<&f$4P0bt$;%eD^_G z-u&BK!THT{5(p7xf%i!)@5YYl^GnNQFU^lEyFvnK>2) z_O!<^)GCuA&a>5fy4NnIA$y_I^d$v*zj zSKDfqelg9^T^;O}HX6ff^&?(fB!je_0~mWdk8jTmS(@rw*mMlLusbm+j6w8l1`HK1 zI3@e@V44?G8wOiGB6=VXD6c|(b7d~^HX_4<=vP{v+4+l(pO%rsz*3nEMDWh|t6!t@ zx=Amlc7;Fp zCQ=6*dg)WEUmq?u?mW)?1nD29x`n@Gq~Yv0S`=8L2;Ca0%Rm?`u+OHV>|@xYzlL2+ z@Z;Y)a%8w!rSz#e=yoG52{gK)jVhY;Mm)!WmGKEgb}2l?_+F0ppW z3jk(FCHS_aAYKOzzV+aK0{dU*$6oWLb_SQy&+u(^7yi08WvO}3%>Yr__u=(TKI$_# zf@L)IlosBK?bsvuEsAx)FVLCCScAEm!0-X|ASjg_H_EL)(`9X)P8`gAost14b9+&1 zrHwdfyi)`-FQJXRC5e1pvY!Knxd;F}VhHp=E0B(1Pb#d5U{P)9{XUBcuaXhxE+QsO zUMxiQsdt{DBnI;D`H?Fh)!PfugYO2_UULJvC7m9_mQ$vbtGh!zZ8LcbjXrJz1tEKS z#pX$YU5O}ECp}3s2!mx7x+bGpF%b_GhVy#5SaP01ka7vaLdUBRaLX~k-{w_dSX zrgAV>pLioOs&J!{ucof%uiuzwtcN9vN$bwaDc>K>B?(EDqDOs6a_IdvZ~Wx@is@*O zegFtO*@Krja^BMP>9v|s52~G$`r|SCbt%q0{tgF}r$UVDYrMhYv6KvrrtB?TR3Zf*jO92OAe`UH(D{f&Sv#p5Lb;39+_-_UKJ3K;G(3b-z^t#IJ(te%k0 zd}w+5JlQFHx?^Nc8*C2?cLiNXrVZOf9Edk8qJ$The-&Ms1Cwj|Pjb(LJD36*Gl(;q zI5*8g(Lpb5arPL2+PM-9#$sJ0bb8oy|nH=uTnD)fdMrYE;U~Y}si(+iIksnc8 zIzah1+Q7z<_xBVRVHJ0J)HF04=qtDX5uaI8ltoJ15<^M#6L+y3G4{K{O}7HeSEW0t zMDJXd5;qK}!S)DEC)HSB^J`A*4~qj~Ev8Zfy7o7(vNfQqg&pcOtgU^Y-l~v9gG)0l z8fK37RMNo%g;m-<^OgAUvWc`e1mj#(J3A^Z1Fw}Dv$CUE!o7;A^0L7NA>5EH7B5zI zi?O_4M}4*Tk(YFb$^H|18Ml6>z1^w&x{WFOC@uPG7kXClWW0VY9RO$(rJDsg4?1T( z8Po*U9UZ(0RN=J?Ly=VHNMG1fAA`mfR!d^7NNdHJ-E6y4HzM?6)H(#ZMs;k)V$G)@ z*-UHK9LR*+8M$(bk!V_rD5PS(*)PCL%!?*J5e1N&%I3Ae?xPg)j+V+=FeBQPv-6n+ z$V!DnF=u2VxzYeFBbzJsmT)2AIyyHU%41!ZPb1pY;a> z)6$G|^?ZADEvkXLEX2|Z@@jbE1{UkGM*RyF{ym*xegbhL)_}!;AD$Q^K`tRQ^gTHO zORQeXVm2SESZClJrI6=~aAP~U=82kVQlw!egdu{=mF!0hg?B_0Tg9nm%bC4B%aj?Z zrgm(7?6ob-&f3a`YRDG!Gj$yXD{9L&aT_ZFw^98tvLGIQEXP5&rdTOo;)PB|N%mwg z)?h=J%x%v$^1U($SbAdEN~r3NA`Y)|SK#Fxyrui|RVAG+wbK!dnEg}+9m5Gtn`Z!f zuu!>hyAl^ic2GUvknY*CnSd^;8ygOp&*N*tubaZmNbKTe>W*L6DE_osT6@t3d8HY+ zpFOs%sUmT{=e6omB0}|?05@sv-(1a|aNjWmv@=OHoOp_~@_!`Mjx0JnkQ}&vy}y8* zqiza|?WSzM7#}qq>tS{5o+qjN@s^EUtY0rHPdSlY4?0EL5sFSJ1!?i@5XiNVvnt}h zI=fXXE-67z5v?s5stT}MTG|Pwm};{z41uUB`%PM%!Jy;f!1+LeD{(5o`_z!VusNQA zqTDEI2#v0g=VcO10_jZKj?$>B!qGqr^Z#@aF^^MYZUAB-vSbg!TZKOJ-*2b9fi=P( zjz(|Z;J`efQ8$C3;z`6rkDzF2^f$KV4)>Nfz%yp9KAMx$ZDNx7&c|=JA3`ZA{a+EP zjP}K*akXI~Gy7NM8bGy60zuWbpM22OQWm~~BSzC3AkkYjpx02S=M(9{%~8P^Om5fK zmLug_|2#d1gVpTxd$7iWwk_h>kc(SU?nWs$bBl4OATjb|ZH{M-6mm6GHmXmvSL5P% z0zd+?jFg7q2@U}reo>tAE?H#voMy5?%@UESB8o6-`_y)|^p2H5RQON!o-+MEV*4i{ z_n|5{XXFnC{>Z-Q@!gsz+r66@1Y|`G@zLcWVIn-UUO=}eauTFwssifledDjq2^J13 zo>>-J6b=*g?D7_C+qqV=Pf@hJkL4?L?BXgHH`?+@-f|!51~6RsJg`x`n$oTfoWkZ} z@cHu3ibuxJOMSU+fQ2wT;=7|n5OQcK4?8OvxaL?~jRY?0x8~H~rq#6wxks1;C zB`WOM$w|ep1*?b>VTlBG#*6wxFYZ*!LKZhoV^z64ZJ#g5DB`BD#J`1ms43rUsrA{M zrrNgeeyAdMdW8D{hW@opPRDmPxq0}`C{0r&nCbf@frQV%J1HRIbH`!%mSMm{R2xc) z0B9vHCjgV-BPY*4;m>tF3N{iYrP-u%-HaCA*YG35SI4WwZU0{2{s4NJoun%%Jz9NH zKZ8k%LOMoO_M|7t;#KC+?38^>vKNS0>D0?+tK5fM-lmbQc4VfE*@wx1WX`7FRk;c< zik`q=IVE_}UQ~+hSY#AeM3J{yNffPIem7z=$>ZPLX`z`@M*DvfLNEKOfqQ#N8<*32 zP&qDYiV*i5RyuXe^4$Mf6b=i-I&4an@#iL%H@O}iYkgc!>T!UB5a|`w0Eq~wvnfUs zoSTbkGK`bVkKjgD$_T~uz!zQuMl)j-(;)CgCHU2`Bb)iiGQb6FX2 z*+TjvU$jH&^!Y*i!s9^Ny6Z*Bq`OM=%VDc)P!nqGhe1@##uED&Fc&y4_ZcdZ)FFkS zN(gr_`ZvMi2t0Va%lGnGsBY$z3QF(q^aqZO4P zs}&dFU%*OiAp6D3RkN#L1r{Z7nHFM;3P>7fqqKR`aYYXvi2gM6vlN`#9oEK z8CtANPf)_y0<5kG!#c%O%f!GoQ-P&7Q&Vk?{M=JEyA%&!0Vp(jU}n%SIXW0ni!kXp zF>gskmbRAZ|BGg%Kj=}=zNcc!J9oiQ+n)R~?`TTRQDhI5HNgx;izg->*~2n7AXH>L zbxv~tGyuuM*1Pq2-XuOqcfHaHQPBB8g)=70D#G6je`)cmz5^?m3H=W2O}67&#|h4j zoX*T`i0xF+Vmf}r?9qhPQeuPTM^)Yz)`lbh{2>laE#w70R-v|%5hAZqa zN2?m9ma`wur?{Rg1xExudmxOtxzbHvP-v=Ml*xn2>&+BZ6VvD)Zn|K|U#AzvvYjR> zT@Pwt4TsfFc-LCWN0m+L>HmHKP;Ha3*mY0kRgEnr?4k(mE9bjla?-s86S}12uKP** zadk?Cd30Iqc}$YkOIpADhq&r}jCZY6K|bsW9@r$6g_z(3E#599(gFd3G>g4kuTI`i zqL$lF>yCdbc3~R2l@Hz-0WG&r`4N(gRbw~V*#SLIVQFhwKSqF(dkA5s8V^-Bdxv97 zC;sxIJtmp|5j#q%K5!DU0Ghi9J|%nuleH;^^-aB=!!rDSn8R219`RjB(E|!HQ_yZe z(5>IdKi=%U(-MW}Un3AtLth&dr6k8H>p}mpsgHGT@;y9@p_Y20S+l>AbO=G2@V%jzcr!Kw^=;o6m$YKcBYiApi0f97_pBqwaej2zD2_J_ zFpq-KZ8vygqM)IJ{)!SVw3p3Dg{($~?9Qi|@A^NJtMMLwntQc#8|s&UTB+D9+RQ2P zujD2=deqo8@Q>tdBF%<9E-6OvyDmpmDS_RNoAaGg5Q?W=WUw1J#ltqCz1t#@oc;Hy z*d}e0rr6$hoec*xWJ?P;F{Fom-ZFt4m>*aHC#u|iUyWqoyi-L?APbCt=_VgfihY87 zpf3@d#NFGw@TiLT9w#3iK48=x!N#9iz8p0P5S@^ViYPG^#9I-;Pf16Jl}*vn35$2KWNPz4e7g6NW|d?W_` z2Jz*u0B^)i^gf09qYVFN_>>wauEd+fJENlD=r(`SXRs7HS-CPmTq~??u5er9qLRk= z;l!#UM}J;pb`K|UytqFmimY7mG@xt(960&n0?_Xmz8q}CMia+&uPe`w6O(*(0A{GIdXG%DFGA1x)Na~1W zCnf0hWb)dQ0OS@qDB_qpw2Y}rCCWu#DOx$Zwd$OHo?Z8JQaqKDh7eiC@XkWG@Ij1l zo7&VF%lE%Q2x?Fz3ugg#5~G(KgM%m&xdcNFs`J(=^gc!9$5)vzCq~(Ayas+A**ErXjX4htlFoMX6&~=l{B3?*5BbyBS!)g{q6@c7H~syUFCnJK>wt z0>J=Rl+XA%GCP%c3?0*d(G+%rkPZVV?(2gV>lQO;107Cgv=lrPHs#odK}3wDz7Gyz zHK)e0Hhf;)j;~%gQxBP0;vHYh?q{?nUl`b)^0A4z%hQ4HuWqnnUyN%|j>>>EE;&jx z#$SKsuEYO=b#NG%-$WVTCx*9Df(JRc_{Y@<+Prr!-ti)!{XbR>e?_7&V00;>+&l*m%cKXMdjk#iR=f{29NaO~mIedeX&&5g3n@aw@F(yr8NAp1seWUQU^jUlIS zZlQ$5&gMg1p;6mRYY}Q*69!Rcjy%~<%oMrBrVoSmTnc4Akb(Knql$cBIMKqnfjB>! z-4{ynRGA-oE!;BLQiJZhj4}K%H8jQkM!p2s8FakMwMQ5fnI)T4``i&12BA{+ zgE|pepDrvZOCs*u0+TPl4q9`XUXYVnm4pABK?8ld=X6_VaQTf`{;|k4m51eWYv2Ew zy{dX1E2hq%yUB4#a*xm(A3EdX-Fz>Gp(&|mSfk6I0BWt?`o;C3nVjp1nG>fpi3C-) zwd0pKof|v;NZFcCO9T013W*b4GN(QRJrL-lJkU1;7HDQvHD|-gGyYFx(bwhBeE7y0-kz`S1qg<7o97Uh2$=W63lxE-zG!$$c zo`x)hFZX6v?Gi^M=})J1uD%R08KR*C>9zjt;toe$6t&Q=F?bPlRPu*NOz7Nwo3;wG zeeZ2lmRCK*+yDSu_k#&iB_~wr+BU#puvMWxiw19Z{9Xn!R;QVGbQ^u5WHJwz1oW4z z-J6v(>!H*w2YvpqKyBbs_pvrxQjOS60JuKh8RYq*@a~i4VHX2jKg@b#iYa- z-Zo9NK75259EcNoYz8hXBGmry^M#k_cE8hm2Wmtr-cqS12$Q7!+fWNbRS>hfCfqPB z{oXm1ISM4f{-xbB;|+An#&bh0(toI#65$OA3wMVxY2l+($b6+?I$4iM`J+|HjxIXs zotmT7=zzCVbd?}Ha7kjZ|L7kZGJd7oUw47d82z_=2dKW>7HAA(UeZ&*;h)8P)980V9<4TTvPWYo4L!cHrskI%{4?PhO*&u+6^L=!Pk4gOQ{0xvwz3~F=i~}>@Z!V6+8{(dO zSGK0Q{UyGd05UST=Z0y`N@3e4I=6PNj2LO5;J6VbaD!HK>kN(MgaMm9Y0Ho}BV>tq|fcjsB z;IVILDHq4{>9~!@IL+pY%~^C^IF92@1?DhUsK)Lta;c5bR#O48mk*#!pBZ#>u} zWsm}E1=IFi6BDP^;JvZ_4WzM!^1Y&As?9D@P_Y%*FMLlT@Lp>RBG7A)jH?(7C6RQl z9X&{CGL@aFT8vdiy)lu&76~#%WRXM`gvo|A$3`6pt_Egl zy2TWZ_fmKYb2R1ldY>}o*Im9>>AqV+I4AshN5ez-b%g;~~D{ASN%Cg&jRb7satdW_N)U$-el4Lws?#=xEamIv1b zS(43)WymLE8N|q~At^{K6LbJ{oGpz|dBQB1dtb?i8MCcGk_XUVWN7QX!N|vv@V00$ z?fz{|tz(N`SmB0epNETlAfW92)yZK|&Vmtnl+l}WlUE|J7ol;YbajFTUp#4#vs2} zLCXOR@LRS36yBV5{y0gkw;o`f0gWYlf;q=Xiq;Oaz?@}Z7K-N8*XbBTWh70P4=+Y8QRHpK6OIH4(deyyXzjJo%R z^_4*8HJ0y}hb*J@zxgjBBTz;gNhE#j zs!6kB-*X#B{$D@ds0@*=bz-~&c;v5VbepMVgtE+NnDA2HA(7_3?HenvK{ST#!9hTm zm^se+^VI)X%u<524qYV=NQ8a1UxV9b40(ZYYo((<-pgq7FNn%3LXA;M*&j& za2)nL5j?Wk+TP`BJPuk#4J;=B8pZH~`u3Mu=(iR789o8--k-EsAJcCHKl5OGwL%@L zmv$L7u_Xuq$*lz2$Zr9)OFX5H4Ly!K+#N#PNs-j^h-gBlMe5?$sTV~0!C=F!OCIhn zN$*zyykX^tBHu8E>k~689#EtPUjtJ{@$tLMwi)Ke`9V4BnipeK%&J#lGC60N!jGP1 z(F0U_xp)@C1P@=8X$L73<@aCjn}wbZ#}8Zzmh!_J?l0UQ?11)s`~b}Ev318ABsqse z>2S??xi{evOEm)%;Z%@i&h4)MoXy*>5=%zWN0nvn#vNutQfU<3kSP0^3oHMn>PV^6 zfv=_`2ldTf?E`EP2A2>og=CAbcKEBy#{O*rGNhRQ@q9ix()+X9NlM^W^J9Fr@F$ zR;WT45V)Th-jibLXt9NvUW+P&Y0!=xH0DlioaTh{ZAb)?46M+dxvr|kXB*sV4E&ZDnAL|UkuyBBuBL?^rC+Tj*vHR%5Lk$O(Cf;utZdA4ese*TW0$I zBAFcZcKGY}p9i2S80>}0Yy>+L`q+u3D|a$>E-o4Oyz_@kIF8c8`LlGR zYCbj1;BX#;cA~10VeUH&o-WK9ha2S~O`l_Il7jQCtsVe)v~N~08!2-3@vi;A0-|w$ zG@xF+->61K?MBJ`=11U9?q1SHfwN^ZnJLS22iq80)Yn*)%WTG@6cV=D7G*My)u>fj zT^e-{#=JO~5x;@sFF;c2&DCgQo#NS-i6h$KkdUA70~UGfW$S}$J>pfQA5b$t`Io-g zaDn%#!8ta!IGUSgaXqzcH`iXm0x>i*QsK*4eoS<0W$0T_Ov4Rm9{pAR0?baLq|^Xb zk-z$+?lik2DB&zVN)5ZXf#yDRo-Ue^ok731#_@?dF!LnZb|qEn0)mh|SADX>u!XY& z!Cd+wQy>tCq_+m<`EV5Pw%SW<({||z80kY5s>^Dm3xtpCQ6d3aYcqj?@`ycVC6ky{ zI@5__qt9Z#k}@FnQ+=T}w9}W`d~0TcP;Po`K%r)s_(G&*E4(|w%hrB7*0~wuxNn}r7D=>$vtK*L@Y|D(hm^Uf!!fMR`T_`X9x_9XSky%RlT&#NT zz~uizkSjQy#PlYRXlmM4PN4W!)I;d6daW9UAeJ%VyFy08iwGi$6(nyF$`aVgkyZLx z(B}A~{9624ZKzrFqb&B@Fx@ox43VaKFi$biQ9ediw-sGwbj|k)N}{+cNOe#7e)z21 ziflYy9ni+OVCgTV13^p27(4{?s5B)jIaOviyUnwGrW_nmPrYfkx7f9SC*@l9-tiJT z&wFs;7pu8CtukOIsmoFtBS*)C?lzeAF48m3F|a}^Wm#y0Sf?ex4i;r{+#cE3Z<5<< z`!U7;z4*8ig4amtI72xxtn{SsIsk5@6IMHY%eRvzYE_!ve4&QSSg95@g+hY!SJRF+dx=ACA^<0!=(}K~Dv;~&*(Cam6*+5p%wL-8 z9~C;GtOEGjJL$uxN}>;2egU|kAcrGg?`5<4Rgs$9Gzf7@oXXJ+`s!N&99m`q zgAkECm2l*l<82{QR5|9dSo7|38jaOUn>p)Kc|&)xz(xepApbr5H7gyiq5UY@_+rql z9YCYg-~)^*N}p+T1sZrBVh4U(y(BXrNOPkKCEIOk_x~h+1&^@#&c^A5uIgJ{hxNZl zH9ve??#sud+w|kN8`>?Q!2h1QAj%S%6wF;1hJchjMeKvXb4Y*fo zSCtd9*rD>4)^Tos?5uJs`fvO#sK3G^D2$;N z#oGn+IFdpzV6V5xsViYg9n6<_c3kn!pjXHE)W4j>j=X=3qI;zlI5}bi7jVd-ya!zR zkExM`C0&9+%l5(Gm^^GN&z%6_a=vV)z4zU|WuWx4J~mm5Yjg8kXN5m5fmHsG#oLi+u|8j1 z^?re-HOGL+;}1Ae9T(V#CCBau@|AD-elP5l-4IzNr9qe7qRmUT#nr`I>-y+yLiO*+ zBB{z0x~rQJe8mDPBblx*RL+a%9jXjjh{rHCN;QZC=v=m|K`&=;4`)WxqxRupg)>Zy zT&Hua%mEAFg-zW_hrc`uiQ?B#CACsI60WWpl_<8#xAVdw>DDo?rETp=4rFWV5a>e*fr^OraI#(&ZkV#T5ZoEoLg&H=Qaw*w_%?%uZ-%jALIw_t^OX6O zaqd_u!@j)P{Vqx#WejjZo^%n$ciZE=yGxtcmo$}S0nj&_qXQV*4V0jKEkXibMV?`O39`}~!@QxO= zAsasMbV;|kSto9*%a*8u7V`=+9wetw01pqrgR4qwSam-pY2*yIdlr2!E{@KtLB7UJ zebx5djsF}h+dvT*d3K%Q(XtDmJqS3^!_HKYdWd_w^#vd6)Qc-2`_VP>nq0kVzPj2a z52Fr0>r_twGJ!9+18vl1@R3ui?>o?s3~`w7U@!!8TBuM}j$Uo*WOi)S60R?}_P4~E ze@Dionazd;Hx2qIiMaEUru;^OM}VD`M>suTGhVb}hjUI23JtgcjJFx=SwrM(wf9fe z-BpvjpT=vcsCgFvF=3q(a*JTz(QZIq`PX-nNaD6oK>JcZb!5ZgfR_iAQf@aaFYQ6$ zdKAVEnndqdGJ+v^_)4o@nvZ6uq!(ZmImYAGwbD$$Q-%y&W_m{l7v5j#b8M6$kAtAkFBla?(`K}? z8w@{_8I@BIgG>964mhoZ-He4(EF`OL(ej|{?DPopiNhSYN~IaM2k_QrtNJni5-!Yr z)JCLrmv#J9F5K3ZK+}LN*OS35m0Kr|%FQ#_i6`R``16`&6{lL82wfBu$IM8u+{xx`A-sC&1t8QY_Q_z|r2MW^kMyhPyRZK#Sen zUYhL>t<#%FPXT7g6GLLDF?fadSuJ84^c?*uKO$$LA>hUQopwWl5aOpt>0SMtJ}AX{ zU(1%U1wdfqgh#3|?Uk&M4}O~?!nW?HqQMM8U(&UNGol;Ex*y>Ag= z7<_f1Jn23)oo-TT`srV6zk*61%rqZG@GQ$&_wCMOv{AbEXXezAC z0t5OEqGI{x0PZ(v4sxw~I{ve$Q}Xw*O%(FBAzf}&=AV^4rD=U+Zltj~ZE2}ztw-fe zATjyF>?^dr`ReR;*vh-=;q@pw^XaW}Fvc;{Xzf*jwtLg?0OgQoRVgT$v|X?mRdQ0Z zbYn(ik;fZ+wrC1!b90m06GvbE%oJiDt2tgQ%lgv+QNb&p`TU zpYEtRT#&ndI0A6MJfmvULcHEkIgS0fBWIeCpfH3gF}bq#poi0CP;d#B^b@q3 zwc$ozy!G?%D^phYdojRg+jf)b@$@~xRjpZ&oaNyvypuUzAz0v@X>BPIq4s;~N~xD^ zRlg0bo2Dk7qHhQ-vSV)vDkz=l36Lfi9t`>5--+3jeHNxn&&2kGhZ*Z}Uz4%*o8(bC z*7Jue1u;NOBHrEJ65zv$Pn4pY8VML7E^9u5;ZBgr{4!{%ut62C1@LS9lRuq{YCk0Q zCGHyP(B8PY%s)2^UEOxD2_se#tl&|C0(bw`{3!I1QKvsg5du55k`>jiRN zv)SlinhV(ch2jqdkGBumP86jtQijeKyn|Hoq4eo z8EOzj|!)$gn{Fb%F&KDO%A4L#0E25AiBj5ncgpUt0PUS=+ojQ^ED z(i3%_`UbbA;Azl4WULRa!+51pnMWijlLMNqoq+Y0uSiaz1JVYd=k3RRTafKrKK8jZ z45S)ygaX%|-$RT`cM3RCw2M@I<}vAV@fbL_G6-9Ck(cHf0OEA3eZC?U>S&z+NT0M4 zgY>3kk}Y;jmkmKjc`2csQ>AdNTO%rsp~pE?)gYe%u=wHa*U!94&$`o3I%42RjZAiR z$v_MeH}wZZ#np=altkA3J;$zVfwoPb(FVK3Hpl(gvblI0Vv4Tv-bT|%dz?Bfij+Ag z+2pDO2=Q`rxLeO?5Q8AA1UR?78!-i&N)3A$$@g0Be!UJDJnN!Bdqpb$#*2hsx!_h@ zgk-#IXV8{s=F+PJRl9}QHB`d3cSomr3JANWqa*2G@KWT0oQF~Yk_0yRs)!?WlUunr5n(TzG-YELI~;`CnfeNkLryY5cC zm*#(cj{%pw#{=Sl;_TD!j@d|)>~5UWPl~6xso-$w+wd2i@>o@bt+9uD?Vv>=%R1{% z*$rcE3&F!l;2|gvabtaM;^DkUfLNnh{HI=-Ewk+%9M5lI@eu(S8~tO-*oMUF=h$ky zQH*noP0-S1SaU@;5&4jZ?Un&fW%0VOp558ivL&NDl;pZ8VeeubY@HB~B#tH$dWPfP zs0zTCyYQ&jj2(>^pxF_1yg=`h!uDb^^FdZbiNKo z%84=jz8L1H9^+x>lDSoriQt%?0|dv14_W3{x@C#KQ?479t?{1VgxOFa^wbtp!{kxP5=|4%|$Q&W2e_Arz3P$_Ot4VmjDnt3W zQ^4hTsqn|4P3ZJvzV+e^i80z{DHCoB@d%|{HG0^}lQzfj3*45-36{#c#s`1BNa0+i zr_MCXc@cKCHEAywY+J!vHtAGp^<6iD02%29EjiB=NNMWP;yRuC@wvrJjwA}&3$j5h zt4Xb9ycZK6;7hW{D8yR4M*Qu5y*zs2&6HZ~uo(w_=nF`R<^s#4b;4&A>08#b=gFAA z)pJHgAUlb3$g1f6**V`5NTNOu%{U-eeMFud4<%&PT%>1yzMU&S#+@?DmHCYt^bMB#9*NX6I3Ix-wER z2q+voD!;eF%V2O!q^~U5T#h(Hu<)0_bn#mOE`dUnN&?qgs34+XrO|{U+htw9Xbnfl z<>}s+5LOH<#0&@pbR@mmUYA+#+qBV8IcnaYFb9niMCYgj=)@gaJ#b&%LRID5cuPa3 z$3V>22z-BH$|R}lt^Rbk|CO73jP)<2E$!r&hwW&qx4&smhtMB8hz zLC$97+-EH8Ttk*wLv)&mmpx%Y->YY57=B;87)j#;7-ecqDO4AZ9;^~Qc;|R;M3n^m zAqv`N$C<0KqumO(Gc);+SC3sXOhT6 zLvE>grQiJh%gexkXc1wfRhQE?l@?EGmCnTO(e0@2YJp@3g#4aXk@$}|ONy)8y<(I2 zFFDbDICkM;GZ(J%0RVPh96VDvluaePGx18CghmNB)NeXEcL=G|46aHle|+$|5svFv z_N0A(ZEy6q#y%(FnbBoWF~aC2Avx6Nr$Ql92LP*2o1;a4WkY~PUiTZj2}t+LCE5{( zrJZJV$^rGbSQGKFYsw$MrrQd!*es=%v7;w=Ah>lCUI^o=wv-svFk0dhzu3c|@?23` zt(i=>vPd+`5+Zy`20zhz!l%Lb0j<^mbZoAx5=v~8keRyd704fUa}Eeks>Fq-IdG!2 zVF*>K_fc411fuPbMsK1L2q|zxA^<*M=eB|ARwGaAzGCA#yf9Me3E<77MN6jGbNUy2u+B~m#-Y?Gttt=?_p_sL;@T?UzN?QqVis{= zo-X`UN<&pzslNa0h-|%8nrisdy+w(u_IWA$snBjbt)szxs7D2()_wYcUN62@MGl)I{C#zF}s@tD!dz8epA7tv)hY#$%DxTZmqR zymJ>cT#-+W==Y!#ut|6E&#AoFaes-M3(e)92e_-bbz20(ykXf9^j}zLa{ojP$;l=L zWPc_@6*esI+>hVZU{B@qu~3cq!V<|apZebYG@F-KH?kOHbzF9>A@Ji=Bg;#p>y%WY zOE_;NDl9^TsKK`VPqlDQA8YNRuDXDHqxVt%nVreYA>XM$jW7~4CC?48nF4)7Krf-` z^j>KSh5&LF47Ms#g#&|uiZ)2hIR{gCRGFVicqXQG$2hC&j_7Z)yY~z`eR@CNSD|;F zz9HY+Eq*Cv&?9!A;-X8&9E<=KI0mOi5~k`saiy6GK*yu^{EL7$9W|Uh@J7aBUD?{m z-+rKqVwzNrmu>mdG{yF$B~F{?PTF_p1Qls;?_N zYz8_q`lH5rbd{jd3h_=F$3}eJ5>jy4(&_~V5sY~K4W`)!Rx8+Fm#BZ=8!&%fal5`D zgV3(r$i99M4a+@)k;vTz{wiu33yd;3rWHLF#pk{K0Ihr*ZC8$RdYI&($ER2{PeTyI zUJt$@=uhU_J=<0wKY8`BSjHWZ>TR?Nos=N>_s=3r#OHVR)WP+4SSnD*$e)HF2*M)` z1(a`nH8!C}PYxNRd+P&N0%2EaYx9}$MnDLYQ}-Pf7P)%ZCE{bF4>Yh^OmHsl$ZTg5 z_MG|xU)5`x@E2#W*n7A~X2XWJ+8HfHGR5i@UThu{rMpB5J41eLI_hec0YBur+!!&3 zGu7V7iQbxDKDlux>K1j`YO%W5TuS$>X^Eu8EM=$CCh z*N{0UY=Bf8y7Q4j1NN4qN4t4R3EJgS9C-wNdrYZ_z!b54ISEI8kHJ*hqRi5Mr1LaQ zEEE$|b5{dc*?R#E%}WqCPoh<+9YaG#>heml-5=^&{E&32MEC`B;+9>MtrK^p&HhqU zV#2fYagK$9&4DEGSvu>66Up~e zW9bi|klK1I(zXsZ#LCy+t#5a{Ig(4&jaV9LHG2X)lwqyyw85ig3 z66n!^WoXB=Wx@ZzrD^ARersJ9NCXQo4tNx{7z%C(kWFh2cGv7L*h*g^{shTn`W{Gn{?3zX zGpgyC94SP+&4hnJ+XK>tYmHD&@H~{YV}sAQ=Y1M30lVTuJRm8j)ErjI8t|D6Y%gr< zlZ4ybqWdV<=`xNbLB?b&zcK;Z4*v2dmWzJEqqfO6OY}A%@{xG}-k}@cO;j3mk$w^a zRCR|?;OMstf^Ogz=N0J}{2|R5ubB>`GV)mp7_Fuk058Lqm3BK~GfZgMrpEhqtvHF- zui7?!XRGKfwvNg3GoH}Rw=`8^jQRK*RLE|eWbyFl(B7=R=7z-I*T0mv-UkLYEmV>O zn-R9SUP1J9%Z*a0mL*fBCM%Zb!?9iX z44}@Aj-=8&`>NbdEbL;wiExD#r=JT zzQ)NjM)Zem=xc)*M-S?;q_(Nv&Jo39x9pkR>VB#oSP48p(D|MkO%f%FP@zw#YQuvv zMEPemW+RaWn#O|8h;f(`xdBM*FjKRt55+UrQUHETEi-7BCgH#YFJ0Bn1f8w|8j@JM z&vlzb`{vYo@m+Mk%c?!gEk-sF7&K?wi`9@PTTlpmc^zLU{YwBLetf~cF<0cPpna<+ zkhY;N6W(C`kdk?sJQ!hqu$d5=ZqG=g&n~hg2vJ1rvSd1aH4ozB3Ni!Ewys~K8OavL zDlGmNCv0Mm5#3U~B&LnOcbS;q2DCJZ_v+npEHrz?oK~h|1EojC#}O5&8jC7sc|=oy z9RgWg`FrMzmkpJB3RO%9pFZys|639Oko#|ck<4?cj@Mr#hdI4O#F_eQZJD@H7L<2g z*7>4b^nNe7q6tI-kS7x9usqb1h9`N5foVdcl%ycP5|A9lsoZ573~o7)UFkPGwKP4s zdw&$8&i?MY$Zg%%$)B<4s8_p=e#$hdpkg&Q;KbIg+|NnImXelYIx#MwobG$AR=mRJ0F2*`!2TUvp}-9okDq7>O?oJ3gp8Iod)m=$iGpM=RpQt;CPd&sjy z>{hTiDTJ*aYEZ7?xMe5u@^^?Wu1^8uPb!Zcklm-=%3PJ?Un1)4!MO#~`vO2HC`*l# zprzJAtX+Y%>P`KEo0^VFM8zsBIw^)C)eM#sB-2yf5t{q2gz@5E(sV)K!gp5aAev5S z?}SQX?~Xl37gZQM;YSyl$NTAK)&#|reiZKai!RbS8hoXd!l%kO>G$P10jnn*`HLAM z4^DC7XS5}fX{J_){W>{=H4oC|A6YgMr7pUg|vRdI2DZO{9+iS(JR< z$7&kSjJ2W?`;xSyGUu`c?;b9csFz3N2hwxjfAS>arceQwh9b*Fd<_{RKLu>RUPmy% zcvC0P7b!lDEp|vAoLA@Zkf;L{3|pa;H55xO9?p+s@-8h8vL8n_$<5F-xQvN2>BChA|yQkwJ| zVO88=loXaqf^Fzk>k;;4c3wVExXgk!dhmguoCAd>swVX^e+;BDt3fh!!L8{iTyYyG zGOC969DtAky;=Z9X=$DNdDtg{rVOv7YPmrW$lY2XS{q|^S*fIgJ(*nd^C6n1i3+L? zMp^o!E;)@nR+-8Ijb|J=OQQeIqCSW^e-epUC1)&4V4>HVJdJi+Xl0cHVQH#+TdKo7 z0{7wiS8HZu`C17fHESKaAF9pJUuueIrGTcIuHK6s$qLFEJ+Gox*)``!W`DP+H=jc! z>fXN!yeKgdm_4flxKy;~Gl+mactD?EW@jVuJr08k<*))>&aBTQu#TNoIC=8j7UnRp zHq2$+!x$EOnixke2(bD(XY9;c!mwDp?Uo&l59^+pkO~2XG|MyUfCvdnR=@^5RbZ*- zb@rv!nDj91dRttwr z9!zyhnU*9L|A!-=3O1luQ!G$PL^S6nWt@Nf@buWo`lS6`z#cl5_9F#OWY(y;lxEEM zl$haOf$7k~ByLq7E)JgW2fSw)!?q)xc2rZf=&JIsf<#8Ya^^}UkKTWvn?8ih zRX~-jIW15L_w&hD5KmkFy(@;g7<{h60)~5KYYtRojaLRR2DC}o1{UU?ihApg&?TEL z?t#X5huTGii9L~xmho9S;j-x~&Ruv0KThaF8 z;5x5bemgy0ALt6gAqsPtdcT5*E@+YFv0Cjig^arD@KdyI#!o;@3gVBn1 zLB*y-7BIuq9vAbQ5rApx;VA*onRTBrni^2sii$U0h5iH~J>z?c>e|og16!8n$6t(( zr7-b5CL$T;M9-Z~?0HfH^Gbt+Z(Re1y|j{c`#!F5O`YUviO}}&rXPRZbc5&Z9&E>u z+xNMQ+8W0DUUzUY_0%@+qh#aaja|t`?4cKKnz2{Y>>Y*(feduiHS@yLBMZ9VEu0t7#zpf<5I6QR-= z>f7hA#exy<(7R6U^;EK=L#!z>r~0Larn2gq=P5MqgCt;XQU`5u%yl`FKHotaP4&dF z30DdJTe51MsG_5}>i6z+VqtdAzIaXXpx&?(FPT{;mJcCku;=!J$SlRmCAvjBJtYA9 z5r*pYDYql55lPfb!j@Z}OD?XjbE%0dnFO5Mj57OxEv)StCA|$h?cpHRm5&@$m(osc zwo3ccFI6Qicpk|TbgXa5v%+vqG1Uhk7J(2~^b*x480aHemmLxjv(^HDnJ*1DXaD7l zcVk=;(1ukeYnk9`4wl|+%6rBr5bFurkHWtunIC8~ynEwzdx1o|4Wk*lex%maxBm@W ztw+LtLfu5etOP|Wy%W;|6kMz)pJf11h2SjB0D^{JNkIj&)BQcB7z#DPCyY&^fEDXo`~w!nX*C%B+grOvr=bt>V&p^<~a~3+DWi7i&419jI)CI!=FZ$J}xH6Fr z@-r5a0SsGAS@ghmfDCaPWE1+FhXOy?xt-VOCS@>u9t9XxYYt(Bf;%q%*PrBIY|xAG z2q$%*Rz57Ah$pG}94bq&luq_~1Bnk%lSiGt^Y#GZCx3*qNS&tYTx8S2S3C#*ZYSLi zaR@K_Bu#V|)g=xVO9XAuIfF093B(HV>ne#x3tm%J{-G7*2VWZfIDp=~tW2g(|KF&) ztS*K8j1dLarA_eMj%OU6YWO z*1UL|O#ApM{TVt|SSy#GYA=Wn8v$0RUvIjkWvQdMvPH4t?VR9Yb=-X1?7hEMEN)x> zA$%lsI z(e@Hz)y|!aqALbg*kX2gxbIF;fP{Dn<==sN=j;uvEy}&eaZj30{fsq zf^T{t_NnJf(Imw=CV0KP?~~dnoV413>Ly^D#$3BXjZEv$lWRKHqb7h`5UP?g+i@DAjo!EbQ4M;6uRziQM0MQ zhUt6j0S3%2VX;IV9k~{)(P6=o$$ce8ni+Ilk}k`|z`lb?kuz#vE_8e=NsL(|VrE=W zp|rw4v6)=W$mOiR^WNxxKwO)2_lY7{y{d!6rCM718kQum4z@0>)PLf|DIshC=1DgZ zrZL!dug;LR+=FrO(a!P9A-+JU{W_~TKG`UC^$_Tq0Z~F*RCd8lAzoEC*e_>MEW{g5o2jyFflsESJ zZ*Me$$Kz-Kc=HUY4J22d;972^ON?hnX5N@l>319CaaYy2?39J8RIk#kh+a7}VHLyh z2Ola1LqT9xSTfS3a9<9k!?+zWQi_a3MJ_O?1;}H2j0cS@BN40Zx zlD}?(l{w^qh^*W4*1ahUJWuHd((>@dw2Gi z?`RvnsS5e|&Nvls$@X&esv0P~j<_*`64{3z8GcNyI5y3Q{B8cHm!`G=I%1{l+No#M zWA6~xd<_r)4}Iwdt&=D^|Naujs+zm9`*dmX^z8{1cm=yS0cm>pzF9m5QVErRnG=Wz z8Jz+$%kLKiJF&Ny zM)-HTW2@TRg8Q06%|#}BV99Khp<$^QLy&6D*NEuc|0M|O5{ihia@bxW1C2Qv94o>vysp3hq<9@p=rMv;C*OrbVKUWY z?kE6TeeZ(pAJEZ>n(_Cg@j(z!j~eK)R@+pN+(U$?98Z)0V7ebcf!kDQUgoYeIKWg@zMO>f z7I)38OR$@BLWI^r3?EWMhGeP+q~Dt@4*6TrYamz2Qq>vW0wJOx0|<@nTL1<`sSz4v zpGt-IO7$T1w^~2}GCel&l~^T*$Th}r+li#c1WHYQdUAPND2MM=17R0!9}K}1$km!& zCQ!!)5;bjv)~m5jngQAp5KujVenpPsgWU5h5}rG#9>t1Do#=BaizN&DWvbhfEY(`(b`Xre1s$};&msl z12*tsUy8S~UjN*@guJ1o`M=vNVRK(da9}z5N1$my$bXK&AO2ezXrBf$w>?`HSWWz&nGCQR>d;=MyU`+4*^Iga@;bw2Q4&A|`)W+jwv_{yu&4 zbl0dZ?-o$qHZ7$*zw??mVf(l>#*efY$As(WLOBCSPqANKOidsW%>V=aMqUxy(hyUrlP2>{q}Hn;?t)O`?RozCcF+ zYIFsi+L$Kia#hLv`13WdUO60{{|`O+2uZ?O%TL+YwZk6f|3LX=b<=x$Nw?ltf*ea; zKpz5%1Md@8b2J#SPCwusuFOkL&4IW8>HCeB{N8IfOnORGEpq^(RHncs?m?s4VDzn+ zcsKPGF?h_PQw-Y?4zfuWa0_WrU+VDb59-YI#Ee^$UxEOVZ;m>HIJbd=6T~tr=PLjd zmAZwF8Ptb)_7~UDMtnt&QYqHe`E_FQJJjPzxi650m@x86uCl_kPd|z}OVTAqpeHuG zf%4Tp*HKU+{HT?5oUXt_sU2K+8PiBot=cFMU_Zo1T;!BxN^FiIeATZpw!=?bq7}UY zkYa#8Aj%b`&O_xK%m)4yp4ad&DEHv1>dxhfCpH*cjb6qZ55TZYu+1da&5|soP#y=d zJqZIb47z;J+agHbODr^SY8IhR{B?+xR@jk(F;rYhvJNFVr~pv#yH6ObAW_hau5QLj zU4Kry)S@iBgSKDqMV2e%&sauq!__-Tc=}4=J2ezLbV8~Z&*qyF3+!T-nt(vX$Q6~h zST=uWFw8v8G18a$Y%GTT2yzKK$Brp?sV^f7dre-*&srs)hr@+Pkq0M&y3+jmoxE-a z*V{KM!xCkQQ9f)u%SZ4W#fpX?6wt)fUA> zf-a8{D$@vYkCVBn7C_ywQCuQ6T+wd#Nt?=8<6NhF(5K|3e22BN%Ci16U5@(OK(o0E zE}c#e5_1c>x~9xTMk!x~c{MhrlH{MJoe2On&y^+Kg$RSTj0ZZz7_bl-@NNr+3<3`# zFr%mOV7ulLCc;nw!8w-4>pTDEbVtHKO$)%rV@68c_P(jqEiLd{86@?^s?{EA(?YXB z>}p)JkbGhH^CqN!xMAKnF~-J<4r$YZ#nrZl>wu*O=c99t4Y)>Gu7?QAsGn0Dl0p=I z7tt=YG}rSrh(@1W@~wT)%Y7P09DkB7JB|}gx-BX18#b_o-G#dKk7`TR<7MDl~|f=SK8m7eTu~%EXIc3FvNpC z%Lu~CR!PZMM&jSnxyFv2N}0mi%7B%eh69v*u%kawV|7k^4mi-~!j7w@1R|W@Hlyg+ zV}nprc9^S)$dUQ2pqH1z&6LPg+!RLPU1IOuZXc=~bKLo>Lm+eLW_O%<^R2L8p!FsP zhjBz;hLu5X+L`~x#^HP~A)3}wkuh^Nn-N{BJ=`EY#l0)vq?#^VwHpqgpL(J9R0iP% zum`^+u2!CXiq80st+ydUukWS#T6C^v3oN`}(3^HjfsjX}2*d2m@27)x>#S!C5cZc@ zrg1pURI!@-Bncn`Kr`(Rs_UX}-eWAq+6{;EL>}jZc#Sni*^s2jB1`OMjIteC&vhbP zRB6#qU6A8K-L+IET+4b!_V0YjKj7nY!jc<59#k5$w`p16Om3ZW=^6=wH$}YZsztVH z=~~eqC{%X(wMwISH{03Mv1N>P!Dkwh8NhJxMHU;PG`BTQrqCn@pe^1BLULyXZ+8ZA zqS=hckZ!M(Z#bzS=${+*rdGjVRGkONpyH|7c`v)P2;Uhwopb*g!WRI^R9u((Un>fUqNk*q8^C^;kV7(CLmx9-Ke9kJO)y}EDK_M zze{8C(O6))fcoKwd=NFe>4USuNWvjwy%Qns^9Q|M-pNIP-cU|r3M-ydxLkQAY8V>J z-d9azeX~`}c*qPrV>-o6w|~@YN8I0D2w%_%fa?;4_K5%>!|=V@an-GCVSIgD?S>*ujc*N=20hf={^t8ZF%`wNvS zZ)vAQzjqSJd|dMfIeMQJB|#fVF)w{AZOOX%9MZooMTuUNzT3bG{c6=t=BUs}V%o1q zDT^M7Q?jL z&A)@$o}SDoY>YxZgAgM^?a4i?)PO1byXmE8h~jsq69m+iV}OE@?-$zOD!sZqjXpoN-P5mgiQ7-^SXHfeTltFoF8%^iaO4yP`7 zlHBB4u%$SCD5~3w(fOL+m7&%W8{LXk8er^;6D?t=K;ujgytnf1d)DSMsB{p9onodj z!Bz0d(DVPfc&gwKBqbUhYH^O1x>O$ulm}Q@S3fH5gp?b+l=Gp)yh$vo0lhZ!=`cWIpPubM$ zS}S{By&W*$8=V6tsu(C&=Y61nZgje^{&OC zyus#Q7lPE`YD{VOc-)kG)lKnXA;ora&Zh)e;63f5!JlU3@f$7pCZU%`D32PnNjjli zpnI^}7bHe6haU!wMs*MiSIOromJd2iL)#C>QO<(E-q@ECxHqK=X;JTp>OuY6P~9{`7fPO7~Z)}TBcAp1?PTTg#x^qfq0l#XQR(#V6| zDwN|1NEfimHa^})SBu0CSCVKh0UHgQyZB zMo&H=mcV{g+c-7;Evz9)oNzRS1dy#kY_yS=UMUf5Qi~?6*=)-#L;d39Mh}^pkNcEq zYB%jv14WSKSQ?JetD(bzFV)lC2dW}2m!PovhMj8Q-4k2;AcbG>!SgGJ5lb9x{$DV}vR^y6>>@eonq{X-JXm z>%?X;&vS3e#5iLqY={?;r)pKDcEz_b+o??oY@;i^R|qSQ@u;_%30$rz?-mYdew$9pyfc_NI@R^HzC@DP$ReJM|1<&+mK(^eqge@khZ`?I9-x_2i z$owH2npXp%i2GqMI1h7yyBHeSwA+5aiE>YLzUP>HrMBvU7J7ed>uaTj z$;KxcU@sCD#9N@~dYdG=ekmvzyj(BKvP02YFw@pwC@uUq+s(`buVmf~S=fKI|1H;m zF9e=Ghm}jGAQ_1A)QXx$$|EVke#)jb+DOS}*=o8?9eVRwNs7ob?Ch18&juHS-tet4 zmY%tBD_6i0JpEQix;MdJbY5co{t1z!0K}@R+fV=5x;h33NS^nitVQ-;ntVD9DW$^d zY;l9hOGI?SO9DjFTIc1siSUz6fc}qxt-5lKrpgwkl=okG7jGzlbRWT}H!rGADQG^H zYOP}VcKC_%HEK-x#VG=tBd!3TSu%U6wQ`l#zkmaLt}Yyabp|-naP?xj>Yt40K)X^8 zugvluIt&|E$uSPgd!+CI3B||9j{hXLw_#%M@Qsmc`M<;qNsT?uJaoi!z6$%>tSd@_ zf&88w7Qr%kbSd9pF4zxZ|9h2i|Cl`CRu_@=lqOhF*!B}NZ` z`|2PE*U||cTk?C{e2(&wEL>SnU~NNitxS-ApAcNvw;9rDHkH@%D+p7wh?S2Zy7L?{ zJF4_a!Ry`G59?zF#2EWFs*nMgNTvE#@y_%*HS<^VM^Xn|-2}S@rA-FHJURDcxEBIo zn2fbfHa~l5ya#*{ZC*1v?Kq9;Yq3Zo2oD;niAt=mZ0#n_is4U~L2@{eebW6wngm2z z$@1Ophr}foNxJO0;!tg-7>OlIl4S9x7KkttygUN zsFkKY>C1)2X4wir;}@6wbrG)dX{5(GO-sx5lprx5I?|mE3ExtwO0f3b-4p*Pu_J;v zD3fAe0&hz^ntpx*f6?*B>g`Ff<7ktn87(H|5^UE-2_b=nw5*U2rX{w^b_?V5))TH> z$6{-(DrtS2(Wx9F%ar)$G9~-*;!uPZYAu9b6!9C>yFT}rA^~d@0!?0ip{*c zALrGP*88hlUaOl9(<7q$U8QlP;0OvMz<_+)PTFWrF^%D?=M)a#S8df8LK9+u4mK-D z3!2|AePF=^LreU}VNECv{Q|5}yx=^rr@wR4MCIKRknTuO8>1{y9L6g8icvG;70Tcp z__hxOIN>B$pN`bhjERtcg-w0gdA7huwtO)79Y!$0RM!Xt-}umJ!<&A=p(4)x^@|JC zpBN|Ri{LMj=NEs1GY7I|!$a8=9+r-_(*7JBqJ?BCf0E0WZ*`TU0~mRWWB0QJmqrGv zRqM~ouEABHa-XUIPgwYSH?OuJJ-)(MX>XO`08iGm?Dm2ej+tJ9zNA+!nZzfyK?9wF z6>Ai}q)F&%vxt|FW$X1@iaqF8n+>%dPZZ z4FX~WKOG>suH`&${b|KT#gV7`Vp96hiKqV~6`FO_N}JpvPrWW$$3=){o82?t;aoP*)uRY++VJ%gM`J(@^loCLIQUv+)C~I>kf~v z+z)zpOSNs+_LT@F>J=ab%|PrnW*1YBBY+z?Fd|VNS=(edmC|wvQcF<=P$sR3r@W($ zGbx5(9K#DO6Qha%-d(FR{1kR>zPW7?u%8eT=2^+Q}+`5mie`c?y~pS;SUAnnaEH7*_PeECQ?`mpE-3g+v8N z^P}5bYk~l{(z3pw^1*DE=)FsjKd!bFF)OWkVqID=k3~%2y_nA)zmL!{^TNb8S(b?= zfxA)qffXF5kx+K_rf|Hafd-yz^q3o8M16vj4!D$M=fa3BlXeHo@|qtE=4^fFtcGQW zQSp@Sx@HJd5}zVR_B0P&(pHi`YWvcF0a1zFOf3Y!re})dg2kt(m?UufF z_+%RQ#2WSU`mFY#ne4r7h$iwjV`bJ=*4VvQl&i7C(NQ*uU%haqG2VE-Z%;R z!M4;R_)8(sUB)SpEoV3!Qa5LO?1!y#uYI4jHdHcH|3A}3R0}i$*@}=Jo$fLQweVJv z;8mtcS%7}{WXPy5Nr!01;Kxx|q>vPMOw{Dlpa;p#l*d-e$ zC}CiTN6QVc7FkNP9>QU*XU&oQM#b+v=2!ZlF5eW->BGJ#fYB&8D zwLkVZt;SLP$fcXcp0{|Sgt3|!N6{C^&V(P`tipZM2a$SQU(kGYK0^GZQ?fKU9zlf! z4f#P3%dlDd(Rr->qW~%ho-ZU6+lqOMjSFq@C!bed3^dy_c3J!huN5OLzVbw(orki2 zto>v6hRU2nBfYW8ThJyXAqroTAo!tq?cEx~KsP|M{!W6CE5yyr@=o+}_9(wAf=JFr zu%*DzWcjM5WSUK0*?Ntkvvw*3Sh9q3Q}s6G?1R z-z@HifK1b#PS_L99I1^)T3{vwZEJL;mJpE9+!o&McoqVOHo<0l`Nv#l&=ZM9q|X1v zK-yDE6GlGE%YrWU$yZI^LWZ9@kH3Zn*(yLoHL^tl0^6xaT0)i3hy2r$QR3)b*c z8Sw@#nhx&X@wrEwe)tJ@?rdu1W0f_xea;Ly+XAXS<~`y{&8q5-u5o+Np09;F@OaeU zJ2%n^!0CbUO@xgn4DD5IQKMZZIYiGl*UQjO)oobx-(N`sLB2^>K!nC6pt2F*?0*Zt z9@0-@&dljmitsp*=0(xstf=)W?EMy(=*fFFhJp2IC&GHeJaVb>iJi2hqHvol9f&cB zSz^aIC>`;@$y+SJqBj#h3f||(hM&Bb#|I7Ye>-3xPN_)xGloS6v(+VhUFvx12_ z(nrs&A~YyjfE>VYm+diIcjq-I?lw^*x6DLhwW}<7GcE3X`^V{hD%WT1@RFwUPYLXb z92#WsW+L&4bGwPzW-Pq<58)FuWDaYUqge0~zSrb?LU%H!hg&D-v$IcTRCnmGeuoVe zkyP0IE*_|v`cP`F0_1m2GVQ^k1*`*~HNn*>&%9oIL)TiB*7Okg(10$~N>ctpXRnYzEZ$9S9Kg$X;SO5FeqUc{ng!*YN)*9C;f=0>LS zMNtm02{_z}-fiptw*a8rA=(wNO`bTz`GRAUWyPh#K*&-kBdwz1CqkMCW*V?Eo<>m) zvjh`fcWF?c#h?F8xUq8C@GK)Nj;rR}wAwszq7!|$mtBD+ebb4izV{f&uDup_(zp5A z;R!>^5Z~#yBmkrFsXaPwo!*?G7uEcw$aAX?*%P|vJ2^!PZ2{N5#VIJ}#PjymkqFVr zW63uyg;m42%j_HXs;NQP4b(*2EGbQ|EX%(wiY zZ$rd}`u5Z-%_{Xo;yNQCccK?L|A|Tx_g-mE3u8cdkO7U7l!}RilT}!GhgjPm|2x**_&^PAj5OQ` z)IBmoA7h$uyA!$5vrXE^qrnaE#}qZQ+sS}k1B&L{Bq*o1k#u+EKHA*+=5G9DTgthraCobS*y?Y3raCelx#p z;`q7U$gni$50_!UpwL0YFApN3JmViw;D}3!MQO2Om&z#`cep?j}Le_aY; zRP0@tbPrwT@2|YU{zx-L{_w!#QDu#M7Ff@-omK9jmSJQRwn4#W0ivi*f*QcAShnL4 zgHTAaGg}i;+wdSxQ+laM+0bqLbY!`xA6&xuRHwYK=)R&2n5^MEIw~TJVIoFBj?Pk zAn{YEwVw1Wu`u6}wEjz%FAffs#aVh^Sm;WGR%YKWvSTc&;!jI!JHLzRGnD-lzH&HR z9LkVHRnz`KCt%=UDv*2I^{Eq<$pZApA7Zzu%NgK7K&l62WP9(AfeY@|v~}IHX;Dll zJSQ(CHjP&$~Yce=+y8{a-d1V>AvMr$TW_6sKFo{dYJB4n_Kj$Am_OoT3la5Yc z&CW=H8M>10skh5h14l+4gz0rnQ@okOr>^(oWJz1~VL}cqa^>&V@h1i1?@pqF5=h6o z!wmAyl1I@O1_IJ_WUgry`Dxos@dcIi&l%_}-(k13ZnP%h zq%1ULYcA_81%m%UNNlBy>ay)#hqbwm7N7{{{s8Z4Y<>Zl$v7Fx(=|2j@bZiG+~5mi zmLOS^t(Cg%y={$l(w}fonrvrPg`Nb|Np?d@_Hy0UHe04<9L@Us9NN$bopv7Y>2!~O z1+`-CG{GxkcB-3^;$$=Whhcs6EID#|N)vUUPviERhFQP5HSk;%##M3%F@1a+$qs|%r>DCN`u`iy6q ze@+^I-G1klh0vOu#mQ!@?kN+j6ShSWP=ZIrn3RC2#}V z{reO=!wWDA_ATl$RC>*IwL>z9p-muPFQ8pkVpB;OnAQs3sJ4pw0?m>@MjQv1%!^eY zE6+=#KbX5Oxttopll|oWE86<#rKmAUoroZ46)R7ar4((6=HbJ z5bm7j@~wVO6|TYDDy;dU_@`(Q3dgk5<2eBwazzkW?>^n|JFj-AUi`9L``}AN5$U>hzknnB62><6c#z$C~|6Rr?=(UV#P1( zED^U}B|fT5wUprH&d`04oRV)(zg4%z#1gGCb**!yiZW{H_7U%v`lF}GysTz)5@(T< zX$&SHi|ApHl$4VEv*T{FHa6WcM25zsnY- zL#}7DSc;c+Z;z*We*hnIe5UkuBSsUmr{$Ce6ndb4=U9&sSdG!No3-=J7a5JB$rM8* zKvlKJrL~Zv*^|EXNlBtmb@JZ>H>*dXp-ZdImXe&vY9-b%@6rB*E z7D=3FHbk5{s4Pr!)t`<&!W6G+AV=uaU2bJr+SafHl+sYc?%j(;b;9lT{YD`YHn5MUF=tYeTA<*QS$X3C$VSER03hNvrd!7Elm*q~P zBmuu20Iv;jj{ugN-@gbhq?zB(Q}G7}mDf#KK{m2r9BL6ppz%UAH*BjRWk>1vNFRF7 z(s!agfa=i*6M&Xl?ViSmVaetre^NloyCMMG41vBhq}XW4ruXg9(CSiSk)A!$9`xJt>C;)axY3UA)BU<}PtoC9@IV@0z%UaDtbo4_C$}H~CEZIsSL=D?h@n zTUujy%>&?9^$>YjI@{6JI}5(9tS;!_GIFyUL#v1qK;**F1kyd|B=SACs}Ki;#gS;X z#QC6Xvk`YNB>OLH0am@=mV7dZk0NUo&hZDAdK9NGbtXpZwH1{BGTXnP0Kcf-B^(mA z@fW{8T+c~NP`&qd#MZxHBuWj6UMhlW1)ONPDEF>PT3oAZA)A!BGH{Jw>lDODH(Euw z(0%CF^6XJ_7<~v3WkSG8s^z}JXr9qjZN6lpm<@q#o!WlGSC0V)^3C$z(EK!{X>gcn z_m?dGW~5w%yA4D)uFjeT2IoiiX6h!4)k*UFn-LY)@Et*b!Gpv)Z2SgdLaHNE<*$Ag zI>zm7Eb@AD|?HGy@!hRSBC-3}6T1g1NLJr=-{)_0`ZtN|n2Dn;Nnf_JbPo zl&l-gYj`WG9befyFo2;JoTgi21@fF%C2bd$Tqf3#=8q6H8y4cFDzbG@L&^$qXfdUA zkQ=4!s(LUuF#u0ejo==IE&&{bcE&Jc*uh~WtP2BpIXHaaGfvmz2~+(K%T-H%E%V{w zi#7;kOV1hR4|L3W`HDSo<^1uSr4ie_n8@>G$4(-4u$ZKZ1|Bkc5ItI!41bqaGzJ%s zDYa;bqF>xCe(j$~qUx4OY!bDJmazbevK<&R*B5? z&F~3bHYErSD|=poRM7+q`@J9;hBD!V#@J zEUtDh#rnt9QTQ^6r_CRY+IO^ ze;IA_4C)GntmoRZ4#+c^_>Ma>YS%IpO5p^#xQ55)6kMe;jB8>`|1%HT^14&?7 z0y*?A=1;9)%_<~gG_0iP!I?5Ht{NXMbZI|@BlqPT?UQQf3i^b3NK~%}mEU;?>`jtg z0F_LJ(9%I&5+LXo$YWTm>=8-`jo8JA-U`K{@s=EM4To$Sj~hF5&g%((k2-By98?`! zg^k(`?0-w-Vno1Zb(PRWPz}=rn3>Ygn$)}re-g_Rp=2RnMZ;%=c=x<(J4F&zz{&E! zWWy`_kW5>LfQ!3-EGrGRVg9u`_S-mPnW+x7m`#r71FFnn4g`xpLMQ-v4kJOHQATYk z*usRj866gUgsC7b)4^nu0GD*10BZduV3^K>ofrTfAyDsta~;A~BynZZW%I;FE=u^tQ|h;M3Q_%% zK5~k#{ieLlb90<*xzyC+Q<&zI-X0+Y)lZ9PT}MrsK`*a0n<>#dgDY}Pb;lmF6KOx6 zp7iipdS>YoSb|UaQL9ZMN`ZU9R0+vl1Q}XcaTX0idRj(lHp9RehKfTpl@kL+6TGq( zir^Y;KNH3?U;(7qYZ5{6FXM=~>?zzQSP9$NJsYU4^Me=w`32n#xVvrZVJ@*HFmN!` z=rye%_?XGzmkzGTY%mkv{~|P;+CYDt9uzR_A9jRC_`s3Dt?PEO>MzakxlX___6_LwZXOyAW+1`Gi-;-{$FTSfhWeE-zogzK&iDswH%nM^W}pLHzs`HlP`j>c>`x{Y|$N*l~0APFq72R(#!Xnxk{b( zFzH;H!s51bNRwtY`9nDTZ3mCFMVO;LmZ7`<^8_wW3!P(Y6YAul6b1N@p?gEA&B*XI zPTc%%3Wp{T)ge()&vi0NXx>spn&Cp2%6NY{ZF47&Bp)0cA z^6kppPUITxXYmcZLn+t|HQFfhMl!UbczUQiIUqvKm-EG(4FJIYy({`4Q_`;N?RNjp zUyl1YX8%`wWGHl`8>p_<4nBovLM9XW|3m3jaucg2R2#b3E!NzTeAGq}g%~ZC2AqdB ziSe{K(U=nD4S@eK>UjdNqYX^qF~oIT`djCoX^1zN8Rj*UD;AU(c}8KR@rE!Z{`; zY3YVnt~t8I8CPVBiyY8PeB(;ioAv3A5n<~=)x#>Zl>)3AWpg?hHP(>We3zIn%z#^h za@1(0$<=P@xmRe?tx`nfwM~56%I+F`i`Z)sAx&tQXY24gF%WxObJ%PcIL%3+EbWm8 zjD>tT*%fhITgRLUr)J|%?pX@C%aekagwMlrc%Aosh1uY1uF(LBI1iba>n5I4x^DGiFa-V66Gz-{*?r zYJO{l=S8G+ABs#<3B!HMj$={0%`qANkncJE^h^+jzmq*ki- z?dsJ8Dx6%q_^fC9$J4ZvN2^Dc4g(LZyh}<8ye(#o36=3_>OZUIwxe|EcfZKRhFS-f z;bU^u8HqtwC?*GT&c+phOVeXT-k<@pZ z)*G;i&j7a}w8M_qBo7pCTi)e92f*{6k7EoW21z1@x1V0?^2QW0# zb>RRYIlgoKBdtq@hDT<$r^s>Aj?^5}l#bfqhiG%SZEp-4t>1q~9$ppiIO2^+*up0m zPqvK8O}ZAo)`@zJYU_z$!7dpIE%0nK-%-zT$nspOkZaQ=d<5|@ifIq{JF{TX#6*=) z30jm&uNe9|>w=N?+j(@@Kcl3ARJWjU`M8K|wV@~EQ80E%^U)JH_9c-tjLJ=Sfsoel zCaxvW=**Z+B%z|Dikn}RDPzM)4tMl2t(?yFnK37w#fvF&>w69JSyndZL;@Xh^gP(ePusD zYC|1m4AA}3W+)%oH;tF|Whj(FScbEC^<8;V=bXD&G;&|(ic#rO+2H+FU!4JmFZ2z1 z*6ie)HY%nY{|R)Eg)s>I2S}|Sra*~{t(oJb6Je?-I~Z}Fk$&v^Wm)CPN5GrW@$ zdses8+afTKNmRfljg!j5vN}dc zeF=W$#EHF@8iniVB}D7_tYt^*?xH0qLK@7?y#1DAKwcp}*$(tmK=i~bttCmMIF@Kg znCFrIHCT@d*ECmc0l0>Wf>P%&*>tp2u%_d8?41KW{%t%$Jve?HM7OhVE{q1ge(=c* zD-kPv9T77>agNI8`5Q*{=|#2r9t+Wd?3wmVW#Pn?h&WwWC$&gxRSVC9RRy(Odf#e()nj>hdgo1$jIIhQ&H4?FG>ykT8>({8#)rwGO2m!A; z?4&$K#g9qUH*Rg7@>_O|uBlLCuFnq+DK1f7uJFc#TLBu!z7^Dn>n^Kh+1hAMw zAv5?|fb&b}B!0r+ky&j_3#C&wZ=`$cjl|T~h#e)y2C0)B$Q-HQD1C@L%mPX<`mXdq zxn8NFyjNDPm_M@)QNAUDy}N&)i#2G%K0ljVu5Y_e6Lw1AC>Z42mGn>nC-%KMQ~wXN zs9*bI$@`Ji-r>x9_p#oZhb;WM)B(dPnp6x}3)ZIF)QNFd$gHEJ`2aCM&c9DrpYmbp z-MLlKC!k;wey4??4+LG-N2Hz;vuwfJAmi2}2b%jhIDVSdD62*1|C0xUKa#cYr{nie z%a_$pZHi>v>D`(85>Y;lJi)K8s5Ukk&xi}JKI(=%)<{wK5tS%?o*1CyMJ zbb7P94#9mx*thD_H0Qi@)`1lY;S^Mmcb%fnVuJ#7cgj_FU0q1BoHFghNW?M1uKG1Z za-#T5_xrum0o*Ebec1TsVR+F>7C(_xfJ9HJXnX4^aR1`U`-f~VBn+NMkiiqr%~=av z`?Y7UJbXMXLOr)}iBaQqnxCei3WM}eo&Rv+)O5hOnao(~;E}WF3J_w6`?2 zGo)pp_LbASK14!eqfD=@#nK&nge*FM!f2h+-FU?As=i{1e#2e#@#lrrf=7BX7}43l zL2+4<-9FX-lr`?#(m|3XE*mLmoE@bANYf0mMv)qU^1}8<8;FCRQVA>+p$EyssCJvl zcVYS)1G22W5AAnLUoR6(;-_iF;f>?sW>~gq`E4O;Y0rwh$hgT&Zf%d|ATgrkj{mhF z7ThBQ776g)WS#@Y5y(MxRj&yps{>xsD$~NeUC5g{C}fv}sdLcD5zH6IeOg%&Et(^P zfqnj1f*qL*y%Qh5PeRz0^ZPT9DTu0T5zv3|(N{LAnpW;Vb5btN%MO+I6nfjZek?70 zGU64NhNJ4Txx~x2rqB1p9v((7t-Tey{-8Xajc5>QDD;vFwbXu>!%c1V$uDrD4g~?u z%F4&m=y7#=VW=^7u5*DksW_1W6a0Efj{&WP>LJ(Yg({jqBBf8;HpfvbhEvZFPs({MdX()@daDQ%2+w_c@k_;=XHdQgkOne9#g2uNiW>{qs>rd zfBOzk8j}EP27q3~*yV_A{k-DDc3Qzq6)B!aPA&eqc+|svOSB#IYbHpT(z3D;ztCtK zm>xL%PWrR!!^8%BA8tw7{pM{)+StR$C~7Yrk%z>TD@^W(Ep z9l6A6keS2@_~?E3b-UlGxc9MA04+|@7~(*B6AMaJi@tdcaX|~@Lprf=o@BjTajf*R z-|9mQiKOf*ZcRb<)g(ztd7cHf;C8Gv=8!xHbpJ>suOUvri9LMB)jeyMbakfzLI@fl z+$P%WF2xWfK-tV68&cFD5n-<(Xlk!Xr@}gJK@=CuMDD!@W?5av)gZxfLO9KN~!Y2 z4~L?gj>ft{()8kIt6yRT?*k4CX=?UI2U-7Pqch|Je#QebQV64dGxgf(kmr5uOS-{VF(5||41htxv-Aw-eZc5 z&2MlDdu`adxtxD{D?BIjKna}ckM$Ds^Fg0n)3E*a!Ttr%#J7G8${k3Ryi|K=V@?XM zV67nSWz(jVSaeU`JyT(_J)>G-=j6p3L?;0hX*KCnLP|%eTye(fjbL*xo-R^6c_PT6 z>Y-Y|N!NJ@lFM{0&J82+U6>sOU0rEh#-K*}JTxi(u65?_r(szR(6~49F#xZMUo~z; zUyLoJv{1G$z)a^BtK`;hLqy56o$>cnmhxRUzx2kr{^H- zhEL!U`o$~s-_PV}WfK6qSW5}JnnsmN3K2;sGE#-rX{V{jaj%NVHysmTo&MVu6sgxO zPkTr?l<`BXDKL57puwLl@N|8^fRFQ1xkZfwHh4+is#=hagtHtwl5#m(mE5FYg^#EEAJ z#!7ubHB1>070+W`OLiV7G%2Yz`se$V172LgVUQdRd{#6JwU9(>G?ZFm7keL9?X%HR zAfLsqRXbADP|R6mJ`*>Pm&>~iY;1SiMdj#3XDah}UvId?07YLz(vl_)CFE{nhrU-NpSRqNs8VK} z>cG1**eWMkeui`LD={{QXWHy6SnvKmBIJcw zB|ZRVAtu{xy3WN(`}??x^tdl7%xG+WB3#~Ib1drZeN^+FpPsUr`(i8;LOiXg5@XUU zyVB@J5z)7hc$S6S6334UwbS6g3uVzk*uhtIQd-ss5qv)W!GS3?@#95579fj(BVEa{ z0X@qpG%=Az1O_P=-A8o1?o#l<@Dar!GY_V<3YFfm}5p zg_Pak+Z6i0Su5WS8CTIu-R$p!)s*&FZ}IHm`$Bt48bq;W+TPU<+O({+0yO>Mtup@A zYbzG=uqaV=_$%2>k%!m~Vy!SYuZj^PAqIsGxV6ve6DaZA`w`fU0xbPz1K8cA zdV~vyytR_Mwy=*Ic$;92!&F|{sLj>hig(Sb|K%~}U}$XUOKTEkWgz*{Kf1y3jX122 z?hk?k@?FMj2r`FD_2_UdE9BtsT4NX*wd;2P_!~l@x>Uyv|I!vtY~J?|fGly_d@sZG z6z(6f^dpqN+$cFfyR3V@P{|aPZM_!;;5rbL&Y5uJ1$k6p*9MBvtJGuMu#xX3gIocA z5{5b@ep(co3HY66BL2hh!bdqa$m?O;N)17%riI05y|7)vn{cldySS9j9*M4u_5qc4 z-b@bcQu=xgt5jBttZr{QL3?ghq5Usf+2dM?YViw=-8t+vj_QMPAE29$IEsTI3h70c ziTm(=SWazBn2#cyOT-1oV3nRqIq_$CbQKrbE)3x-)nO|7V{_yyKNHfHYypP_5IFN8 zzefWXhK#q|Q22yRu$0$aD;DFxpx7>6=TUG5g57wy4rpqIYT|wNPO}7?5fguejO`_y z@)dk#CaY@@;e$RVGE$+8APZv3t!!E)P8lv%H~M?v&PUFPL4@G=Y~0A74W0VOIsC6q zP)IkYpF*Y$y!kb3y~xG#zeW8Y@(s>(9xd;h6o%_f&TAF1RI3RSp5zw0dDjhx1|9qb zQGB@eQ%I;_>LNdvDBLQ>ExUJPcM{RTBq8pV=pgxTL9S!CQf!w ziSe6J#4>ER@ih?M-+91wvebaSTve(|oLk>zAkw%b5QWZu+WYM`^EV1|;3eKsl3HXi z=IfjGwXHuiDuu77&B<51Sl~R9F10%a;H1t)tCG0Gq_A??7n&Fb-o0G!?sE^Tmd`~Q zIu?s*r-f)eifPJSDcr`MN|6|9*+ZMfy5m|;(NX?{d7SQ&7jW@tQRx!SaIqTMM=9k8g$c(F3@ z11S>O+wgr>VB-b(#_~;IGqTYReTw*oy>A5*DQ3$yRQqc`!K-aciJqlqdwWNyE)8>{ z`Z7qJO2NhCU5ai&&^!46pSX!lZJ)2QN-8EN9yZ0Vqhh^L!L1`9LJDX-ymr{Vy$%N0 z4B9g4QL8702raD|x15+^Lmta9#x4D(j98LXGc?&2FeppefD`1;X(chb+m!_2brs3! z`95f-IW^f3G2BmyE>F-eo3soyws>so1#cRXi3Ch}tblso%%_zvz3I229MVnKn36Or zKezYH=WGW~yZq*u3|6IbNY~*wYk#g)a~Wso7(_E^?Zw!?sKILq-eV6i`LHx|b6F@w z#+O8)=OnM~5z>4mvsl>>(ZC8--(FkN6+Dm#uK-=U8(AN>X6g~4#X`5-UEvTNn$6CK_BLe7DpM-Ci<1xk+r~I!`DEoHYAssq+?r?l zKtCg0RJgyzg+YX&qdg!xP!UIAG3N;gUX&rwWN6>$f{i|ARMO0dgHVZ7t6uDBM%Kz|b*W z{+V9bn})$*eTh~9PxX0CENHV^nLR#dujISL zpKv8fCQXHpf;5i>=Nx$)(#nP+E*~#$6wMpb`l$6}?${)5FMm$%z-fBbaUv+otCcal zFjFV0G~yQX69>n9H9*9+ZE(X|R@zaF0oShStLO7lJ2$Mk!k) zeP5)iuz8~(Tr8ZY=lDO5pjKH6r{f~1q@a;GH4u_)XPr6SNVt@OjjH~rhv}hM?Mp}! zp5pqu6CaNt*a`O9Ip;;09nO*K;@L4=TyPlRh^Bfvay^g>`uk$n|5{IYK`5s|x_U!X zy*I#6aajxtQ+$6$Nt$l8bx%p75l(Bdx z)ay9mz(%jL!>#))YcM{I784oIcV^K~vDdh9)%n7?;^k_3Man3AgS^i^H+S_+j{t6b z%z6j%C42{?O#2k5HlhBZFQOJ!;YTNv#|_3^Yy2BaX(n) z$wLwHb^-ZG0r(8Ebv^?XC9_~vW!hLjj_a;J$Jj(Vw8Xxk^+&0O7Tfjz@X}0}fYjvLb+FnAQ6?E^vIr;h+c8AL z>RiAbi`>g>A1SAdY(=y6)A<@Yr~tKtxRC!v|9%wZ59(HAkP}{-*1kJRdd~Orl~!V- zn=~k}x>S%?e!zR+VFt%cY&D=$fIeJB7xqa#%Zdsn9PS1?!)WPbVwOL<1Py6qbTN)A z*rD_zi$bWb4*34l!f?tI8AcEMS_{(cFEuO#{*b>ojZ@kzEE3HI!nL5TQMH&PzwiQ1 z8U1UtI?n|P*XVu|p18ryfr#YvE+AsR?7VW}dG~{7pC@;rqzOj#%C`EVZXQ$QrKG&M z!2bG-%1@B@<8B`x_tPi`)d?OKYt*Ar+w@Oj&g7z4nC2AL?jP|incPcPe?n{!$|vQr z?@DBX!DkI>npU9?VCJvzq)P_Yq3n0a;dk!f%h(=X1DD=uo(vL0D9?>j@vmod**F|b zyJm8xTdBP9j+pbBreY0Nv|o}g+MiXs6hcfXfSQkI4@xAqg2*g_^1He8WGb$TE$wUgb$LgOoauG7g^U4wtQgY z;=S}Ne~J}$s#rlD9M?}o>}c&7`rkgrhiJ~pNrW@Dw)(MkdAS3d3$sj5p{p4A;pIwV z)!Jk9@?_WXIVh_|$K*gSlcd8B#9qG-QQTcuxC8os!m3MKE~t!Yk$Yh{ zik#oiEw9%gxvB4vedP{Qs=Ssw8(jMF zG0cihf5YFFlyxkWYEFip3GyNJX3seAhv8o1uX>n5Z}@eMt%TThci%k+NUawUF482(;eE3IPaND$a`9@fzA6$vR=N|4lY8b3qgv>@lM z(_Zm2;B2s4@Da347{&EoX>m4Mtv=9t=EkO!c~#5ipOIB2i;*a*gJ;`*3KQqzSQ2mu{|I^Lh_h43X!5zqHoQ^@Umv%=(I1jwA=kAo~T^-mFs zyFH=x`6|;9D1caz40mI49h{;xhN-Ku{W3gu6nMpvj(;NmTyuCZoAhbN!Yq8E3xrZ8 z%8GfQLNon%o7llKaBx0Lpp{bgM=VyAo-p8xbM3Hh3{-*yCbJRo`8P?BA*g7TZ{i&z zEW4TpH6Od+gngIsm@J*yWyv45C1xo3_CT+2OWpzPXZkLCN5<)iRfEZ8L7h>Mya}dQ zFMkMN(|Ka{+YOkONF`!pjs=M^)N)rGP9=RQJX~0s!ubxs7&7JQzoVz>d!run#%*c) z?JC4~a@e8c6n*3H{QksU9|dHJc&oZ%&!K<~u*Ku&l` zcM;Ri$|zC%*8NirRI_*`lEgY>GOWMgB;k?y;j{$SBY&x6slQVy0sZ_pcc9#s$34}S zl3&`mjBLC2ffIi#SD(V~jJahf8mAJJ`TEwQI*qLMt|OVcGq1E-)@g|FZsz8tj)_2~ zF+{8NewdzQV#@H#RwF%y_8ORdZ;Mkffox8LFVdX69-?#0xgR~eE>~S;@sEQC_+a)% zO|^NQRk*lxBjfbiyvLgw@#S1E0AoZQuBqi_gWOEvwNNOZD}X2d6f}X3(sV3I4ta9YP`De3-KE8*lnR6O~^KRMpS!-A;#%;IPd>Ex+9Mil+V>sU*4<#{CWi`o2i>z>GS?%6>) zb>50xA#!DG@e*LJ{)NdhRHqq6v@CR_RW2#NAXFZQ5#Xr;@$8Bqr9!&@A5rprfi(r#z>!QzvV$Clw}}aCWRb>At%m(8^TBsXAR7zhxkM?h9%#oY&-zs%1i}IBc0L<7 zH-#t!6iqv`z$u~9jPrbUeLx$JZaYy|iK6w~>Al?1OAX87bGJ#wp8T6>i5+#z_qmRJ z={LMMNh@kG2^D@&QOvGZ5X(=x z`GrGPpPEi;05<3oSrj1*^rsUO+|2t(A!sqa?#oDlD-ASo)wDHatb_*Hf+q}ELXg0O zh*vVN<5Dfb_>V#%LnQ9nxak#ORX=+c%?(IXLf{#{O->%+DyScL&b zWn}v-qiQd8z$o-K%qXh_VULf{KKh!PEuML;S{c1`&&xSUU-PswCQ!Cye8MA>NyqaS zx;-;e@50ngojpgKX_+=BCV<*1QBO_!v~P?|zK?kvu~=*}{i#h6Rn6qj8G_n!`P~`4 zZWya6F$bq5#rg{7gGcUai`6nK!E1R8?}`H`WWn%-Lp{>Elh|dWCIEr$lbGVe1R?_5 zBJs&$Q|jX~0(3saob_j(s8qvsJ6zmD<-F&vLg11p_fDEXlheDUF21L5To|_R`$p`e z@4H8hROYS~*D~tibKo zSG%Q*-0U7BM#!3CP&}Ja`(NZwo!Sg0Xxm0o_8t>Vyp*H_%tF7Ew+1!TzQB%Qty8y7 zm8J%l-}qlJoT_M_CI<>iAW-!(l{PtV>!l&_r2s0oGiqo>;~@z6GGJao)j2xEL#H?n zbpzgkjCLt+a!RK_naA)`*ggW2)|>2CFA4^Qm7Q(Fl$1k=94AQ& z-&`jF91t*@z6TEH$i}F5OeU^Eh2Eyy`H(6;5B$%6%_5z~b3>!PPXLW)-6!91m#9iT zkIRd%?{TeT>LO>l-x$gS5&BF*r%SPG?`>|{I9AHUl%lO>De}vY#P+5BjptbuMkU^E z8MCgG!4jJw<4|Ioh>&(pJ!oojs%#NS(1&2(6gFhcm!?u9O)M1m@#~V{r%SAzyi_?) z2&KZ5t|~@e*Gksg-P57EoCchE9y7+PnH4ub;rJMTrGb=|#?Ip!S#LBBnC}XohPp(* z9?L_uuo6fbMlZDx>$c{7Hy?%+rzZcDqa~rW^X?@crxU-bN@KiI!}03qdclp1wLc^e zo@{sKbe&3HdB$5;XA`%@IWDpqMA4r%b`$fR$1hViw5>uDg9!YI6s;t*UL4ymYH(a9 z%LOmuu56_S0YzowNGu8b547I z)yFL4KIxwG?8cvPz;8|+)gpf5ondeqLO`QG!#|3GIf~ZXrvfF8373- zAo1`)nD&*CbwvjpRh_`HAZ4=dBy1ENaU2&6Fk7h!{>8uND5J{&TLh zT>9$oYAET`1+TqeI~oNkPKnVWcNTrdoO+(d8tI^)Uu93bt%9k{AOgNl?DLGqEPci8 zXNz&|mtr8^R|pa^GRg(lt1i3qdme_1pP7mJ9W7j^tP*PSR06Jx2g#~?2)GV?*ayiH z!p0<<{%_@+dVw>cj7W|u-Q*^6Y$9xm!|OwG_et+VQ>_%5BOz2vj`DPQj2^p1QyDow zD=GqqH0f8t6Oq7wef#KSO#sLam#3bbZkhq<9=WpZH66$9kD}JHhmmgIgZiJcNhrRy zqPj) z53py|)0=RG*vX!$5bzPf)=XOh*OyUr_NA6>E^aL14+9YFp=pEY28t*q4=pJK2fKDG z{AUkM!-%Ja%`TShiL&r{sDvXgqdWX9Td4R(A;B9{#JDB`$z20PBU^u->(`@_PDiKo zHeGG`lV7zV`x!5Umg+@5O@xxFZtXKDKbo*%k^Xi&g6iHjJq7Y>?}84hT8IC<1at0| z3eOqlG*D0d@jXi`WEJY*TPvAp5<|G}_nsAlxHYlXb2DLOQ5ZT;T00;$NtVoV3Rjw8%{`hZ z1O5&X5OurU$^iwQ`o9-N(aAt@mZ~0!TbJ#)z8)RW#{nd6XT;NY2@DM=+oVibHp8cy zaV!jPL|oGoT5~OUcCU>-g+&jxrUKkS;2Syz`$&)ssuS8cs9lLLaswK^@SBUD`)HZ~ z9mEO`8eNXMJ?vfSF#r}bbqCD9p$)AN;DE^lCkB@u0((7bNpa#pfr~Kp(y`cwV4;&K zK_B=Ok`Ugo;XHxl??&?G7zn-oVV{-4)06-}i7$PL@qz?sxos`wSN6}Iw9oV%ZVPDI zjo0b(Qw!mqS0OSbO5>r9o!lvWMKyH8excqkz$`R2pEsYhk-Eqrbwk-QHPCg2j{cJU znrs#TWRlR0OF}f^kUW6-G)ri2RrI0(yOn#-3+Zl#Zyt(o@6pO*?%Z_esBI+EPs78E z^4WK_ocDTK-o~J)Iu4JR5d4g;Zd-~YUTZmClsIRk%Y(oJ5r}BOM--jcXDP#x>oNfS za62od04A!j@d<&_o?~DFXw>9j-rU$5brMcvwZMN#xi50pnv(rPsM|zq?Y{au6ZsyyLu)7AyKo_Wd zJDP1E*EiTjlxIoY=FHVivaY_XQc5>^sUUvOu~Jy(E3j4tmQXfFFzjhf;ll*narc`RdR%M_H6QR3*HmDqBDBy{W5mb*JVr zd=_IcWBPKzhn?)XNx^_K>g$=_6)C&Ya|_>*&XiRe4>JA=T!GjSn}f8PPTzG1rw~I{ z#zEhA@k7jm#gc+okDrCV44?$#(QD9F7xJJMEfN0IkW=06Dm+PhBiGwrONF@8<;?kW zW@2ld=Hn~PLzfDOD_X5afxAx!G}W#+xm4f&<%~X^5Phx+-*6s5 zz)Ud!fzy11Eejr-VIG;(-kMY9VwcIo<#&#Z+6XR2=s5}lsmJ7memC133xb$@*=xFA zrF7{Y^bVeH?YwGRGEU&Mt8sZJXP}oj$nA0$S2CvgS;xNa#$63v3ODYySJ$pGIU(`m zb0(hRw*YOJMJjtq`_Vxw2*-5V*>^6e5!d^#Usb6gm9QI`MKkb?-D+48G&YOBJKXt z+|qf)?<>VXk^ruRImcf~ptD4aMEIzH5I2dOJRnq?08c{ZLONXOVQhF_l|3qJzN6+m zuy9hpjTy7Ee*~qs%mET?<(x^<4D3t zW)fan698TKlgb^1gfBGP2qgA(7Mu)Pl=aqwghC%?>80sPBmOoy*zavJ{A%UabDj0f$ttLOZygo7ZPgEK!L|4itS+($OEHpsX+v^(o{Z2W@p@N zgpZNkqQUGw;t*M-_1gBw>a|gRd0vlOovMaAg0&0AUVINeY)7*m;h^&mwoU&-m=Z1# zRQ|i}tj6=^#G=ZptJA?d{STg^6jBAW8_1q5wWk&j5ra~%Iqk32xjHNcF|7Sp;*(-r zlvE30i@#xx(sP;>T73ZR-yR@P_fe~MR3v=rZ(I_wmQoOuPn`;_q!`FT-FFRAal*m&{ABql{r(&0| zRQf=jhD0XLU@l#BLZCd$mo2@Ya>1UMH_RdrIO561M^jsVig=U!N*gyJOUb;d92EAk zKm9Gb;>7EUuC+fv`OP7s#6H?U5`Cokv9Fuz&-6bbrh9Oee5E_@=KypmiP0J6Ol0^ z7jZGv14R|&n2_Y#hp;y9zcXM8yz1S=6vYZ(fvwOdWfIoIeaRjo|2ww;{p32#SRoB& zaje7orzszXrUH$BH9JmkT8^!N;&5hT3FZvW? zhElCcA>uE1KkG~>G@tWa*Nbg|7YIH6@8)ye00U#)Zlsr(DSa)`r4;^H#1$OfY9w&O zXyGsH@OKi$9AIVy6VJRo8*y#W`vwS;TuTyh*GTVNL9Lol6cuZKsys0@d;1LBZ`5mjSjvQ1d!l<7P+Y6Q^JkE-vuW2*-1 z5w1G^zFqA>{j*Ot>pft;VVge;W)?qO7Wuw=r9(ElE%tm$R9oXE#8Xcrd*@`32BZy% zzJ}rkT$d*+B-(HxeZva__<7m$#QoU#Q*@Stt)>A@a{cwvWK_BE{o9u9oLWe$kT_B$ z787x4u2ePmY>C0k!UYS-)Kvzd_eofz#e!(7Zu|%WZ*bRB&o+92EMoa)GXcDZtw~mP zdd`@-L8|a=8qxaS3$X4c@M|irH3rUTCCz}eLMKBJWU9XYAAww~g9@YtTii)*4f%3M z9}OyEd=$IQJ!Ywd!8_E6shF4V&=?}cLg?T4>p*l^xKTt<%{@f zOK0KlTsa6Rb0VVQ3z^LCGK6bqD+^X;>`|kO zWS&Vj;FeB)AX0KrK<#OV0Q?hDeXdCWMmr}_1=Rf=G<5SNB7S4F>N0zodfM z$3dN?l_&<$4G&)0leP3efYqLX8B{sAEnM757KwI?r&UYiWkR-fp{d_>x88;VQrpbQ z+u?h=qL15rlTpkc?4UzY0c!Iqyb3oWyEgZH>iV>-TMX3}3wwAS3}vIYNiQm8VD+QktZ>U$#C;x$XY`F4VxXE=7SRL4Jp|MWppLP2dkh(T~3Q85sa1`mN#l zLF#)_&9bVSfpe;d*nxppNgGeaqS2+o^W6Z!u|DcMY^g^$XAZ-a*6{=s3_vqGdf0!m z&_qf*3fPf%^=PyaB!360aa`f~9UTe^kBUX1v7be z1?(bQ#`?9U#UzlwyIdr*QO+*_YyL)rm@BGU1u6_~&`}&Ao5V=O>V2ooA6K&k`C%cv z)J70qL}5i__mSZ6lRkoiewm5!u4asEiH-nCD(fb?kP7?84J~8uY#&jpmwrU2p;BDc zlaHsgNt=caqp`6zf(a+e@xpM;YWb~{Mu%N4HJuqY zy-k5V_+A$Zgk@hL9l40^S)BqBP~fxGSMb?p_vjscLUPcjpCOJ)xfiD8RyiwUYhFs@ zxd=!0RjdqC&usM>lb4ip6JOG#6fOp3gAY8QtK(|NaGhPbKSWbqKu z+yQyxwUy_j7e&d`^NUfIGu6&y(yAxHCU29BA0nC7R>qpJ+`?*Ogd}e=ua&DO!fknqGhpLlx%dBv;Bnq8APbG5ZUcA*a~@Qlm}AK|dM$bmDFWj`WW<3*6kj(&~Cv5Zq!juejkESoE$jXv&6!4FnbTJ zj}vOKO3rq?*B$JH@Ez!zN`?H5g*J5&6HJfjqz}4rgjh>V`-Xck}<|W5}*qmye!eWvV3$fP z)KMAOygQpFZB$T=gS9ksI6QS{eA`Aa{Y5KErXX1k@_y(bjug(&Se8}XDtXrq2h3`_ zL~9_+`4EKDjc%9zVWDdQdy*3kYSM+xCKBs)q^Ly&HSb7)XJ}mDdXoz;550xE3xTE^ zq;EeubqspMnPV=b=(GS1zv~mVV|7M?{O&C)s_fv9AFJ6TFSn|mgnp49$gPHoPS&_>J&bTXA?B>kjGB5YDQ zzmLc?UvBA@!xEt&>P+0-(&3}U5ny_?GFxlMcXTPS43lDe>U1g`tm?raa&f~@!%lk6(Q&*tL5J7!Q=uzkJM zg8}v_F6soj_Hxo5(t1VC#5^W*+QXJG+>3L^c+e7(vh@_G8KQSCmFFaG|K4~U3(V;+ zn8@5y7sQnpR7C;liad?->rek zj)@}*7mGoseH*7N=V-xGa&wW!W8}x@Cuq{{K$}*(_XRhfcX%Tvr$9zSI2JN~z#B?XYp^`3|h`N;Q#hGt5bIe_!c1Q3&p=Nf>=@u`?n{776mn zhD*n3nb~{=X>`noB_5QVPy6Z)32%M&nMrx$;i8#SGp*zUSsJUx07~(kJtGc@FkCsw zVkagX-0o>|pD8?s0clyTO_L~xEdH<7Z(j`r6#rKY`(wI@o?#GXZ9*7pcu*7{1695) z0amwG^8K^8-%LzhojAu?VNbh9)3w>Y zCp?-C21JuLcOl2N!We0w{{1sS`+zJ-J1la-{-Xt+L)*D|P9Ys08iaT6#DmIczHXIE4Uc4);^wuR zbgb18I@bE#5P?ZV;0P$Z%af=Bx0w2O1&HXwqLI!jb9gvyev~8=YXm!cT1p-5ZAo=( zk(HwHPR_GHx)E?YNR;i>e#pWu4;*^lHSs0^RrR+U=ye2MXX$Og)@^p&aWBA%`kZaA z_(c590f0A~Op2bD;^B~u2@}ZnY%2~y(lE`SoZ9D<^E)fJb@82l=H8XG7+hEGbha}{ z(|ZMK)&|=FQ4hRBj06h}}&H#=Nu8uip&A#%q;N4Lb1teZU zZh4VsXV(pB6KpgkGB>^rmDbvrnbP|IcMWMT=7D5Y# zoG-ENMH>hF56A6{Yr0>+wVl{yhv53X(jkEiTuI#J8xkyKnp(tC#490W-=pl#48qB! zv+~=h$+kc<8Ke7vVPBMw!=_LCkQte-MsYNFN-iJ|fcNcIFfy(nI=~v?d~8%~WD4<% z?&pEJ;5$kjY^wTX9`q%FjZ{LEk=_XG!k3hwzuh9^9|7YkXGf_Gg^~_PQ50Ls`tSwy z8d^#t&hip7st9R9pfxl%3+#&RP|@?-v}s&f~|}h zuUV)F{ipN>GmtwoL?P z0|=E*I9Ego+adhmsov#aG!Ftx!7c)IMlQz&eN;@7YP6vUoUg{*$n$Lxfp0LYY#Q@h zSNbmQ{KP!8$ur%A2B)Iu0`|7Zk2KOic`^Ln^`LgN-%Rqhdj$WnsKc<^-6)-lflW$P z@mn0l1=<`VX#%bt#>|+oT79PeF&EZg)Ppa7*QJYIyoMGg_wu(0PN^j)#q3bt`BT>M z=nyC3!Is>Lc*Fcpgh{zu>(a1I+qHxdv(EL>nqFTefQ{S7$a!RG_RSJ|7glC+-Z$Nc znjX-EZk|~kQL`G$OUe~;WMdMoSMb>&E?X?%23fXYYlz`~op101mP^_cPpCGo8gl}iZAq4w zPqpNe-uGsN${=B&9r|DZHG85Cc0gIc%L&JYMK>10+?iHt92fu_QRRAZ zlxDyGjf)qq;uQ= zF#tKm*#~RoGB2vi;@T^d{x7hTMSb;ov?2*K?Y?Qx_LM2&(UzwVSNaXALF_bzkGcJ<>0X|i#SU+Ne^!Tom zrP`7L&aEXDrMV#sm?GZ}Z=1~Yh1+|Wy`g8J=j(&+O9cgS_@5X6>)gTXG>i46dOCp7 zS+PYc)1#_i>^lWg9H~W}5>kvcSMjwGJVM{2pW9+tqYM2o8=1mja<0s5ZIy${T)Kw5 z3JnI&wTK?nYm&(5Z!j7#=33g%4wSj-nl%TW4HZzh4=bRV+ zxTxPwXR27{r}Yg#t%$yY+%`icTpK*3)+mw8GF4SuH%Y2khd7XcYu>g9dL7RqYlbci zY?0;lOYQz_*r>Sv@;+QL&<&X%E#|{kfh%o+szi_qW1_fzA!TK#(UVXy=92S-6%8M! zkF0_Erqhae-9HYgTLo7otb(qo@3krcJVnv_0GAzr0hOcu8 zNDvf-H;ockn}+}xRUG!nRsI7Kv*QHElvC*}6kqVgAq3O5KP{>|-U4eyU|G$siH+?oG62E0lb2MXb zATC4!e2Vw-2foEx?@a9IXX-wR5CvGl0fNH6Oztvs)`f7mp7b@sv0DPGu8!HqlCNyn zHRq+3bb!+jz1YJ~`;k+!axYGKLBSSA!%YV5HnfetnQ*N2NfO|*GkGXgHQ#4 zJMu2OpG+M&${iyG8_7NI$*vTXs98;RP!ROz!zRFRnNW6*u@-Zj|1WNg*H_Sz>RN8Z z)TuW{778=D20G0+Ym<7pTfD0*$tu)IiP+b+01Kdo;rYDnk~CHph*vy>#PE@O%hpqtMbg(h@JEmn zuHkC6Eog1-_Ce`q*mIYl>x!3I`m6u)ZH%~R1oiJI()PR%LM@Pay|_m8&F`k2e5f|a zCn@8pV-@QOGKk@~9Euo+O2aw(#0#S&^l>}n)XI!J|MEu4?FuSX?RiKj>9V<7>OY;N z7ujq!a;Fm}kN&V$*$W0!ylh$K#NDab+&#--zLQSB=)VRZC0<3RR;##^31e9|Oa&A`TyX%f>bJy0Q&;);gpQoDvk2Vj@u1=j%;bV^#!osOIMyZxvP{cn4Vv;Tgz#G?}5u!{y}9kP>#zqxi5 z>!dJ`D)$I-mHe@@_1y+hMh6)3A$UqU=KU(mm8}DlI3Py8Ni6s#&eIp4}>~cZcGbNThx&Owod8Rp`aY#p=HjB%+m#BeXHmIFqFTB@5d0 z$yz9t#j!>LJF-6`!r8b)0_t3o!!Hu-PYYcZ(&kS*qU;3c$8}~_jqLbU$^E7=&e?7@<&%#(dSP1c>g__g_PNee*O@Ad`VEOag zVoQpi8E8P@hIiGBX_OF_h5x?5sy{ymaW)6(A3Cu@<$~aqK|+Ej=|}e8i;m{at+VIK zQG9ViaJ2@XT5VX97D;hD*{FI=5S#gxZkQwcL~x`NC*&Ib*7@^&v*jf%Cji|D6sEpTxPad!|Rf(SWIIWomTvQO90I>Vn?2!_gBa6k_V#`1T08IC`&1K8R(0A_K&&^*DvO0hUjoB z14%s}T2;j8mbIR;WSBE8(+;B5{g6f={A0*`e1|SqxF|+NP+^b6 zX+WyIE~J+NZ;Qp4`2PvE#sF;^X$Rz@9+M>rj{jYQDhkyN*Xkh6b-1X{K?gJ zg5Dvk5)0aJI-f@0F`Q$*oB2h<9+mJ4aHr)acelX8^v!Qhg(8uvP!K%X?O_ejVT`U? zUgQ%-NS3pHJsguVD?*$Vp>gd+*Ei>Uz;Za`-KtP4z;#Q7v3<_7&L_?nZ&&sTA7A_t zK8Od#e;rR^4#{(Hwn>v6U4r{P2aV)Lz=DKpjNj>gUP9{*&Y*KW+A5!BnmnsVUi>#0 zdsMWFAVT>2wsWWKyx5gj?U)apj`df#g`nm})|xW>=a1y?H`FOw(7Y0MIJYR}60p1H z2;m29ym{W=@-*?4tjN6T|HyG7tk!~%;Iora+1Zn|%_k;wj-RYLB$p&OExndDk7c65 zkjaL$5lrnX{;o=+KFTBvB5Jc;ho{eg;$#9+32j}j*{T|{5|Kxyv;c21v4X2yZ8Z=g zV&`@1pb-*L%YYQd6^m^9>uywCS;~d>_rS*prCsi`=*H9l$LuHBH{Ue6C=QV(%+fx zDmvf0Pw2f5<4&lA^Sy~$UEa&Q_5%w}xghGMu*QRb-QaqnWK+_9fy4g_q{{Zpu;=U( zTKfKT8x@KIUZ3D{$AY{Dprxjyza!i(su8yCVpHNee5g?TI{gi$XYK?P1&|p2323ZF>2O8?_({ zY-M0yAF~9qh#!qLVmb!96Zy&LE6TG7=iP)q}k>x`{4ko6iupZ58zJNWB?%1;Xc-rvfra+`!$ zqb>%#PscK4>!;f!a=an)+c*)~x<-58ibWuV|Plh8l%Pk&RhVFrqw#r&GQp+(f41N#Z;s z9OU6I&lDZfC+wqNsDBs5nYp|VPb)FSPY$s+p0M8q4OrGZ4z&t>$}=^L&jrPV?9=JB za%`gX?Z5MRxH)uZx~ZUo9YwkKVy92tsEtOK?Ur#0K%OKVlE{dE~Za7g0$ zMnp$7wDbxWJY61QPXh(WZKf_C;Y)=Q;@#rm?cHLxKjfz~3_(v}3c~euT+4VP{z-&8 zly*YVL$v;qd!#)ZPsGE^nbz6GK9Q8++D~ZV@4k;>rm}Gd5m`Ej9Lm&NY}O9CdG;xD zQn{6GFt!YS`5q%^T7gnw`U;Qe)rr4CqnSj^KT=)?Qh2z$e&dh~C7R1b%8?Bzp z5Z4Q7(`$vS2z*jyKy1hcNx)9;9$X>e{^A|?#2CN^EgCg|G+f%rL3lUrW|(+39Sa*1 zA)7IHd2RQc-G_l@pXtN6SCdtDusSprDqfH87vV$Az;Z}BYh%DjzKx&-s-PZEn{7aQIoFZ$(85hCS=@0zbBU;*7?Uq~^0c(E{E-lt zcaq2|oh@zg#~4jRFdqLCww|5%VP3d0(3n?buE`M_0&;iAnNxZhXxds$Cn8d>wJn;J zD3>v=bM;1yqJH8p3ZC1)KOF#`L4RQASHznP693B>O?A~_y>*4yz1g=KeFLJ27WqtK z(}zejQSFyTPHyyMCI6HeiYvi%UMeNjDZT@%S772=nd}Vh(J_xu!DrI^3-L%jmdQhz z;nZPgge$G0Q&ywL0ZShh7?RVp4vfEC;c!apBf=Bd1*&Ap$3g43k(Q+d4~x9^LU zsT+~R;pP>m`yT7@tWLCOL1V;ym5ic2pXATf;IA$GX#O!dL*2${>9z>CTKgHoFCw8o zT;jD|Ch!;B7JgmpD^@5qE7xX2rov(J*VEs*FzsDhj~NH!k9&mqpS7mCx^6ie#O2veJL9)g-DLvtDDxP@&vA z*u(ptD1>R30ol0J9Q*;LLqq*4$0fLj^Fz;<#iA5ufNPo8d-T9R8hCeY4L=zTz_9;` z+oaYhO}4f wNtMFg1$zY(qD`a#03(l9jAq-V-2ef^nhKA%D!%%0C$Yq5`vL#}000D8TIoe7Z~y=R literal 0 HcmV?d00001 diff --git a/kernel/tools/cpupowertools/files/patches/mageia/CVE-2019-12379.patch b/kernel/tools/cpupowertools/files/patches/mageia/CVE-2019-12379.patch new file mode 100644 index 00000000..04d16049 --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/mageia/CVE-2019-12379.patch @@ -0,0 +1,37 @@ +From 84ecc2f6eb1cb12e6d44818f94fa49b50f06e6ac Mon Sep 17 00:00:00 2001 +From: Gen Zhang +Date: Thu, 23 May 2019 08:34:52 +0800 +Subject: consolemap: Fix a memory leaking bug in drivers/tty/vt/consolemap.c + +In function con_insert_unipair(), when allocation for p2 and p1[n] +fails, ENOMEM is returned, but previously allocated p1 is not freed, +remains as leaking memory. Thus we should free p1 as well when this +allocation fails. + +Signed-off-by: Gen Zhang +Reviewed-by: Kees Cook +Signed-off-by: Greg Kroah-Hartman +--- + drivers/tty/vt/consolemap.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/tty/vt/consolemap.c b/drivers/tty/vt/consolemap.c +index b28aa0d289f8..79fcc96cc7c0 100644 +--- a/drivers/tty/vt/consolemap.c ++++ b/drivers/tty/vt/consolemap.c +@@ -489,7 +489,11 @@ con_insert_unipair(struct uni_pagedir *p, u_short unicode, u_short fontpos) + p2 = p1[n = (unicode >> 6) & 0x1f]; + if (!p2) { + p2 = p1[n] = kmalloc_array(64, sizeof(u16), GFP_KERNEL); +- if (!p2) return -ENOMEM; ++ if (!p2) { ++ kfree(p1); ++ p->uni_pgdir[n] = NULL; ++ return -ENOMEM; ++ } + memset(p2, 0xff, 64*sizeof(u16)); /* No glyphs for the characters (yet) */ + } + +-- +cgit 1.2-0.3.lf.el7 + diff --git a/kernel/tools/cpupowertools/files/patches/mageia/PCI-Add-function-1-DMA-alias-quirk-for-Highpoint-RocketRAID-644L.patch b/kernel/tools/cpupowertools/files/patches/mageia/PCI-Add-function-1-DMA-alias-quirk-for-Highpoint-RocketRAID-644L.patch new file mode 100644 index 00000000..b3c56fe0 --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/mageia/PCI-Add-function-1-DMA-alias-quirk-for-Highpoint-RocketRAID-644L.patch @@ -0,0 +1,34 @@ +From: Hans de Goede +Subject: [PATCH 2/2] PCI: Add function 1 DMA alias quirk for Highpoint RocketRAID 644L +Date: Fri, 2 Mar 2018 11:36:33 +0100 + +The Highpoint RocketRAID 644L uses a Marvel 88SE9235 controller, as with +other Marvel controllers this needs a function 1 DMA alias quirk. + +Note the RocketRAID 642L uses the same Marvel 88SE9235 controller and +already is listed with a function 1 DMA alias quirk. + +Cc: stable@vger.kernel.org +BugLink: https://bugzilla.redhat.com/show_bug.cgi?id=1534106 +Signed-off-by: Hans de Goede +--- + drivers/pci/quirks.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c +index 8b14bd326d4a..46d47bd6ca1f 100644 +--- a/drivers/pci/quirks.c ++++ b/drivers/pci/quirks.c +@@ -3908,6 +3908,8 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x9230, + quirk_dma_func1_alias); + DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TTI, 0x0642, + quirk_dma_func1_alias); ++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TTI, 0x0645, ++ quirk_dma_func1_alias); + /* https://bugs.gentoo.org/show_bug.cgi?id=497630 */ + DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_JMICRON, + PCI_DEVICE_ID_JMICRON_JMB388_ESD, +-- +2.14.3 + + diff --git a/kernel/tools/cpupowertools/files/patches/mageia/arch-ARM-omap2-hide-omap3_save_secure_ram-on-non-OMAP3-bu.patch b/kernel/tools/cpupowertools/files/patches/mageia/arch-ARM-omap2-hide-omap3_save_secure_ram-on-non-OMAP3-bu.patch new file mode 100644 index 00000000..e2783603 --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/mageia/arch-ARM-omap2-hide-omap3_save_secure_ram-on-non-OMAP3-bu.patch @@ -0,0 +1,46 @@ +From 863204cfdae98626a92535ac928ad79f4d6b74ff Mon Sep 17 00:00:00 2001 +From: Arnd Bergmann +Date: Wed, 6 Dec 2017 14:17:17 +0100 +Subject: [PATCH] ARM: omap2: hide omap3_save_secure_ram on non-OMAP3 builds + +In configurations without CONFIG_OMAP3 but with secure RAM support, +we now run into a link failure: + +arch/arm/mach-omap2/omap-secure.o: In function `omap3_save_secure_ram': +omap-secure.c:(.text+0x130): undefined reference to `save_secure_ram_context' + +The omap3_save_secure_ram() function is only called from the OMAP34xx +power management code, so we can simply hide that function in the +appropriate #ifdef. + +Fixes: d09220a887f7 ("ARM: OMAP2+: Fix SRAM virt to phys translation for save_secure_ram_context") +Acked-by: Tony Lindgren +Tested-by: Dan Murphy +Signed-off-by: Arnd Bergmann +--- + arch/arm/mach-omap2/omap-secure.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/arch/arm/mach-omap2/omap-secure.c b/arch/arm/mach-omap2/omap-secure.c +index 9ff92050053c..fa7f308c9027 100644 +--- a/arch/arm/mach-omap2/omap-secure.c ++++ b/arch/arm/mach-omap2/omap-secure.c +@@ -73,6 +73,7 @@ phys_addr_t omap_secure_ram_mempool_base(void) + return omap_secure_memblock_base; + } + ++#if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM) + u32 omap3_save_secure_ram(void __iomem *addr, int size) + { + u32 ret; +@@ -91,6 +92,7 @@ u32 omap3_save_secure_ram(void __iomem *addr, int size) + + return ret; + } ++#endif + + /** + * rx51_secure_dispatcher: Routine to dispatch secure PPA API calls +-- +2.16.2 + diff --git a/kernel/tools/cpupowertools/files/patches/mageia/ata-ahci-Add-PCI-id-for-the-Highpoint-Rocketraid-644L-card.patch b/kernel/tools/cpupowertools/files/patches/mageia/ata-ahci-Add-PCI-id-for-the-Highpoint-Rocketraid-644L-card.patch new file mode 100644 index 00000000..cf6a1a2c --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/mageia/ata-ahci-Add-PCI-id-for-the-Highpoint-Rocketraid-644L-card.patch @@ -0,0 +1,37 @@ +From: Hans de Goede +Subject: [PATCH 1/2] ahci: Add PCI-id for the Highpoint Rocketraid 644L card +Date: Fri, 2 Mar 2018 11:36:32 +0100 + +Like the Highpoint Rocketraid 642L and cards using a Marvel 88SE9235 +controller in general, this RAID card also supports AHCI mode and short +of a custom driver, this is the only way to make it work under Linux. + +Note that even though the card is called to 644L, it has a product-id +of 0x0645. + +Cc: stable@vger.kernel.org +BugLink: https://bugzilla.redhat.com/show_bug.cgi?id=1534106 +Signed-off-by: Hans de Goede +--- + drivers/ata/ahci.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c +index 355a95a83a34..1ff17799769d 100644 +--- a/drivers/ata/ahci.c ++++ b/drivers/ata/ahci.c +@@ -550,7 +550,9 @@ static const struct pci_device_id ahci_pci_tbl[] = { + .driver_data = board_ahci_yes_fbs }, + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9230), + .driver_data = board_ahci_yes_fbs }, +- { PCI_DEVICE(PCI_VENDOR_ID_TTI, 0x0642), ++ { PCI_DEVICE(PCI_VENDOR_ID_TTI, 0x0642), /* highpoint rocketraid 642L */ ++ .driver_data = board_ahci_yes_fbs }, ++ { PCI_DEVICE(PCI_VENDOR_ID_TTI, 0x0645), /* highpoint rocketraid 644L */ + .driver_data = board_ahci_yes_fbs }, + + /* Promise */ +-- +2.14.3 + + diff --git a/kernel/tools/cpupowertools/files/patches/mageia/disable-mrproper-in-devel-rpms.patch b/kernel/tools/cpupowertools/files/patches/mageia/disable-mrproper-in-devel-rpms.patch new file mode 100644 index 00000000..150d8e1e --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/mageia/disable-mrproper-in-devel-rpms.patch @@ -0,0 +1,74 @@ + + Makefile | 18 +++++------------- + scripts/kconfig/Makefile | 4 ---- + 2 files changed, 5 insertions(+), 17 deletions(-) + +diff -Nurp linux-5.4.orig/Makefile linux-5.4/Makefile +--- linux-5.4.orig/Makefile 2019-11-30 23:06:49.394199628 +0200 ++++ linux-5.4/Makefile 2019-11-30 23:08:00.927203318 +0200 +@@ -1093,8 +1093,7 @@ include/config/kernel.release: FORCE + # Carefully list dependencies so we do not try to build scripts twice + # in parallel + PHONY += scripts +-scripts: scripts_basic scripts_dtc +- $(Q)$(MAKE) $(build)=$(@) ++scripts: + + # Things we need to do before we recursively start building the kernel + # or the modules are listed in "prepare". +@@ -1112,7 +1111,7 @@ prepare0: archprepare + $(Q)$(MAKE) $(build)=. + + # All the preparing.. +-prepare: prepare0 prepare-objtool ++prepare: + + # Support for using generic headers in asm-generic + asm-generic := -f $(srctree)/scripts/Makefile.asm-generic obj +@@ -1363,15 +1362,8 @@ CLEAN_DIRS += include/ksym + CLEAN_FILES += modules.builtin.modinfo + + # Directories & files removed with 'make mrproper' +-MRPROPER_DIRS += include/config include/generated \ +- arch/$(SRCARCH)/include/generated .tmp_objdiff \ +- debian/ snap/ tar-install/ +-MRPROPER_FILES += .config .config.old .version \ +- Module.symvers \ +- signing_key.pem signing_key.priv signing_key.x509 \ +- x509.genkey extra_certificates signing_key.x509.keyid \ +- signing_key.x509.signer vmlinux-gdb.py \ +- *.spec ++MRPROPER_DIRS += "" ++MRPROPER_FILES += "" + + # Directories & files removed with 'make distclean' + DISTCLEAN_DIRS += +@@ -1394,7 +1386,7 @@ clean: archclean vmlinuxclean + # + mrproper: rm-dirs := $(wildcard $(MRPROPER_DIRS)) + mrproper: rm-files := $(wildcard $(MRPROPER_FILES)) +-mrproper-dirs := $(addprefix _mrproper_,scripts) ++mrproper-dirs := $(addprefix _mrproper_,scripts) + + PHONY += $(mrproper-dirs) mrproper + $(mrproper-dirs): +diff -Nurp linux-5.4.orig/scripts/kconfig/Makefile linux-5.4/scripts/kconfig/Makefile +--- linux-5.4.orig/scripts/kconfig/Makefile 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4/scripts/kconfig/Makefile 2019-11-30 23:07:24.957201462 +0200 +@@ -24,16 +24,12 @@ endif + unexport CONFIG_ + + xconfig: $(obj)/qconf +- $< $(silent) $(Kconfig) + + gconfig: $(obj)/gconf +- $< $(silent) $(Kconfig) + + menuconfig: $(obj)/mconf +- $< $(silent) $(Kconfig) + + config: $(obj)/conf +- $< $(silent) --oldaskconfig $(Kconfig) + + nconfig: $(obj)/nconf + $< $(silent) $(Kconfig) diff --git a/kernel/tools/cpupowertools/files/patches/mageia/fs-aufs-4.14.patch b/kernel/tools/cpupowertools/files/patches/mageia/fs-aufs-4.14.patch index b558c0aa..8672929f 100644 --- a/kernel/tools/cpupowertools/files/patches/mageia/fs-aufs-4.14.patch +++ b/kernel/tools/cpupowertools/files/patches/mageia/fs-aufs-4.14.patch @@ -90,7 +90,7 @@ fs/aufs/wkq.c | 378 ++++ fs/aufs/wkq.h | 81 + fs/aufs/xattr.c | 343 ++++ - fs/aufs/xino.c | 1406 +++++++++++++++ + fs/aufs/xino.c | 1457 +++++++++++++++ fs/dcache.c | 2 +- fs/fcntl.c | 4 +- fs/inode.c | 2 +- @@ -117,7 +117,7 @@ mm/mmap.c | 33 +- mm/nommu.c | 10 +- mm/prfile.c | 86 + - 119 files changed, 35967 insertions(+), 31 deletions(-) + 119 files changed, 36018 insertions(+), 31 deletions(-) diff --git a/Documentation/ABI/testing/debugfs-aufs b/Documentation/ABI/testing/debugfs-aufs new file mode 100644 @@ -34595,10 +34595,10 @@ index 000000000000..dbe452868cd5 +} diff --git a/fs/aufs/xino.c b/fs/aufs/xino.c new file mode 100644 -index 000000000000..74aecb7193ab +index 000000000000..eea2c34cabf4 --- /dev/null +++ b/fs/aufs/xino.c -@@ -0,0 +1,1406 @@ +@@ -0,0 +1,1457 @@ +/* + * SPDX-License-Identifier: GPL-2.0 + * Copyright (C) 2005-2017 Junjiro R. Okajima @@ -34612,6 +34612,9 @@ index 000000000000..74aecb7193ab +#include +#include "aufs.h" + ++static ssize_t xino_fread_wkq(vfs_readf_t func, struct file *file, void *buf, ++ size_t size, loff_t *pos); ++ +/* todo: unnecessary to support mmap_sem since kernel-space? */ +ssize_t xino_fread(vfs_readf_t func, struct file *file, void *kbuf, size_t size, + loff_t *pos) @@ -34622,14 +34625,26 @@ index 000000000000..74aecb7193ab + void *k; + char __user *u; + } buf; ++ int i; ++ const int prevent_endless = 10; + ++ i = 0; + buf.k = kbuf; + oldfs = get_fs(); + set_fs(KERNEL_DS); + do { -+ /* todo: signal_pending? */ + err = func(file, buf.u, size, pos); -+ } while (err == -EAGAIN || err == -EINTR); ++ if (err == -EINTR ++ && !au_wkq_test() ++ && fatal_signal_pending(current)) { ++ set_fs(oldfs); ++ err = xino_fread_wkq(func, file, kbuf, size, pos); ++ BUG_ON(err == -EINTR); ++ oldfs = get_fs(); ++ set_fs(KERNEL_DS); ++ } ++ } while (i++ < prevent_endless ++ && (err == -EAGAIN || err == -EINTR)); + set_fs(oldfs); + +#if 0 /* reserved for future use */ @@ -34640,6 +34655,42 @@ index 000000000000..74aecb7193ab + return err; +} + ++struct xino_fread_args { ++ ssize_t *errp; ++ vfs_readf_t func; ++ struct file *file; ++ void *buf; ++ size_t size; ++ loff_t *pos; ++}; ++ ++static void call_xino_fread(void *args) ++{ ++ struct xino_fread_args *a = args; ++ *a->errp = xino_fread(a->func, a->file, a->buf, a->size, a->pos); ++} ++ ++static ssize_t xino_fread_wkq(vfs_readf_t func, struct file *file, void *buf, ++ size_t size, loff_t *pos) ++{ ++ ssize_t err; ++ int wkq_err; ++ struct xino_fread_args args = { ++ .errp = &err, ++ .func = func, ++ .file = file, ++ .buf = buf, ++ .size = size, ++ .pos = pos ++ }; ++ ++ wkq_err = au_wkq_wait(call_xino_fread, &args); ++ if (unlikely(wkq_err)) ++ err = wkq_err; ++ ++ return err; ++} ++ +/* ---------------------------------------------------------------------- */ + +static ssize_t xino_fwrite_wkq(vfs_writef_t func, struct file *file, void *buf, diff --git a/kernel/tools/cpupowertools/files/patches/mageia/fs-aufs-5.4-modular.patch b/kernel/tools/cpupowertools/files/patches/mageia/fs-aufs-5.4-modular.patch new file mode 100644 index 00000000..ec4a9135 --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/mageia/fs-aufs-5.4-modular.patch @@ -0,0 +1,321 @@ + + fs/aufs/Kconfig | 2 +- + fs/dcache.c | 2 ++ + fs/exec.c | 1 + + fs/fcntl.c | 1 + + fs/file_table.c | 2 ++ + fs/inode.c | 1 + + fs/namespace.c | 3 +++ + fs/notify/group.c | 1 + + fs/open.c | 1 + + fs/read_write.c | 4 ++++ + fs/splice.c | 2 ++ + fs/sync.c | 1 + + fs/xattr.c | 1 + + kernel/locking/lockdep.c | 1 + + kernel/task_work.c | 1 + + security/device_cgroup.c | 1 + + security/security.c | 8 ++++++++ + 17 files changed, 32 insertions(+), 1 deletion(-) + +diff -Nurp linux-5.4-aufs/fs/aufs/Kconfig linux-5.4-aufs-mod/fs/aufs/Kconfig +--- linux-5.4-aufs/fs/aufs/Kconfig 2019-11-28 01:25:59.062925618 +0200 ++++ linux-5.4-aufs-mod/fs/aufs/Kconfig 2019-11-28 01:38:40.564895255 +0200 +@@ -1,6 +1,6 @@ + # SPDX-License-Identifier: GPL-2.0 + config AUFS_FS +- bool "Aufs (Advanced multi layered unification filesystem) support" ++ tristate "Aufs (Advanced multi layered unification filesystem) support" + help + Aufs is a stackable unification filesystem such as Unionfs, + which unifies several directories and provides a merged single +diff -Nurp linux-5.4-aufs/fs/dcache.c linux-5.4-aufs-mod/fs/dcache.c +--- linux-5.4-aufs/fs/dcache.c 2019-11-28 01:25:59.069925618 +0200 ++++ linux-5.4-aufs-mod/fs/dcache.c 2019-11-28 01:38:40.585895254 +0200 +@@ -1369,6 +1369,7 @@ rename_retry: + seq = 1; + goto again; + } ++EXPORT_SYMBOL_GPL(d_walk); + + struct check_mount { + struct vfsmount *mnt; +@@ -2914,6 +2915,7 @@ void d_exchange(struct dentry *dentry1, + + write_sequnlock(&rename_lock); + } ++EXPORT_SYMBOL_GPL(d_exchange); + + /** + * d_ancestor - search for an ancestor +diff -Nurp linux-5.4-aufs/fs/exec.c linux-5.4-aufs-mod/fs/exec.c +--- linux-5.4-aufs/fs/exec.c 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs-mod/fs/exec.c 2019-11-28 01:38:40.589895254 +0200 +@@ -110,6 +110,7 @@ bool path_noexec(const struct path *path + return (path->mnt->mnt_flags & MNT_NOEXEC) || + (path->mnt->mnt_sb->s_iflags & SB_I_NOEXEC); + } ++EXPORT_SYMBOL_GPL(path_noexec); + + #ifdef CONFIG_USELIB + /* +diff -Nurp linux-5.4-aufs/fs/fcntl.c linux-5.4-aufs-mod/fs/fcntl.c +--- linux-5.4-aufs/fs/fcntl.c 2019-11-28 01:25:59.069925618 +0200 ++++ linux-5.4-aufs-mod/fs/fcntl.c 2019-11-28 01:38:40.589895254 +0200 +@@ -85,6 +85,7 @@ int setfl(int fd, struct file * filp, un + out: + return error; + } ++EXPORT_SYMBOL_GPL(setfl); + + static void f_modown(struct file *filp, struct pid *pid, enum pid_type type, + int force) +diff -Nurp linux-5.4-aufs/fs/file_table.c linux-5.4-aufs-mod/fs/file_table.c +--- linux-5.4-aufs/fs/file_table.c 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs-mod/fs/file_table.c 2019-11-28 01:38:40.589895254 +0200 +@@ -162,6 +162,7 @@ over: + } + return ERR_PTR(-ENFILE); + } ++EXPORT_SYMBOL_GPL(alloc_empty_file); + + /* + * Variant of alloc_empty_file() that doesn't check and modify nr_files. +@@ -375,6 +377,7 @@ void __fput_sync(struct file *file) + } + + EXPORT_SYMBOL(fput); ++EXPORT_SYMBOL_GPL(__fput_sync); + + void __init files_init(void) + { +diff -Nurp linux-5.4-aufs/fs/inode.c linux-5.4-aufs-mod/fs/inode.c +--- linux-5.4-aufs/fs/inode.c 2019-11-28 01:25:59.070925617 +0200 ++++ linux-5.4-aufs-mod/fs/inode.c 2019-11-28 01:38:40.589895254 +0200 +@@ -1682,6 +1682,7 @@ int update_time(struct inode *inode, str + + return update_time(inode, time, flags); + } ++EXPORT_SYMBOL_GPL(update_time); + + /** + * touch_atime - update the access time +diff -Nurp linux-5.4-aufs/fs/namespace.c linux-5.4-aufs-mod/fs/namespace.c +--- linux-5.4-aufs/fs/namespace.c 2019-11-28 01:25:59.070925617 +0200 ++++ linux-5.4-aufs-mod/fs/namespace.c 2019-11-28 01:38:40.589895254 +0200 +@@ -431,6 +431,7 @@ void __mnt_drop_write(struct vfsmount *m + mnt_dec_writers(real_mount(mnt)); + preempt_enable(); + } ++EXPORT_SYMBOL_GPL(__mnt_drop_write); + + /** + * mnt_drop_write - give up write access to a mount +@@ -781,6 +782,7 @@ int is_current_mnt_ns(struct vfsmount *m + { + return check_mnt(real_mount(mnt)); + } ++EXPORT_SYMBOL_GPL(is_current_mnt_ns); + + /* + * vfsmount lock must be held for write +@@ -1903,6 +1905,7 @@ int iterate_mounts(int (*f)(struct vfsmo + } + return 0; + } ++EXPORT_SYMBOL_GPL(iterate_mounts); + + static void lock_mnt_tree(struct mount *mnt) + { +diff -Nurp linux-5.4-aufs/fs/notify/group.c linux-5.4-aufs-mod/fs/notify/group.c +--- linux-5.4-aufs/fs/notify/group.c 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs-mod/fs/notify/group.c 2019-11-28 01:38:40.590895253 +0200 +@@ -99,6 +99,7 @@ void fsnotify_get_group(struct fsnotify_ + { + refcount_inc(&group->refcnt); + } ++EXPORT_SYMBOL_GPL(fsnotify_get_group); + + /* + * Drop a reference to a group. Free it if it's through. +diff -Nurp linux-5.4-aufs/fs/open.c linux-5.4-aufs-mod/fs/open.c +--- linux-5.4-aufs/fs/open.c 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs-mod/fs/open.c 2019-11-28 01:38:48.762894928 +0200 +@@ -65,6 +65,7 @@ int do_truncate(struct dentry *dentry, l + inode_unlock(dentry->d_inode); + return ret; + } ++EXPORT_SYMBOL_GPL(do_truncate); + + long vfs_truncate(const struct path *path, loff_t length) + { +diff -Nurp linux-5.4-aufs/fs/read_write.c linux-5.4-aufs-mod/fs/read_write.c +--- linux-5.4-aufs/fs/read_write.c 2019-11-28 01:25:59.070925617 +0200 ++++ linux-5.4-aufs-mod/fs/read_write.c 2019-11-28 01:38:48.780894927 +0200 +@@ -468,6 +468,7 @@ ssize_t vfs_read(struct file *file, char + + return ret; + } ++EXPORT_SYMBOL_GPL(vfs_read); + + static ssize_t new_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos) + { +@@ -508,6 +509,7 @@ vfs_readf_t vfs_readf(struct file *file) + return new_sync_read; + return ERR_PTR(-ENOSYS); + } ++EXPORT_SYMBOL_GPL(vfs_readf); + + vfs_writef_t vfs_writef(struct file *file) + { +@@ -519,6 +521,7 @@ vfs_writef_t vfs_writef(struct file *fil + return new_sync_write; + return ERR_PTR(-ENOSYS); + } ++EXPORT_SYMBOL_GPL(vfs_writef); + + ssize_t __kernel_write(struct file *file, const void *buf, size_t count, loff_t *pos) + { +@@ -588,6 +591,7 @@ ssize_t vfs_write(struct file *file, con + + return ret; + } ++EXPORT_SYMBOL_GPL(vfs_write); + + /* file_ppos returns &file->f_pos or NULL if file is stream */ + static inline loff_t *file_ppos(struct file *file) +diff -Nurp linux-5.4-aufs/fs/splice.c linux-5.4-aufs-mod/fs/splice.c +--- linux-5.4-aufs/fs/splice.c 2019-11-28 01:25:59.071925617 +0200 ++++ linux-5.4-aufs-mod/fs/splice.c 2019-11-28 01:38:48.780894927 +0200 +@@ -847,6 +847,7 @@ long do_splice_from(struct pipe_inode_in + + return splice_write(pipe, out, ppos, len, flags); + } ++EXPORT_SYMBOL_GPL(do_splice_from); + + /* + * Attempt to initiate a splice from a file to a pipe. +@@ -876,6 +877,7 @@ long do_splice_to(struct file *in, loff_ + + return splice_read(in, ppos, pipe, len, flags); + } ++EXPORT_SYMBOL_GPL(do_splice_to); + + /** + * splice_direct_to_actor - splices data directly between two non-pipes +diff -Nurp linux-5.4-aufs/fs/sync.c linux-5.4-aufs-mod/fs/sync.c +--- linux-5.4-aufs/fs/sync.c 2019-11-28 01:25:59.071925617 +0200 ++++ linux-5.4-aufs-mod/fs/sync.c 2019-11-28 01:38:48.780894927 +0200 +@@ -39,6 +39,7 @@ int __sync_filesystem(struct super_block + sb->s_op->sync_fs(sb, wait); + return __sync_blockdev(sb->s_bdev, wait); + } ++EXPORT_SYMBOL_GPL(__sync_filesystem); + + /* + * Write out and wait upon all dirty data associated with this +diff -Nurp linux-5.4-aufs/fs/xattr.c linux-5.4-aufs-mod/fs/xattr.c +--- linux-5.4-aufs/fs/xattr.c 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs-mod/fs/xattr.c 2019-11-28 01:38:48.780894927 +0200 +@@ -296,6 +296,7 @@ vfs_getxattr_alloc(struct dentry *dentry + *xattr_value = value; + return error; + } ++EXPORT_SYMBOL_GPL(vfs_getxattr_alloc); + + ssize_t + __vfs_getxattr(struct dentry *dentry, struct inode *inode, const char *name, +diff -Nurp linux-5.4-aufs/kernel/locking/lockdep.c linux-5.4-aufs-mod/kernel/locking/lockdep.c +--- linux-5.4-aufs/kernel/locking/lockdep.c 2019-11-28 01:25:59.072925617 +0200 ++++ linux-5.4-aufs-mod/kernel/locking/lockdep.c 2019-11-28 01:38:48.780894927 +0200 +@@ -174,6 +174,7 @@ inline struct lock_class *lockdep_hlock_ + */ + return lock_classes + class_idx; + } ++EXPORT_SYMBOL_GPL(lockdep_hlock_class); + #define hlock_class(hlock) lockdep_hlock_class(hlock) + + #ifdef CONFIG_LOCK_STAT +diff -Nurp linux-5.4-aufs/kernel/task_work.c linux-5.4-aufs-mod/kernel/task_work.c +--- linux-5.4-aufs/kernel/task_work.c 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs-mod/kernel/task_work.c 2019-11-28 01:38:48.786894927 +0200 +@@ -116,3 +116,4 @@ void task_work_run(void) + } while (work); + } + } ++EXPORT_SYMBOL_GPL(task_work_run); +diff -Nurp linux-5.4-aufs/security/device_cgroup.c linux-5.4-aufs-mod/security/device_cgroup.c +--- linux-5.4-aufs/security/device_cgroup.c 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs-mod/security/device_cgroup.c 2019-11-28 01:38:48.790894927 +0200 +@@ -824,3 +824,4 @@ int __devcgroup_check_permission(short t + + return 0; + } ++EXPORT_SYMBOL_GPL(__devcgroup_check_permission); +diff -Nurp linux-5.4-aufs/security/security.c linux-5.4-aufs-mod/security/security.c +--- linux-5.4-aufs/security/security.c 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs-mod/security/security.c 2019-11-28 01:38:48.794894926 +0200 +@@ -1036,6 +1036,7 @@ int security_path_rmdir(const struct pat + return 0; + return call_int_hook(path_rmdir, 0, dir, dentry); + } ++EXPORT_SYMBOL_GPL(security_path_rmdir); + + int security_path_unlink(const struct path *dir, struct dentry *dentry) + { +@@ -1052,6 +1053,7 @@ int security_path_symlink(const struct p + return 0; + return call_int_hook(path_symlink, 0, dir, dentry, old_name); + } ++EXPORT_SYMBOL_GPL(security_path_symlink); + + int security_path_link(struct dentry *old_dentry, const struct path *new_dir, + struct dentry *new_dentry) +@@ -1060,6 +1062,7 @@ int security_path_link(struct dentry *ol + return 0; + return call_int_hook(path_link, 0, old_dentry, new_dir, new_dentry); + } ++EXPORT_SYMBOL_GPL(security_path_link); + + int security_path_rename(const struct path *old_dir, struct dentry *old_dentry, + const struct path *new_dir, struct dentry *new_dentry, +@@ -1087,6 +1090,7 @@ int security_path_truncate(const struct + return 0; + return call_int_hook(path_truncate, 0, path); + } ++EXPORT_SYMBOL_GPL(security_path_truncate); + + int security_path_chmod(const struct path *path, umode_t mode) + { +@@ -1094,6 +1098,7 @@ int security_path_chmod(const struct pat + return 0; + return call_int_hook(path_chmod, 0, path, mode); + } ++EXPORT_SYMBOL_GPL(security_path_chmod); + + int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid) + { +@@ -1101,6 +1106,7 @@ int security_path_chown(const struct pat + return 0; + return call_int_hook(path_chown, 0, path, uid, gid); + } ++EXPORT_SYMBOL_GPL(security_path_chown); + + int security_path_chroot(const struct path *path) + { +@@ -1201,6 +1207,7 @@ int security_inode_permission(struct ino + return 0; + return call_int_hook(inode_permission, 0, inode, mask); + } ++EXPORT_SYMBOL_GPL(security_inode_permission); + + int security_inode_setattr(struct dentry *dentry, struct iattr *attr) + { +@@ -1378,6 +1385,7 @@ int security_file_permission(struct file + + return fsnotify_perm(file, mask); + } ++EXPORT_SYMBOL_GPL(security_file_permission); + + int security_file_alloc(struct file *file) + { diff --git a/kernel/tools/cpupowertools/files/patches/mageia/fs-aufs-5.4-version.patch b/kernel/tools/cpupowertools/files/patches/mageia/fs-aufs-5.4-version.patch new file mode 100755 index 00000000..85c71bf3 --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/mageia/fs-aufs-5.4-version.patch @@ -0,0 +1,12 @@ +diff -Nurp linux-5.3-aufs/include/uapi/linux/aufs_type.h linux-5.3-aufs-ver/include/uapi/linux/aufs_type.h +--- linux-5.3-aufs/include/uapi/linux/aufs_type.h 2019-09-24 16:13:44.012259519 +0300 ++++ linux-5.3-aufs-ver/include/uapi/linux/aufs_type.h 2019-09-24 20:04:21.924707762 +0300 +@@ -27,7 +27,7 @@ + + #include + +-#define AUFS_VERSION "5.x-rcN" ++#define AUFS_VERSION "5.4" + + /* todo? move this to linux-2.6.19/include/magic.h */ + #define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's') diff --git a/kernel/tools/cpupowertools/files/patches/mageia/fs-aufs-5.4.patch b/kernel/tools/cpupowertools/files/patches/mageia/fs-aufs-5.4.patch new file mode 100644 index 00000000..0f717dbf --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/mageia/fs-aufs-5.4.patch @@ -0,0 +1,37876 @@ + + Documentation/ABI/testing/debugfs-aufs | 55 + Documentation/ABI/testing/sysfs-aufs | 31 + Documentation/filesystems/aufs/README | 399 +++ + Documentation/filesystems/aufs/design/01intro.txt | 158 + + Documentation/filesystems/aufs/design/02struct.txt | 245 ++ + Documentation/filesystems/aufs/design/03atomic_open.txt | 72 + Documentation/filesystems/aufs/design/03lookup.txt | 100 + Documentation/filesystems/aufs/design/04branch.txt | 61 + Documentation/filesystems/aufs/design/05wbr_policy.txt | 51 + Documentation/filesystems/aufs/design/06dirren.dot | 31 + Documentation/filesystems/aufs/design/06dirren.txt | 89 + Documentation/filesystems/aufs/design/06fhsm.txt | 105 + Documentation/filesystems/aufs/design/06mmap.txt | 59 + Documentation/filesystems/aufs/design/06xattr.txt | 81 + Documentation/filesystems/aufs/design/07export.txt | 45 + Documentation/filesystems/aufs/design/08shwh.txt | 39 + Documentation/filesystems/aufs/design/10dynop.txt | 34 + MAINTAINERS | 13 + drivers/block/loop.c | 18 + fs/Kconfig | 1 + fs/Makefile | 1 + fs/aufs/Kconfig | 199 + + fs/aufs/Makefile | 39 + fs/aufs/aufs.h | 49 + fs/aufs/branch.c | 1415 +++++++++++ + fs/aufs/branch.h | 353 ++ + fs/aufs/cpup.c | 1445 +++++++++++ + fs/aufs/cpup.h | 87 + fs/aufs/dbgaufs.c | 513 ++++ + fs/aufs/dbgaufs.h | 40 + fs/aufs/dcsub.c | 212 + + fs/aufs/dcsub.h | 124 + + fs/aufs/debug.c | 428 +++ + fs/aufs/debug.h | 213 + + fs/aufs/dentry.c | 1141 +++++++++ + fs/aufs/dentry.h | 255 ++ + fs/aufs/dinfo.c | 541 ++++ + fs/aufs/dir.c | 750 ++++++ + fs/aufs/dir.h | 121 + fs/aufs/dirren.c | 1303 ++++++++++ + fs/aufs/dirren.h | 127 + + fs/aufs/dynop.c | 354 ++ + fs/aufs/dynop.h | 64 + fs/aufs/export.c | 825 ++++++ + fs/aufs/f_op.c | 806 ++++++ + fs/aufs/fhsm.c | 413 +++ + fs/aufs/file.c | 850 ++++++ + fs/aufs/file.h | 329 ++ + fs/aufs/finfo.c | 136 + + fs/aufs/fstype.h | 388 +++ + fs/aufs/hbl.h | 52 + fs/aufs/hfsnotify.c | 275 ++ + fs/aufs/hfsplus.c | 47 + fs/aufs/hnotify.c | 708 +++++ + fs/aufs/i_op.c | 1492 ++++++++++++ + fs/aufs/i_op_add.c | 923 +++++++ + fs/aufs/i_op_del.c | 500 ++++ + fs/aufs/i_op_ren.c | 1237 ++++++++++ + fs/aufs/iinfo.c | 273 ++ + fs/aufs/inode.c | 516 ++++ + fs/aufs/inode.h | 685 +++++ + fs/aufs/ioctl.c | 207 + + fs/aufs/lcnt.h | 173 + + fs/aufs/loop.c | 135 + + fs/aufs/loop.h | 42 + fs/aufs/magic.mk | 31 + fs/aufs/module.c | 259 ++ + fs/aufs/module.h | 153 + + fs/aufs/mvdown.c | 693 +++++ + fs/aufs/opts.c | 1867 +++++++++++++++ + fs/aufs/opts.h | 212 + + fs/aufs/plink.c | 503 ++++ + fs/aufs/poll.c | 38 + fs/aufs/posix_acl.c | 92 + fs/aufs/procfs.c | 158 + + fs/aufs/rdu.c | 371 +++ + fs/aufs/rwsem.h | 60 + fs/aufs/sbinfo.c | 301 ++ + fs/aufs/super.c | 1034 ++++++++ + fs/aufs/super.h | 576 ++++ + fs/aufs/sysaufs.c | 80 + fs/aufs/sysaufs.h | 89 + fs/aufs/sysfs.c | 338 ++ + fs/aufs/sysrq.c | 147 + + fs/aufs/vdir.c | 883 +++++++ + fs/aufs/vfsub.c | 889 +++++++ + fs/aufs/vfsub.h | 341 ++ + fs/aufs/wbr_policy.c | 817 ++++++ + fs/aufs/whout.c | 1049 ++++++++ + fs/aufs/whout.h | 73 + fs/aufs/wkq.c | 379 +++ + fs/aufs/wkq.h | 76 + fs/aufs/xattr.c | 343 ++ + fs/aufs/xino.c | 1952 ++++++++++++++++ + fs/dcache.c | 2 + fs/fcntl.c | 4 + fs/inode.c | 2 + fs/namespace.c | 6 + fs/proc/base.c | 2 + fs/proc/nommu.c | 5 + fs/proc/task_mmu.c | 7 + fs/proc/task_nommu.c | 5 + fs/read_write.c | 22 + fs/splice.c | 10 + fs/sync.c | 2 + include/linux/fs.h | 10 + include/linux/lockdep.h | 3 + include/linux/mm.h | 22 + include/linux/mm_types.h | 2 + include/linux/mnt_namespace.h | 3 + include/linux/splice.h | 6 + include/uapi/linux/aufs_type.h | 439 +++ + kernel/fork.c | 2 + kernel/locking/lockdep.c | 3 + mm/Makefile | 2 + mm/filemap.c | 2 + mm/mmap.c | 33 + mm/nommu.c | 10 + mm/prfile.c | 86 + 119 files changed, 36936 insertions(+), 31 deletions(-) + +diff -Nurp linux-5.4/Documentation/ABI/testing/debugfs-aufs linux-5.4-aufs/Documentation/ABI/testing/debugfs-aufs +--- linux-5.4/Documentation/ABI/testing/debugfs-aufs 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/Documentation/ABI/testing/debugfs-aufs 2019-11-28 01:25:59.060925618 +0200 +@@ -0,0 +1,55 @@ ++What: /debug/aufs/si_/ ++Date: March 2009 ++Contact: J. R. Okajima ++Description: ++ Under /debug/aufs, a directory named si_ is created ++ per aufs mount, where is a unique id generated ++ internally. ++ ++What: /debug/aufs/si_/plink ++Date: Apr 2013 ++Contact: J. R. Okajima ++Description: ++ It has three lines and shows the information about the ++ pseudo-link. The first line is a single number ++ representing a number of buckets. The second line is a ++ number of pseudo-links per buckets (separated by a ++ blank). The last line is a single number representing a ++ total number of psedo-links. ++ When the aufs mount option 'noplink' is specified, it ++ will show "1\n0\n0\n". ++ ++What: /debug/aufs/si_/xib ++Date: March 2009 ++Contact: J. R. Okajima ++Description: ++ It shows the consumed blocks by xib (External Inode Number ++ Bitmap), its block size and file size. ++ When the aufs mount option 'noxino' is specified, it ++ will be empty. About XINO files, see the aufs manual. ++ ++What: /debug/aufs/si_/xi0, xi1 ... xiN and xiN-N ++Date: March 2009 ++Contact: J. R. Okajima ++Description: ++ It shows the consumed blocks by xino (External Inode Number ++ Translation Table), its link count, block size and file ++ size. ++ Due to the file size limit, there may exist multiple ++ xino files per branch. In this case, "-N" is added to ++ the filename and it corresponds to the index of the ++ internal xino array. "-0" is omitted. ++ When the aufs mount option 'noxino' is specified, Those ++ entries won't exist. About XINO files, see the aufs ++ manual. ++ ++What: /debug/aufs/si_/xigen ++Date: March 2009 ++Contact: J. R. Okajima ++Description: ++ It shows the consumed blocks by xigen (External Inode ++ Generation Table), its block size and file size. ++ If CONFIG_AUFS_EXPORT is disabled, this entry will not ++ be created. ++ When the aufs mount option 'noxino' is specified, it ++ will be empty. About XINO files, see the aufs manual. +diff -Nurp linux-5.4/Documentation/ABI/testing/sysfs-aufs linux-5.4-aufs/Documentation/ABI/testing/sysfs-aufs +--- linux-5.4/Documentation/ABI/testing/sysfs-aufs 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/Documentation/ABI/testing/sysfs-aufs 2019-11-28 01:25:59.060925618 +0200 +@@ -0,0 +1,31 @@ ++What: /sys/fs/aufs/si_/ ++Date: March 2009 ++Contact: J. R. Okajima ++Description: ++ Under /sys/fs/aufs, a directory named si_ is created ++ per aufs mount, where is a unique id generated ++ internally. ++ ++What: /sys/fs/aufs/si_/br0, br1 ... brN ++Date: March 2009 ++Contact: J. R. Okajima ++Description: ++ It shows the abolute path of a member directory (which ++ is called branch) in aufs, and its permission. ++ ++What: /sys/fs/aufs/si_/brid0, brid1 ... bridN ++Date: July 2013 ++Contact: J. R. Okajima ++Description: ++ It shows the id of a member directory (which is called ++ branch) in aufs. ++ ++What: /sys/fs/aufs/si_/xi_path ++Date: March 2009 ++Contact: J. R. Okajima ++Description: ++ It shows the abolute path of XINO (External Inode Number ++ Bitmap, Translation Table and Generation Table) file ++ even if it is the default path. ++ When the aufs mount option 'noxino' is specified, it ++ will be empty. About XINO files, see the aufs manual. +diff -Nurp linux-5.4/Documentation/filesystems/aufs/design/01intro.txt linux-5.4-aufs/Documentation/filesystems/aufs/design/01intro.txt +--- linux-5.4/Documentation/filesystems/aufs/design/01intro.txt 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/Documentation/filesystems/aufs/design/01intro.txt 2019-11-28 01:25:59.060925618 +0200 +@@ -0,0 +1,158 @@ ++ ++# Copyright (C) 2005-2019 Junjiro R. Okajima ++ ++Introduction ++---------------------------------------- ++ ++aufs [ei ju: ef es] | /ey-yoo-ef-es/ | [a u f s] ++1. abbrev. for "advanced multi-layered unification filesystem". ++2. abbrev. for "another unionfs". ++3. abbrev. for "auf das" in German which means "on the" in English. ++ Ex. "Butter aufs Brot"(G) means "butter onto bread"(E). ++ But "Filesystem aufs Filesystem" is hard to understand. ++4. abbrev. for "African Urban Fashion Show". ++ ++AUFS is a filesystem with features: ++- multi layered stackable unification filesystem, the member directory ++ is called as a branch. ++- branch permission and attribute, 'readonly', 'real-readonly', ++ 'readwrite', 'whiteout-able', 'link-able whiteout', etc. and their ++ combination. ++- internal "file copy-on-write". ++- logical deletion, whiteout. ++- dynamic branch manipulation, adding, deleting and changing permission. ++- allow bypassing aufs, user's direct branch access. ++- external inode number translation table and bitmap which maintains the ++ persistent aufs inode number. ++- seekable directory, including NFS readdir. ++- file mapping, mmap and sharing pages. ++- pseudo-link, hardlink over branches. ++- loopback mounted filesystem as a branch. ++- several policies to select one among multiple writable branches. ++- revert a single systemcall when an error occurs in aufs. ++- and more... ++ ++ ++Multi Layered Stackable Unification Filesystem ++---------------------------------------------------------------------- ++Most people already knows what it is. ++It is a filesystem which unifies several directories and provides a ++merged single directory. When users access a file, the access will be ++passed/re-directed/converted (sorry, I am not sure which English word is ++correct) to the real file on the member filesystem. The member ++filesystem is called 'lower filesystem' or 'branch' and has a mode ++'readonly' and 'readwrite.' And the deletion for a file on the lower ++readonly branch is handled by creating 'whiteout' on the upper writable ++branch. ++ ++On LKML, there have been discussions about UnionMount (Jan Blunck, ++Bharata B Rao and Valerie Aurora) and Unionfs (Erez Zadok). They took ++different approaches to implement the merged-view. ++The former tries putting it into VFS, and the latter implements as a ++separate filesystem. ++(If I misunderstand about these implementations, please let me know and ++I shall correct it. Because it is a long time ago when I read their ++source files last time). ++ ++UnionMount's approach will be able to small, but may be hard to share ++branches between several UnionMount since the whiteout in it is ++implemented in the inode on branch filesystem and always ++shared. According to Bharata's post, readdir does not seems to be ++finished yet. ++There are several missing features known in this implementations such as ++- for users, the inode number may change silently. eg. copy-up. ++- link(2) may break by copy-up. ++- read(2) may get an obsoleted filedata (fstat(2) too). ++- fcntl(F_SETLK) may be broken by copy-up. ++- unnecessary copy-up may happen, for example mmap(MAP_PRIVATE) after ++ open(O_RDWR). ++ ++In linux-3.18, "overlay" filesystem (formerly known as "overlayfs") was ++merged into mainline. This is another implementation of UnionMount as a ++separated filesystem. All the limitations and known problems which ++UnionMount are equally inherited to "overlay" filesystem. ++ ++Unionfs has a longer history. When I started implementing a stackable ++filesystem (Aug 2005), it already existed. It has virtual super_block, ++inode, dentry and file objects and they have an array pointing lower ++same kind objects. After contributing many patches for Unionfs, I ++re-started my project AUFS (Jun 2006). ++ ++In AUFS, the structure of filesystem resembles to Unionfs, but I ++implemented my own ideas, approaches and enhancements and it became ++totally different one. ++ ++Comparing DM snapshot and fs based implementation ++- the number of bytes to be copied between devices is much smaller. ++- the type of filesystem must be one and only. ++- the fs must be writable, no readonly fs, even for the lower original ++ device. so the compression fs will not be usable. but if we use ++ loopback mount, we may address this issue. ++ for instance, ++ mount /cdrom/squashfs.img /sq ++ losetup /sq/ext2.img ++ losetup /somewhere/cow ++ dmsetup "snapshot /dev/loop0 /dev/loop1 ..." ++- it will be difficult (or needs more operations) to extract the ++ difference between the original device and COW. ++- DM snapshot-merge may help a lot when users try merging. in the ++ fs-layer union, users will use rsync(1). ++ ++You may want to read my old paper "Filesystems in LiveCD" ++(http://aufs.sourceforge.net/aufs2/report/sq/sq.pdf). ++ ++ ++Several characters/aspects/persona of aufs ++---------------------------------------------------------------------- ++ ++Aufs has several characters, aspects or persona. ++1. a filesystem, callee of VFS helper ++2. sub-VFS, caller of VFS helper for branches ++3. a virtual filesystem which maintains persistent inode number ++4. reader/writer of files on branches such like an application ++ ++1. Callee of VFS Helper ++As an ordinary linux filesystem, aufs is a callee of VFS. For instance, ++unlink(2) from an application reaches sys_unlink() kernel function and ++then vfs_unlink() is called. vfs_unlink() is one of VFS helper and it ++calls filesystem specific unlink operation. Actually aufs implements the ++unlink operation but it behaves like a redirector. ++ ++2. Caller of VFS Helper for Branches ++aufs_unlink() passes the unlink request to the branch filesystem as if ++it were called from VFS. So the called unlink operation of the branch ++filesystem acts as usual. As a caller of VFS helper, aufs should handle ++every necessary pre/post operation for the branch filesystem. ++- acquire the lock for the parent dir on a branch ++- lookup in a branch ++- revalidate dentry on a branch ++- mnt_want_write() for a branch ++- vfs_unlink() for a branch ++- mnt_drop_write() for a branch ++- release the lock on a branch ++ ++3. Persistent Inode Number ++One of the most important issue for a filesystem is to maintain inode ++numbers. This is particularly important to support exporting a ++filesystem via NFS. Aufs is a virtual filesystem which doesn't have a ++backend block device for its own. But some storage is necessary to ++keep and maintain the inode numbers. It may be a large space and may not ++suit to keep in memory. Aufs rents some space from its first writable ++branch filesystem (by default) and creates file(s) on it. These files ++are created by aufs internally and removed soon (currently) keeping ++opened. ++Note: Because these files are removed, they are totally gone after ++ unmounting aufs. It means the inode numbers are not persistent ++ across unmount or reboot. I have a plan to make them really ++ persistent which will be important for aufs on NFS server. ++ ++4. Read/Write Files Internally (copy-on-write) ++Because a branch can be readonly, when you write a file on it, aufs will ++"copy-up" it to the upper writable branch internally. And then write the ++originally requested thing to the file. Generally kernel doesn't ++open/read/write file actively. In aufs, even a single write may cause a ++internal "file copy". This behaviour is very similar to cp(1) command. ++ ++Some people may think it is better to pass such work to user space ++helper, instead of doing in kernel space. Actually I am still thinking ++about it. But currently I have implemented it in kernel space. +diff -Nurp linux-5.4/Documentation/filesystems/aufs/design/02struct.txt linux-5.4-aufs/Documentation/filesystems/aufs/design/02struct.txt +--- linux-5.4/Documentation/filesystems/aufs/design/02struct.txt 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/Documentation/filesystems/aufs/design/02struct.txt 2019-11-28 01:25:59.060925618 +0200 +@@ -0,0 +1,245 @@ ++ ++# Copyright (C) 2005-2019 Junjiro R. Okajima ++ ++Basic Aufs Internal Structure ++ ++Superblock/Inode/Dentry/File Objects ++---------------------------------------------------------------------- ++As like an ordinary filesystem, aufs has its own ++superblock/inode/dentry/file objects. All these objects have a ++dynamically allocated array and store the same kind of pointers to the ++lower filesystem, branch. ++For example, when you build a union with one readwrite branch and one ++readonly, mounted /au, /rw and /ro respectively. ++- /au = /rw + /ro ++- /ro/fileA exists but /rw/fileA ++ ++Aufs lookup operation finds /ro/fileA and gets dentry for that. These ++pointers are stored in a aufs dentry. The array in aufs dentry will be, ++- [0] = NULL (because /rw/fileA doesn't exist) ++- [1] = /ro/fileA ++ ++This style of an array is essentially same to the aufs ++superblock/inode/dentry/file objects. ++ ++Because aufs supports manipulating branches, ie. add/delete/change ++branches dynamically, these objects has its own generation. When ++branches are changed, the generation in aufs superblock is ++incremented. And a generation in other object are compared when it is ++accessed. When a generation in other objects are obsoleted, aufs ++refreshes the internal array. ++ ++ ++Superblock ++---------------------------------------------------------------------- ++Additionally aufs superblock has some data for policies to select one ++among multiple writable branches, XIB files, pseudo-links and kobject. ++See below in detail. ++About the policies which supports copy-down a directory, see ++wbr_policy.txt too. ++ ++ ++Branch and XINO(External Inode Number Translation Table) ++---------------------------------------------------------------------- ++Every branch has its own xino (external inode number translation table) ++file. The xino file is created and unlinked by aufs internally. When two ++members of a union exist on the same filesystem, they share the single ++xino file. ++The struct of a xino file is simple, just a sequence of aufs inode ++numbers which is indexed by the lower inode number. ++In the above sample, assume the inode number of /ro/fileA is i111 and ++aufs assigns the inode number i999 for fileA. Then aufs writes 999 as ++4(8) bytes at 111 * 4(8) bytes offset in the xino file. ++ ++When the inode numbers are not contiguous, the xino file will be sparse ++which has a hole in it and doesn't consume as much disk space as it ++might appear. If your branch filesystem consumes disk space for such ++holes, then you should specify 'xino=' option at mounting aufs. ++ ++Aufs has a mount option to free the disk blocks for such holes in XINO ++files on tmpfs or ramdisk. But it is not so effective actually. If you ++meet a problem of disk shortage due to XINO files, then you should try ++"tmpfs-ino.patch" (and "vfs-ino.patch" too) in aufs4-standalone.git. ++The patch localizes the assignment inumbers per tmpfs-mount and avoid ++the holes in XINO files. ++ ++Also a writable branch has three kinds of "whiteout bases". All these ++are existed when the branch is joined to aufs, and their names are ++whiteout-ed doubly, so that users will never see their names in aufs ++hierarchy. ++1. a regular file which will be hardlinked to all whiteouts. ++2. a directory to store a pseudo-link. ++3. a directory to store an "orphan"-ed file temporary. ++ ++1. Whiteout Base ++ When you remove a file on a readonly branch, aufs handles it as a ++ logical deletion and creates a whiteout on the upper writable branch ++ as a hardlink of this file in order not to consume inode on the ++ writable branch. ++2. Pseudo-link Dir ++ See below, Pseudo-link. ++3. Step-Parent Dir ++ When "fileC" exists on the lower readonly branch only and it is ++ opened and removed with its parent dir, and then user writes ++ something into it, then aufs copies-up fileC to this ++ directory. Because there is no other dir to store fileC. After ++ creating a file under this dir, the file is unlinked. ++ ++Because aufs supports manipulating branches, ie. add/delete/change ++dynamically, a branch has its own id. When the branch order changes, ++aufs finds the new index by searching the branch id. ++ ++ ++Pseudo-link ++---------------------------------------------------------------------- ++Assume "fileA" exists on the lower readonly branch only and it is ++hardlinked to "fileB" on the branch. When you write something to fileA, ++aufs copies-up it to the upper writable branch. Additionally aufs ++creates a hardlink under the Pseudo-link Directory of the writable ++branch. The inode of a pseudo-link is kept in aufs super_block as a ++simple list. If fileB is read after unlinking fileA, aufs returns ++filedata from the pseudo-link instead of the lower readonly ++branch. Because the pseudo-link is based upon the inode, to keep the ++inode number by xino (see above) is essentially necessary. ++ ++All the hardlinks under the Pseudo-link Directory of the writable branch ++should be restored in a proper location later. Aufs provides a utility ++to do this. The userspace helpers executed at remounting and unmounting ++aufs by default. ++During this utility is running, it puts aufs into the pseudo-link ++maintenance mode. In this mode, only the process which began the ++maintenance mode (and its child processes) is allowed to operate in ++aufs. Some other processes which are not related to the pseudo-link will ++be allowed to run too, but the rest have to return an error or wait ++until the maintenance mode ends. If a process already acquires an inode ++mutex (in VFS), it has to return an error. ++ ++ ++XIB(external inode number bitmap) ++---------------------------------------------------------------------- ++Addition to the xino file per a branch, aufs has an external inode number ++bitmap in a superblock object. It is also an internal file such like a ++xino file. ++It is a simple bitmap to mark whether the aufs inode number is in-use or ++not. ++To reduce the file I/O, aufs prepares a single memory page to cache xib. ++ ++As well as XINO files, aufs has a feature to truncate/refresh XIB to ++reduce the number of consumed disk blocks for these files. ++ ++ ++Virtual or Vertical Dir, and Readdir in Userspace ++---------------------------------------------------------------------- ++In order to support multiple layers (branches), aufs readdir operation ++constructs a virtual dir block on memory. For readdir, aufs calls ++vfs_readdir() internally for each dir on branches, merges their entries ++with eliminating the whiteout-ed ones, and sets it to file (dir) ++object. So the file object has its entry list until it is closed. The ++entry list will be updated when the file position is zero and becomes ++obsoleted. This decision is made in aufs automatically. ++ ++The dynamically allocated memory block for the name of entries has a ++unit of 512 bytes (by default) and stores the names contiguously (no ++padding). Another block for each entry is handled by kmem_cache too. ++During building dir blocks, aufs creates hash list and judging whether ++the entry is whiteouted by its upper branch or already listed. ++The merged result is cached in the corresponding inode object and ++maintained by a customizable life-time option. ++ ++Some people may call it can be a security hole or invite DoS attack ++since the opened and once readdir-ed dir (file object) holds its entry ++list and becomes a pressure for system memory. But I'd say it is similar ++to files under /proc or /sys. The virtual files in them also holds a ++memory page (generally) while they are opened. When an idea to reduce ++memory for them is introduced, it will be applied to aufs too. ++For those who really hate this situation, I've developed readdir(3) ++library which operates this merging in userspace. You just need to set ++LD_PRELOAD environment variable, and aufs will not consume no memory in ++kernel space for readdir(3). ++ ++ ++Workqueue ++---------------------------------------------------------------------- ++Aufs sometimes requires privilege access to a branch. For instance, ++in copy-up/down operation. When a user process is going to make changes ++to a file which exists in the lower readonly branch only, and the mode ++of one of ancestor directories may not be writable by a user ++process. Here aufs copy-up the file with its ancestors and they may ++require privilege to set its owner/group/mode/etc. ++This is a typical case of a application character of aufs (see ++Introduction). ++ ++Aufs uses workqueue synchronously for this case. It creates its own ++workqueue. The workqueue is a kernel thread and has privilege. Aufs ++passes the request to call mkdir or write (for example), and wait for ++its completion. This approach solves a problem of a signal handler ++simply. ++If aufs didn't adopt the workqueue and changed the privilege of the ++process, then the process may receive the unexpected SIGXFSZ or other ++signals. ++ ++Also aufs uses the system global workqueue ("events" kernel thread) too ++for asynchronous tasks, such like handling inotify/fsnotify, re-creating a ++whiteout base and etc. This is unrelated to a privilege. ++Most of aufs operation tries acquiring a rw_semaphore for aufs ++superblock at the beginning, at the same time waits for the completion ++of all queued asynchronous tasks. ++ ++ ++Whiteout ++---------------------------------------------------------------------- ++The whiteout in aufs is very similar to Unionfs's. That is represented ++by its filename. UnionMount takes an approach of a file mode, but I am ++afraid several utilities (find(1) or something) will have to support it. ++ ++Basically the whiteout represents "logical deletion" which stops aufs to ++lookup further, but also it represents "dir is opaque" which also stop ++further lookup. ++ ++In aufs, rmdir(2) and rename(2) for dir uses whiteout alternatively. ++In order to make several functions in a single systemcall to be ++revertible, aufs adopts an approach to rename a directory to a temporary ++unique whiteouted name. ++For example, in rename(2) dir where the target dir already existed, aufs ++renames the target dir to a temporary unique whiteouted name before the ++actual rename on a branch, and then handles other actions (make it opaque, ++update the attributes, etc). If an error happens in these actions, aufs ++simply renames the whiteouted name back and returns an error. If all are ++succeeded, aufs registers a function to remove the whiteouted unique ++temporary name completely and asynchronously to the system global ++workqueue. ++ ++ ++Copy-up ++---------------------------------------------------------------------- ++It is a well-known feature or concept. ++When user modifies a file on a readonly branch, aufs operate "copy-up" ++internally and makes change to the new file on the upper writable branch. ++When the trigger systemcall does not update the timestamps of the parent ++dir, aufs reverts it after copy-up. ++ ++ ++Move-down (aufs3.9 and later) ++---------------------------------------------------------------------- ++"Copy-up" is one of the essential feature in aufs. It copies a file from ++the lower readonly branch to the upper writable branch when a user ++changes something about the file. ++"Move-down" is an opposite action of copy-up. Basically this action is ++ran manually instead of automatically and internally. ++For desgin and implementation, aufs has to consider these issues. ++- whiteout for the file may exist on the lower branch. ++- ancestor directories may not exist on the lower branch. ++- diropq for the ancestor directories may exist on the upper branch. ++- free space on the lower branch will reduce. ++- another access to the file may happen during moving-down, including ++ UDBA (see "Revalidate Dentry and UDBA"). ++- the file should not be hard-linked nor pseudo-linked. they should be ++ handled by auplink utility later. ++ ++Sometimes users want to move-down a file from the upper writable branch ++to the lower readonly or writable branch. For instance, ++- the free space of the upper writable branch is going to run out. ++- create a new intermediate branch between the upper and lower branch. ++- etc. ++ ++For this purpose, use "aumvdown" command in aufs-util.git. +diff -Nurp linux-5.4/Documentation/filesystems/aufs/design/03atomic_open.txt linux-5.4-aufs/Documentation/filesystems/aufs/design/03atomic_open.txt +--- linux-5.4/Documentation/filesystems/aufs/design/03atomic_open.txt 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/Documentation/filesystems/aufs/design/03atomic_open.txt 2019-11-28 01:25:59.060925618 +0200 +@@ -0,0 +1,72 @@ ++ ++# Copyright (C) 2015-2019 Junjiro R. Okajima ++ ++Support for a branch who has its ->atomic_open() ++---------------------------------------------------------------------- ++The filesystems who implement its ->atomic_open() are not majority. For ++example NFSv4 does, and aufs should call NFSv4 ->atomic_open, ++particularly for open(O_CREAT|O_EXCL, 0400) case. Other than ++->atomic_open(), NFSv4 returns an error for this open(2). While I am not ++sure whether all filesystems who have ->atomic_open() behave like this, ++but NFSv4 surely returns the error. ++ ++In order to support ->atomic_open() for aufs, there are a few ++approaches. ++ ++A. Introduce aufs_atomic_open() ++ - calls one of VFS:do_last(), lookup_open() or atomic_open() for ++ branch fs. ++B. Introduce aufs_atomic_open() calling create, open and chmod. this is ++ an aufs user Pip Cet's approach ++ - calls aufs_create(), VFS finish_open() and notify_change(). ++ - pass fake-mode to finish_open(), and then correct the mode by ++ notify_change(). ++C. Extend aufs_open() to call branch fs's ->atomic_open() ++ - no aufs_atomic_open(). ++ - aufs_lookup() registers the TID to an aufs internal object. ++ - aufs_create() does nothing when the matching TID is registered, but ++ registers the mode. ++ - aufs_open() calls branch fs's ->atomic_open() when the matching ++ TID is registered. ++D. Extend aufs_open() to re-try branch fs's ->open() with superuser's ++ credential ++ - no aufs_atomic_open(). ++ - aufs_create() registers the TID to an internal object. this info ++ represents "this process created this file just now." ++ - when aufs gets EACCES from branch fs's ->open(), then confirm the ++ registered TID and re-try open() with superuser's credential. ++ ++Pros and cons for each approach. ++ ++A. ++ - straightforward but highly depends upon VFS internal. ++ - the atomic behavaiour is kept. ++ - some of parameters such as nameidata are hard to reproduce for ++ branch fs. ++ - large overhead. ++B. ++ - easy to implement. ++ - the atomic behavaiour is lost. ++C. ++ - the atomic behavaiour is kept. ++ - dirty and tricky. ++ - VFS checks whether the file is created correctly after calling ++ ->create(), which means this approach doesn't work. ++D. ++ - easy to implement. ++ - the atomic behavaiour is lost. ++ - to open a file with superuser's credential and give it to a user ++ process is a bad idea, since the file object keeps the credential ++ in it. It may affect LSM or something. This approach doesn't work ++ either. ++ ++The approach A is ideal, but it hard to implement. So here is a ++variation of A, which is to be implemented. ++ ++A-1. Introduce aufs_atomic_open() ++ - calls branch fs ->atomic_open() if exists. otherwise calls ++ vfs_create() and finish_open(). ++ - the demerit is that the several checks after branch fs ++ ->atomic_open() are lost. in the ordinary case, the checks are ++ done by VFS:do_last(), lookup_open() and atomic_open(). some can ++ be implemented in aufs, but not all I am afraid. +diff -Nurp linux-5.4/Documentation/filesystems/aufs/design/03lookup.txt linux-5.4-aufs/Documentation/filesystems/aufs/design/03lookup.txt +--- linux-5.4/Documentation/filesystems/aufs/design/03lookup.txt 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/Documentation/filesystems/aufs/design/03lookup.txt 2019-11-28 01:25:59.060925618 +0200 +@@ -0,0 +1,100 @@ ++ ++# Copyright (C) 2005-2019 Junjiro R. Okajima ++ ++Lookup in a Branch ++---------------------------------------------------------------------- ++Since aufs has a character of sub-VFS (see Introduction), it operates ++lookup for branches as VFS does. It may be a heavy work. But almost all ++lookup operation in aufs is the simplest case, ie. lookup only an entry ++directly connected to its parent. Digging down the directory hierarchy ++is unnecessary. VFS has a function lookup_one_len() for that use, and ++aufs calls it. ++ ++When a branch is a remote filesystem, aufs basically relies upon its ++->d_revalidate(), also aufs forces the hardest revalidate tests for ++them. ++For d_revalidate, aufs implements three levels of revalidate tests. See ++"Revalidate Dentry and UDBA" in detail. ++ ++ ++Test Only the Highest One for the Directory Permission (dirperm1 option) ++---------------------------------------------------------------------- ++Let's try case study. ++- aufs has two branches, upper readwrite and lower readonly. ++ /au = /rw + /ro ++- "dirA" exists under /ro, but /rw. and its mode is 0700. ++- user invoked "chmod a+rx /au/dirA" ++- the internal copy-up is activated and "/rw/dirA" is created and its ++ permission bits are set to world readable. ++- then "/au/dirA" becomes world readable? ++ ++In this case, /ro/dirA is still 0700 since it exists in readonly branch, ++or it may be a natively readonly filesystem. If aufs respects the lower ++branch, it should not respond readdir request from other users. But user ++allowed it by chmod. Should really aufs rejects showing the entries ++under /ro/dirA? ++ ++To be honest, I don't have a good solution for this case. So aufs ++implements 'dirperm1' and 'nodirperm1' mount options, and leave it to ++users. ++When dirperm1 is specified, aufs checks only the highest one for the ++directory permission, and shows the entries. Otherwise, as usual, checks ++every dir existing on all branches and rejects the request. ++ ++As a side effect, dirperm1 option improves the performance of aufs ++because the number of permission check is reduced when the number of ++branch is many. ++ ++ ++Revalidate Dentry and UDBA (User's Direct Branch Access) ++---------------------------------------------------------------------- ++Generally VFS helpers re-validate a dentry as a part of lookup. ++0. digging down the directory hierarchy. ++1. lock the parent dir by its i_mutex. ++2. lookup the final (child) entry. ++3. revalidate it. ++4. call the actual operation (create, unlink, etc.) ++5. unlock the parent dir ++ ++If the filesystem implements its ->d_revalidate() (step 3), then it is ++called. Actually aufs implements it and checks the dentry on a branch is ++still valid. ++But it is not enough. Because aufs has to release the lock for the ++parent dir on a branch at the end of ->lookup() (step 2) and ++->d_revalidate() (step 3) while the i_mutex of the aufs dir is still ++held by VFS. ++If the file on a branch is changed directly, eg. bypassing aufs, after ++aufs released the lock, then the subsequent operation may cause ++something unpleasant result. ++ ++This situation is a result of VFS architecture, ->lookup() and ++->d_revalidate() is separated. But I never say it is wrong. It is a good ++design from VFS's point of view. It is just not suitable for sub-VFS ++character in aufs. ++ ++Aufs supports such case by three level of revalidation which is ++selectable by user. ++1. Simple Revalidate ++ Addition to the native flow in VFS's, confirm the child-parent ++ relationship on the branch just after locking the parent dir on the ++ branch in the "actual operation" (step 4). When this validation ++ fails, aufs returns EBUSY. ->d_revalidate() (step 3) in aufs still ++ checks the validation of the dentry on branches. ++2. Monitor Changes Internally by Inotify/Fsnotify ++ Addition to above, in the "actual operation" (step 4) aufs re-lookup ++ the dentry on the branch, and returns EBUSY if it finds different ++ dentry. ++ Additionally, aufs sets the inotify/fsnotify watch for every dir on branches ++ during it is in cache. When the event is notified, aufs registers a ++ function to kernel 'events' thread by schedule_work(). And the ++ function sets some special status to the cached aufs dentry and inode ++ private data. If they are not cached, then aufs has nothing to ++ do. When the same file is accessed through aufs (step 0-3) later, ++ aufs will detect the status and refresh all necessary data. ++ In this mode, aufs has to ignore the event which is fired by aufs ++ itself. ++3. No Extra Validation ++ This is the simplest test and doesn't add any additional revalidation ++ test, and skip the revalidation in step 4. It is useful and improves ++ aufs performance when system surely hide the aufs branches from user, ++ by over-mounting something (or another method). +diff -Nurp linux-5.4/Documentation/filesystems/aufs/design/04branch.txt linux-5.4-aufs/Documentation/filesystems/aufs/design/04branch.txt +--- linux-5.4/Documentation/filesystems/aufs/design/04branch.txt 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/Documentation/filesystems/aufs/design/04branch.txt 2019-11-28 01:25:59.060925618 +0200 +@@ -0,0 +1,61 @@ ++ ++# Copyright (C) 2005-2019 Junjiro R. Okajima ++ ++Branch Manipulation ++ ++Since aufs supports dynamic branch manipulation, ie. add/remove a branch ++and changing its permission/attribute, there are a lot of works to do. ++ ++ ++Add a Branch ++---------------------------------------------------------------------- ++o Confirm the adding dir exists outside of aufs, including loopback ++ mount, and its various attributes. ++o Initialize the xino file and whiteout bases if necessary. ++ See struct.txt. ++ ++o Check the owner/group/mode of the directory ++ When the owner/group/mode of the adding directory differs from the ++ existing branch, aufs issues a warning because it may impose a ++ security risk. ++ For example, when a upper writable branch has a world writable empty ++ top directory, a malicious user can create any files on the writable ++ branch directly, like copy-up and modify manually. If something like ++ /etc/{passwd,shadow} exists on the lower readonly branch but the upper ++ writable branch, and the writable branch is world-writable, then a ++ malicious guy may create /etc/passwd on the writable branch directly ++ and the infected file will be valid in aufs. ++ I am afraid it can be a security issue, but aufs can do nothing except ++ producing a warning. ++ ++ ++Delete a Branch ++---------------------------------------------------------------------- ++o Confirm the deleting branch is not busy ++ To be general, there is one merit to adopt "remount" interface to ++ manipulate branches. It is to discard caches. At deleting a branch, ++ aufs checks the still cached (and connected) dentries and inodes. If ++ there are any, then they are all in-use. An inode without its ++ corresponding dentry can be alive alone (for example, inotify/fsnotify case). ++ ++ For the cached one, aufs checks whether the same named entry exists on ++ other branches. ++ If the cached one is a directory, because aufs provides a merged view ++ to users, as long as one dir is left on any branch aufs can show the ++ dir to users. In this case, the branch can be removed from aufs. ++ Otherwise aufs rejects deleting the branch. ++ ++ If any file on the deleting branch is opened by aufs, then aufs ++ rejects deleting. ++ ++ ++Modify the Permission of a Branch ++---------------------------------------------------------------------- ++o Re-initialize or remove the xino file and whiteout bases if necessary. ++ See struct.txt. ++ ++o rw --> ro: Confirm the modifying branch is not busy ++ Aufs rejects the request if any of these conditions are true. ++ - a file on the branch is mmap-ed. ++ - a regular file on the branch is opened for write and there is no ++ same named entry on the upper branch. +diff -Nurp linux-5.4/Documentation/filesystems/aufs/design/05wbr_policy.txt linux-5.4-aufs/Documentation/filesystems/aufs/design/05wbr_policy.txt +--- linux-5.4/Documentation/filesystems/aufs/design/05wbr_policy.txt 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/Documentation/filesystems/aufs/design/05wbr_policy.txt 2019-11-28 01:25:59.060925618 +0200 +@@ -0,0 +1,51 @@ ++ ++# Copyright (C) 2005-2019 Junjiro R. Okajima ++ ++Policies to Select One among Multiple Writable Branches ++---------------------------------------------------------------------- ++When the number of writable branch is more than one, aufs has to decide ++the target branch for file creation or copy-up. By default, the highest ++writable branch which has the parent (or ancestor) dir of the target ++file is chosen (top-down-parent policy). ++By user's request, aufs implements some other policies to select the ++writable branch, for file creation several policies, round-robin, ++most-free-space, and other policies. For copy-up, top-down-parent, ++bottom-up-parent, bottom-up and others. ++ ++As expected, the round-robin policy selects the branch in circular. When ++you have two writable branches and creates 10 new files, 5 files will be ++created for each branch. mkdir(2) systemcall is an exception. When you ++create 10 new directories, all will be created on the same branch. ++And the most-free-space policy selects the one which has most free ++space among the writable branches. The amount of free space will be ++checked by aufs internally, and users can specify its time interval. ++ ++The policies for copy-up is more simple, ++top-down-parent is equivalent to the same named on in create policy, ++bottom-up-parent selects the writable branch where the parent dir ++exists and the nearest upper one from the copyup-source, ++bottom-up selects the nearest upper writable branch from the ++copyup-source, regardless the existence of the parent dir. ++ ++There are some rules or exceptions to apply these policies. ++- If there is a readonly branch above the policy-selected branch and ++ the parent dir is marked as opaque (a variation of whiteout), or the ++ target (creating) file is whiteout-ed on the upper readonly branch, ++ then the result of the policy is ignored and the target file will be ++ created on the nearest upper writable branch than the readonly branch. ++- If there is a writable branch above the policy-selected branch and ++ the parent dir is marked as opaque or the target file is whiteouted ++ on the branch, then the result of the policy is ignored and the target ++ file will be created on the highest one among the upper writable ++ branches who has diropq or whiteout. In case of whiteout, aufs removes ++ it as usual. ++- link(2) and rename(2) systemcalls are exceptions in every policy. ++ They try selecting the branch where the source exists as possible ++ since copyup a large file will take long time. If it can't be, ++ ie. the branch where the source exists is readonly, then they will ++ follow the copyup policy. ++- There is an exception for rename(2) when the target exists. ++ If the rename target exists, aufs compares the index of the branches ++ where the source and the target exists and selects the higher ++ one. If the selected branch is readonly, then aufs follows the ++ copyup policy. +diff -Nurp linux-5.4/Documentation/filesystems/aufs/design/06dirren.dot linux-5.4-aufs/Documentation/filesystems/aufs/design/06dirren.dot +--- linux-5.4/Documentation/filesystems/aufs/design/06dirren.dot 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/Documentation/filesystems/aufs/design/06dirren.dot 2019-11-28 01:25:59.060925618 +0200 +@@ -0,0 +1,31 @@ ++ ++// to view this graph, run dot(1) command in GRAPHVIZ. ++ ++digraph G { ++node [shape=box]; ++whinfo [label="detailed info file\n(lower_brid_root-hinum, h_inum, namelen, old name)"]; ++ ++node [shape=oval]; ++ ++aufs_rename -> whinfo [label="store/remove"]; ++ ++node [shape=oval]; ++inode_list [label="h_inum list in branch\ncache"]; ++ ++node [shape=box]; ++whinode [label="h_inum list file"]; ++ ++node [shape=oval]; ++brmgmt [label="br_add/del/mod/umount"]; ++ ++brmgmt -> inode_list [label="create/remove"]; ++brmgmt -> whinode [label="load/store"]; ++ ++inode_list -> whinode [style=dashed,dir=both]; ++ ++aufs_rename -> inode_list [label="add/del"]; ++ ++aufs_lookup -> inode_list [label="search"]; ++ ++aufs_lookup -> whinfo [label="load/remove"]; ++} +diff -Nurp linux-5.4/Documentation/filesystems/aufs/design/06dirren.txt linux-5.4-aufs/Documentation/filesystems/aufs/design/06dirren.txt +--- linux-5.4/Documentation/filesystems/aufs/design/06dirren.txt 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/Documentation/filesystems/aufs/design/06dirren.txt 2019-11-28 01:25:59.060925618 +0200 +@@ -0,0 +1,89 @@ ++ ++# Copyright (C) 2017-2019 Junjiro R. Okajima ++ ++Special handling for renaming a directory (DIRREN) ++---------------------------------------------------------------------- ++First, let's assume we have a simple usecase. ++ ++- /u = /rw + /ro ++- /rw/dirA exists ++- /ro/dirA and /ro/dirA/file exist too ++- there is no dirB on both branches ++- a user issues rename("dirA", "dirB") ++ ++Now, what should aufs behave against this rename(2)? ++There are a few possible cases. ++ ++A. returns EROFS. ++ since dirA exists on a readonly branch which cannot be renamed. ++B. returns EXDEV. ++ it is possible to copy-up dirA (only the dir itself), but the child ++ entries ("file" in this case) should not be. it must be a bad ++ approach to copy-up recursively. ++C. returns a success. ++ even the branch /ro is readonly, aufs tries renaming it. Obviously it ++ is a violation of aufs' policy. ++D. construct an extra information which indicates that /ro/dirA should ++ be handled as the name of dirB. ++ overlayfs has a similar feature called REDIRECT. ++ ++Until now, aufs implements the case B only which returns EXDEV, and ++expects the userspace application behaves like mv(1) which tries ++issueing rename(2) recursively. ++ ++A new aufs feature called DIRREN is introduced which implements the case ++D. There are several "extra information" added. ++ ++1. detailed info per renamed directory ++ path: /rw/dirB/$AUFS_WH_DR_INFO_PFX. ++2. the inode-number list of directories on a branch ++ path: /rw/dirB/$AUFS_WH_DR_BRHINO ++ ++The filename of "detailed info per directory" represents the lower ++branch, and its format is ++- a type of the branch id ++ one of these. ++ + uuid (not implemented yet) ++ + fsid ++ + dev ++- the inode-number of the branch root dir ++ ++And it contains these info in a single regular file. ++- magic number ++- branch's inode-number of the logically renamed dir ++- the name of the before-renamed dir ++ ++The "detailed info per directory" file is created in aufs rename(2), and ++loaded in any lookup. ++The info is considered in lookup for the matching case only. Here ++"matching" means that the root of branch (in the info filename) is same ++to the current looking-up branch. After looking-up the before-renamed ++name, the inode-number is compared. And the matched dentry is used. ++ ++The "inode-number list of directories" is a regular file which contains ++simply the inode-numbers on the branch. The file is created or updated ++in removing the branch, and loaded in adding the branch. Its lifetime is ++equal to the branch. ++The list is refered in lookup, and when the current target inode is ++found in the list, the aufs tries loading the "detailed info per ++directory" and get the changed and valid name of the dir. ++ ++Theoretically these "extra informaiton" may be able to be put into XATTR ++in the dir inode. But aufs doesn't choose this way because ++1. XATTR may not be supported by the branch (or its configuration) ++2. XATTR may have its size limit. ++3. XATTR may be less easy to convert than a regular file, when the ++ format of the info is changed in the future. ++At the same time, I agree that the regular file approach is much slower ++than XATTR approach. So, in the future, aufs may take the XATTR or other ++better approach. ++ ++This DIRREN feature is enabled by aufs configuration, and is activated ++by a new mount option. ++ ++For the more complicated case, there is a work with UDBA option, which ++is to dected the direct access to the branches (by-passing aufs) and to ++maintain the cashes in aufs. Since a single cached aufs dentry may ++contains two names, before- and after-rename, the name comparision in ++UDBA handler may not work correctly. In this case, the behaviour will be ++equivalen to udba=reval case. +diff -Nurp linux-5.4/Documentation/filesystems/aufs/design/06fhsm.txt linux-5.4-aufs/Documentation/filesystems/aufs/design/06fhsm.txt +--- linux-5.4/Documentation/filesystems/aufs/design/06fhsm.txt 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/Documentation/filesystems/aufs/design/06fhsm.txt 2019-11-28 01:25:59.060925618 +0200 +@@ -0,0 +1,105 @@ ++ ++# Copyright (C) 2011-2019 Junjiro R. Okajima ++ ++File-based Hierarchical Storage Management (FHSM) ++---------------------------------------------------------------------- ++Hierarchical Storage Management (or HSM) is a well-known feature in the ++storage world. Aufs provides this feature as file-based with multiple ++writable branches, based upon the principle of "Colder, the Lower". ++Here the word "colder" means that the less used files, and "lower" means ++that the position in the order of the stacked branches vertically. ++These multiple writable branches are prioritized, ie. the topmost one ++should be the fastest drive and be used heavily. ++ ++o Characters in aufs FHSM story ++- aufs itself and a new branch attribute. ++- a new ioctl interface to move-down and to establish a connection with ++ the daemon ("move-down" is a converse of "copy-up"). ++- userspace tool and daemon. ++ ++The userspace daemon establishes a connection with aufs and waits for ++the notification. The notified information is very similar to struct ++statfs containing the number of consumed blocks and inodes. ++When the consumed blocks/inodes of a branch exceeds the user-specified ++upper watermark, the daemon activates its move-down process until the ++consumed blocks/inodes reaches the user-specified lower watermark. ++ ++The actual move-down is done by aufs based upon the request from ++user-space since we need to maintain the inode number and the internal ++pointer arrays in aufs. ++ ++Currently aufs FHSM handles the regular files only. Additionally they ++must not be hard-linked nor pseudo-linked. ++ ++ ++o Cowork of aufs and the user-space daemon ++ During the userspace daemon established the connection, aufs sends a ++ small notification to it whenever aufs writes something into the ++ writable branch. But it may cost high since aufs issues statfs(2) ++ internally. So user can specify a new option to cache the ++ info. Actually the notification is controlled by these factors. ++ + the specified cache time. ++ + classified as "force" by aufs internally. ++ Until the specified time expires, aufs doesn't send the info ++ except the forced cases. When aufs decide forcing, the info is always ++ notified to userspace. ++ For example, the number of free inodes is generally large enough and ++ the shortage of it happens rarely. So aufs doesn't force the ++ notification when creating a new file, directory and others. This is ++ the typical case which aufs doesn't force. ++ When aufs writes the actual filedata and the files consumes any of new ++ blocks, the aufs forces notifying. ++ ++ ++o Interfaces in aufs ++- New branch attribute. ++ + fhsm ++ Specifies that the branch is managed by FHSM feature. In other word, ++ participant in the FHSM. ++ When nofhsm is set to the branch, it will not be the source/target ++ branch of the move-down operation. This attribute is set ++ independently from coo and moo attributes, and if you want full ++ FHSM, you should specify them as well. ++- New mount option. ++ + fhsm_sec ++ Specifies a second to suppress many less important info to be ++ notified. ++- New ioctl. ++ + AUFS_CTL_FHSM_FD ++ create a new file descriptor which userspace can read the notification ++ (a subset of struct statfs) from aufs. ++- Module parameter 'brs' ++ It has to be set to 1. Otherwise the new mount option 'fhsm' will not ++ be set. ++- mount helpers /sbin/mount.aufs and /sbin/umount.aufs ++ When there are two or more branches with fhsm attributes, ++ /sbin/mount.aufs invokes the user-space daemon and /sbin/umount.aufs ++ terminates it. As a result of remounting and branch-manipulation, the ++ number of branches with fhsm attribute can be one. In this case, ++ /sbin/mount.aufs will terminate the user-space daemon. ++ ++ ++Finally the operation is done as these steps in kernel-space. ++- make sure that, ++ + no one else is using the file. ++ + the file is not hard-linked. ++ + the file is not pseudo-linked. ++ + the file is a regular file. ++ + the parent dir is not opaqued. ++- find the target writable branch. ++- make sure the file is not whiteout-ed by the upper (than the target) ++ branch. ++- make the parent dir on the target branch. ++- mutex lock the inode on the branch. ++- unlink the whiteout on the target branch (if exists). ++- lookup and create the whiteout-ed temporary name on the target branch. ++- copy the file as the whiteout-ed temporary name on the target branch. ++- rename the whiteout-ed temporary name to the original name. ++- unlink the file on the source branch. ++- maintain the internal pointer array and the external inode number ++ table (XINO). ++- maintain the timestamps and other attributes of the parent dir and the ++ file. ++ ++And of course, in every step, an error may happen. So the operation ++should restore the original file state after an error happens. +diff -Nurp linux-5.4/Documentation/filesystems/aufs/design/06mmap.txt linux-5.4-aufs/Documentation/filesystems/aufs/design/06mmap.txt +--- linux-5.4/Documentation/filesystems/aufs/design/06mmap.txt 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/Documentation/filesystems/aufs/design/06mmap.txt 2019-11-28 01:25:59.060925618 +0200 +@@ -0,0 +1,59 @@ ++ ++# Copyright (C) 2005-2019 Junjiro R. Okajima ++ ++mmap(2) -- File Memory Mapping ++---------------------------------------------------------------------- ++In aufs, the file-mapped pages are handled by a branch fs directly, no ++interaction with aufs. It means aufs_mmap() calls the branch fs's ++->mmap(). ++This approach is simple and good, but there is one problem. ++Under /proc, several entries show the mmapped files by its path (with ++device and inode number), and the printed path will be the path on the ++branch fs's instead of virtual aufs's. ++This is not a problem in most cases, but some utilities lsof(1) (and its ++user) may expect the path on aufs. ++ ++To address this issue, aufs adds a new member called vm_prfile in struct ++vm_area_struct (and struct vm_region). The original vm_file points to ++the file on the branch fs in order to handle everything correctly as ++usual. The new vm_prfile points to a virtual file in aufs, and the ++show-functions in procfs refers to vm_prfile if it is set. ++Also we need to maintain several other places where touching vm_file ++such like ++- fork()/clone() copies vma and the reference count of vm_file is ++ incremented. ++- merging vma maintains the ref count too. ++ ++This is not a good approach. It just fakes the printed path. But it ++leaves all behaviour around f_mapping unchanged. This is surely an ++advantage. ++Actually aufs had adopted another complicated approach which calls ++generic_file_mmap() and handles struct vm_operations_struct. In this ++approach, aufs met a hard problem and I could not solve it without ++switching the approach. ++ ++There may be one more another approach which is ++- bind-mount the branch-root onto the aufs-root internally ++- grab the new vfsmount (ie. struct mount) ++- lazy-umount the branch-root internally ++- in open(2) the aufs-file, open the branch-file with the hidden ++ vfsmount (instead of the original branch's vfsmount) ++- ideally this "bind-mount and lazy-umount" should be done atomically, ++ but it may be possible from userspace by the mount helper. ++ ++Adding the internal hidden vfsmount and using it in opening a file, the ++file path under /proc will be printed correctly. This approach looks ++smarter, but is not possible I am afraid. ++- aufs-root may be bind-mount later. when it happens, another hidden ++ vfsmount will be required. ++- it is hard to get the chance to bind-mount and lazy-umount ++ + in kernel-space, FS can have vfsmount in open(2) via ++ file->f_path, and aufs can know its vfsmount. But several locks are ++ already acquired, and if aufs tries to bind-mount and lazy-umount ++ here, then it may cause a deadlock. ++ + in user-space, bind-mount doesn't invoke the mount helper. ++- since /proc shows dev and ino, aufs has to give vma these info. it ++ means a new member vm_prinode will be necessary. this is essentially ++ equivalent to vm_prfile described above. ++ ++I have to give up this "looks-smater" approach. +diff -Nurp linux-5.4/Documentation/filesystems/aufs/design/06xattr.txt linux-5.4-aufs/Documentation/filesystems/aufs/design/06xattr.txt +--- linux-5.4/Documentation/filesystems/aufs/design/06xattr.txt 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/Documentation/filesystems/aufs/design/06xattr.txt 2019-11-28 01:25:59.060925618 +0200 +@@ -0,0 +1,81 @@ ++ ++# Copyright (C) 2014-2019 Junjiro R. Okajima ++ ++Listing XATTR/EA and getting the value ++---------------------------------------------------------------------- ++For the inode standard attributes (owner, group, timestamps, etc.), aufs ++shows the values from the topmost existing file. This behaviour is good ++for the non-dir entries since the bahaviour exactly matches the shown ++information. But for the directories, aufs considers all the same named ++entries on the lower branches. Which means, if one of the lower entry ++rejects readdir call, then aufs returns an error even if the topmost ++entry allows it. This behaviour is necessary to respect the branch fs's ++security, but can make users confused since the user-visible standard ++attributes don't match the behaviour. ++To address this issue, aufs has a mount option called dirperm1 which ++checks the permission for the topmost entry only, and ignores the lower ++entry's permission. ++ ++A similar issue can happen around XATTR. ++getxattr(2) and listxattr(2) families behave as if dirperm1 option is ++always set. Otherwise these very unpleasant situation would happen. ++- listxattr(2) may return the duplicated entries. ++- users may not be able to remove or reset the XATTR forever, ++ ++ ++XATTR/EA support in the internal (copy,move)-(up,down) ++---------------------------------------------------------------------- ++Generally the extended attributes of inode are categorized as these. ++- "security" for LSM and capability. ++- "system" for posix ACL, 'acl' mount option is required for the branch ++ fs generally. ++- "trusted" for userspace, CAP_SYS_ADMIN is required. ++- "user" for userspace, 'user_xattr' mount option is required for the ++ branch fs generally. ++ ++Moreover there are some other categories. Aufs handles these rather ++unpopular categories as the ordinary ones, ie. there is no special ++condition nor exception. ++ ++In copy-up, the support for XATTR on the dst branch may differ from the ++src branch. In this case, the copy-up operation will get an error and ++the original user operation which triggered the copy-up will fail. It ++can happen that even all copy-up will fail. ++When both of src and dst branches support XATTR and if an error occurs ++during copying XATTR, then the copy-up should fail obviously. That is a ++good reason and aufs should return an error to userspace. But when only ++the src branch support that XATTR, aufs should not return an error. ++For example, the src branch supports ACL but the dst branch doesn't ++because the dst branch may natively un-support it or temporary ++un-support it due to "noacl" mount option. Of course, the dst branch fs ++may NOT return an error even if the XATTR is not supported. It is ++totally up to the branch fs. ++ ++Anyway when the aufs internal copy-up gets an error from the dst branch ++fs, then aufs tries removing the just copied entry and returns the error ++to the userspace. The worst case of this situation will be all copy-up ++will fail. ++ ++For the copy-up operation, there two basic approaches. ++- copy the specified XATTR only (by category above), and return the ++ error unconditionally if it happens. ++- copy all XATTR, and ignore the error on the specified category only. ++ ++In order to support XATTR and to implement the correct behaviour, aufs ++chooses the latter approach and introduces some new branch attributes, ++"icexsec", "icexsys", "icextr", "icexusr", and "icexoth". ++They correspond to the XATTR namespaces (see above). Additionally, to be ++convenient, "icex" is also provided which means all "icex*" attributes ++are set (here the word "icex" stands for "ignore copy-error on XATTR"). ++ ++The meaning of these attributes is to ignore the error from setting ++XATTR on that branch. ++Note that aufs tries copying all XATTR unconditionally, and ignores the ++error from the dst branch according to the specified attributes. ++ ++Some XATTR may have its default value. The default value may come from ++the parent dir or the environment. If the default value is set at the ++file creating-time, it will be overwritten by copy-up. ++Some contradiction may happen I am afraid. ++Do we need another attribute to stop copying XATTR? I am unsure. For ++now, aufs implements the branch attributes to ignore the error. +diff -Nurp linux-5.4/Documentation/filesystems/aufs/design/07export.txt linux-5.4-aufs/Documentation/filesystems/aufs/design/07export.txt +--- linux-5.4/Documentation/filesystems/aufs/design/07export.txt 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/Documentation/filesystems/aufs/design/07export.txt 2019-11-28 01:25:59.060925618 +0200 +@@ -0,0 +1,45 @@ ++ ++# Copyright (C) 2005-2019 Junjiro R. Okajima ++ ++Export Aufs via NFS ++---------------------------------------------------------------------- ++Here is an approach. ++- like xino/xib, add a new file 'xigen' which stores aufs inode ++ generation. ++- iget_locked(): initialize aufs inode generation for a new inode, and ++ store it in xigen file. ++- destroy_inode(): increment aufs inode generation and store it in xigen ++ file. it is necessary even if it is not unlinked, because any data of ++ inode may be changed by UDBA. ++- encode_fh(): for a root dir, simply return FILEID_ROOT. otherwise ++ build file handle by ++ + branch id (4 bytes) ++ + superblock generation (4 bytes) ++ + inode number (4 or 8 bytes) ++ + parent dir inode number (4 or 8 bytes) ++ + inode generation (4 bytes)) ++ + return value of exportfs_encode_fh() for the parent on a branch (4 ++ bytes) ++ + file handle for a branch (by exportfs_encode_fh()) ++- fh_to_dentry(): ++ + find the index of a branch from its id in handle, and check it is ++ still exist in aufs. ++ + 1st level: get the inode number from handle and search it in cache. ++ + 2nd level: if not found in cache, get the parent inode number from ++ the handle and search it in cache. and then open the found parent ++ dir, find the matching inode number by vfs_readdir() and get its ++ name, and call lookup_one_len() for the target dentry. ++ + 3rd level: if the parent dir is not cached, call ++ exportfs_decode_fh() for a branch and get the parent on a branch, ++ build a pathname of it, convert it a pathname in aufs, call ++ path_lookup(). now aufs gets a parent dir dentry, then handle it as ++ the 2nd level. ++ + to open the dir, aufs needs struct vfsmount. aufs keeps vfsmount ++ for every branch, but not itself. to get this, (currently) aufs ++ searches in current->nsproxy->mnt_ns list. it may not be a good ++ idea, but I didn't get other approach. ++ + test the generation of the gotten inode. ++- every inode operation: they may get EBUSY due to UDBA. in this case, ++ convert it into ESTALE for NFSD. ++- readdir(): call lockdep_on/off() because filldir in NFSD calls ++ lookup_one_len(), vfs_getattr(), encode_fh() and others. +diff -Nurp linux-5.4/Documentation/filesystems/aufs/design/08shwh.txt linux-5.4-aufs/Documentation/filesystems/aufs/design/08shwh.txt +--- linux-5.4/Documentation/filesystems/aufs/design/08shwh.txt 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/Documentation/filesystems/aufs/design/08shwh.txt 2019-11-28 01:25:59.060925618 +0200 +@@ -0,0 +1,39 @@ ++ ++# Copyright (C) 2005-2019 Junjiro R. Okajima ++ ++Show Whiteout Mode (shwh) ++---------------------------------------------------------------------- ++Generally aufs hides the name of whiteouts. But in some cases, to show ++them is very useful for users. For instance, creating a new middle layer ++(branch) by merging existing layers. ++ ++(borrowing aufs1 HOW-TO from a user, Michael Towers) ++When you have three branches, ++- Bottom: 'system', squashfs (underlying base system), read-only ++- Middle: 'mods', squashfs, read-only ++- Top: 'overlay', ram (tmpfs), read-write ++ ++The top layer is loaded at boot time and saved at shutdown, to preserve ++the changes made to the system during the session. ++When larger changes have been made, or smaller changes have accumulated, ++the size of the saved top layer data grows. At this point, it would be ++nice to be able to merge the two overlay branches ('mods' and 'overlay') ++and rewrite the 'mods' squashfs, clearing the top layer and thus ++restoring save and load speed. ++ ++This merging is simplified by the use of another aufs mount, of just the ++two overlay branches using the 'shwh' option. ++# mount -t aufs -o ro,shwh,br:/livesys/overlay=ro+wh:/livesys/mods=rr+wh \ ++ aufs /livesys/merge_union ++ ++A merged view of these two branches is then available at ++/livesys/merge_union, and the new feature is that the whiteouts are ++visible! ++Note that in 'shwh' mode the aufs mount must be 'ro', which will disable ++writing to all branches. Also the default mode for all branches is 'ro'. ++It is now possible to save the combined contents of the two overlay ++branches to a new squashfs, e.g.: ++# mksquashfs /livesys/merge_union /path/to/newmods.squash ++ ++This new squashfs archive can be stored on the boot device and the ++initramfs will use it to replace the old one at the next boot. +diff -Nurp linux-5.4/Documentation/filesystems/aufs/design/10dynop.txt linux-5.4-aufs/Documentation/filesystems/aufs/design/10dynop.txt +--- linux-5.4/Documentation/filesystems/aufs/design/10dynop.txt 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/Documentation/filesystems/aufs/design/10dynop.txt 2019-11-28 01:25:59.060925618 +0200 +@@ -0,0 +1,34 @@ ++ ++# Copyright (C) 2010-2019 Junjiro R. Okajima ++ ++Dynamically customizable FS operations ++---------------------------------------------------------------------- ++Generally FS operations (struct inode_operations, struct ++address_space_operations, struct file_operations, etc.) are defined as ++"static const", but it never means that FS have only one set of ++operation. Some FS have multiple sets of them. For instance, ext2 has ++three sets, one for XIP, for NOBH, and for normal. ++Since aufs overrides and redirects these operations, sometimes aufs has ++to change its behaviour according to the branch FS type. More importantly ++VFS acts differently if a function (member in the struct) is set or ++not. It means aufs should have several sets of operations and select one ++among them according to the branch FS definition. ++ ++In order to solve this problem and not to affect the behaviour of VFS, ++aufs defines these operations dynamically. For instance, aufs defines ++dummy direct_IO function for struct address_space_operations, but it may ++not be set to the address_space_operations actually. When the branch FS ++doesn't have it, aufs doesn't set it to its address_space_operations ++while the function definition itself is still alive. So the behaviour ++itself will not change, and it will return an error when direct_IO is ++not set. ++ ++The lifetime of these dynamically generated operation object is ++maintained by aufs branch object. When the branch is removed from aufs, ++the reference counter of the object is decremented. When it reaches ++zero, the dynamically generated operation object will be freed. ++ ++This approach is designed to support AIO (io_submit), Direct I/O and ++XIP (DAX) mainly. ++Currently this approach is applied to address_space_operations for ++regular files only. +diff -Nurp linux-5.4/Documentation/filesystems/aufs/README linux-5.4-aufs/Documentation/filesystems/aufs/README +--- linux-5.4/Documentation/filesystems/aufs/README 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/Documentation/filesystems/aufs/README 2019-11-28 01:25:59.060925618 +0200 +@@ -0,0 +1,399 @@ ++ ++Aufs5 -- advanced multi layered unification filesystem version 5.x ++http://aufs.sf.net ++Junjiro R. Okajima ++ ++ ++0. Introduction ++---------------------------------------- ++In the early days, aufs was entirely re-designed and re-implemented ++Unionfs Version 1.x series. Adding many original ideas, approaches, ++improvements and implementations, it became totally different from ++Unionfs while keeping the basic features. ++Later, Unionfs Version 2.x series began taking some of the same ++approaches to aufs1's. ++Unionfs was being developed by Professor Erez Zadok at Stony Brook ++University and his team. ++ ++Aufs5 supports linux-v5.0 and later, If you want older kernel version ++support, ++- for linux-v4.x series, try aufs4-linux.git or aufs4-standalone.git ++- for linux-v3.x series, try aufs3-linux.git or aufs3-standalone.git ++- for linux-v2.6.16 and later, try aufs2-2.6.git, aufs2-standalone.git ++ or aufs1 from CVS on SourceForge. ++ ++Note: it becomes clear that "Aufs was rejected. Let's give it up." ++ According to Christoph Hellwig, linux rejects all union-type ++ filesystems but UnionMount. ++ ++ ++PS. Al Viro seems have a plan to merge aufs as well as overlayfs and ++ UnionMount, and he pointed out an issue around a directory mutex ++ lock and aufs addressed it. But it is still unsure whether aufs will ++ be merged (or any other union solution). ++ ++ ++ ++1. Features ++---------------------------------------- ++- unite several directories into a single virtual filesystem. The member ++ directory is called as a branch. ++- you can specify the permission flags to the branch, which are 'readonly', ++ 'readwrite' and 'whiteout-able.' ++- by upper writable branch, internal copyup and whiteout, files/dirs on ++ readonly branch are modifiable logically. ++- dynamic branch manipulation, add, del. ++- etc... ++ ++Also there are many enhancements in aufs, such as: ++- test only the highest one for the directory permission (dirperm1) ++- copyup on open (coo=) ++- 'move' policy for copy-up between two writable branches, after ++ checking free space. ++- xattr, acl ++- readdir(3) in userspace. ++- keep inode number by external inode number table ++- keep the timestamps of file/dir in internal copyup operation ++- seekable directory, supporting NFS readdir. ++- whiteout is hardlinked in order to reduce the consumption of inodes ++ on branch ++- do not copyup, nor create a whiteout when it is unnecessary ++- revert a single systemcall when an error occurs in aufs ++- remount interface instead of ioctl ++- maintain /etc/mtab by an external command, /sbin/mount.aufs. ++- loopback mounted filesystem as a branch ++- kernel thread for removing the dir who has a plenty of whiteouts ++- support copyup sparse file (a file which has a 'hole' in it) ++- default permission flags for branches ++- selectable permission flags for ro branch, whether whiteout can ++ exist or not ++- export via NFS. ++- support /fs/aufs and /aufs. ++- support multiple writable branches, some policies to select one ++ among multiple writable branches. ++- a new semantics for link(2) and rename(2) to support multiple ++ writable branches. ++- no glibc changes are required. ++- pseudo hardlink (hardlink over branches) ++- allow a direct access manually to a file on branch, e.g. bypassing aufs. ++ including NFS or remote filesystem branch. ++- userspace wrapper for pathconf(3)/fpathconf(3) with _PC_LINK_MAX. ++- and more... ++ ++Currently these features are dropped temporary from aufs5. ++See design/08plan.txt in detail. ++- nested mount, i.e. aufs as readonly no-whiteout branch of another aufs ++ (robr) ++- statistics of aufs thread (/sys/fs/aufs/stat) ++ ++Features or just an idea in the future (see also design/*.txt), ++- reorder the branch index without del/re-add. ++- permanent xino files for NFSD ++- an option for refreshing the opened files after add/del branches ++- light version, without branch manipulation. (unnecessary?) ++- copyup in userspace ++- inotify in userspace ++- readv/writev ++ ++ ++2. Download ++---------------------------------------- ++There are three GIT trees for aufs5, aufs5-linux.git, ++aufs5-standalone.git, and aufs-util.git. Note that there is no "5" in ++"aufs-util.git." ++While the aufs-util is always necessary, you need either of aufs5-linux ++or aufs5-standalone. ++ ++The aufs5-linux tree includes the whole linux mainline GIT tree, ++git://git.kernel.org/.../torvalds/linux.git. ++And you cannot select CONFIG_AUFS_FS=m for this version, eg. you cannot ++build aufs5 as an external kernel module. ++Several extra patches are not included in this tree. Only ++aufs5-standalone tree contains them. They are described in the later ++section "Configuration and Compilation." ++ ++On the other hand, the aufs5-standalone tree has only aufs source files ++and necessary patches, and you can select CONFIG_AUFS_FS=m. ++But you need to apply all aufs patches manually. ++ ++You will find GIT branches whose name is in form of "aufs5.x" where "x" ++represents the linux kernel version, "linux-5.x". For instance, ++"aufs5.0" is for linux-5.0. For latest "linux-5.x-rcN", use ++"aufs5.x-rcN" branch. ++ ++o aufs5-linux tree ++$ git clone --reference /your/linux/git/tree \ ++ git://github.com/sfjro/aufs5-linux.git aufs5-linux.git ++- if you don't have linux GIT tree, then remove "--reference ..." ++$ cd aufs5-linux.git ++$ git checkout origin/aufs5.0 ++ ++Or You may want to directly git-pull aufs into your linux GIT tree, and ++leave the patch-work to GIT. ++$ cd /your/linux/git/tree ++$ git remote add aufs5 git://github.com/sfjro/aufs5-linux.git ++$ git fetch aufs5 ++$ git checkout -b my5.0 v5.0 ++$ (add your local change...) ++$ git pull aufs5 aufs5.0 ++- now you have v5.0 + your_changes + aufs5.0 in you my5.0 branch. ++- you may need to solve some conflicts between your_changes and ++ aufs5.0. in this case, git-rerere is recommended so that you can ++ solve the similar conflicts automatically when you upgrade to 5.1 or ++ later in the future. ++ ++o aufs5-standalone tree ++$ git clone git://github.com/sfjro/aufs5-standalone.git aufs5-standalone.git ++$ cd aufs5-standalone.git ++$ git checkout origin/aufs5.0 ++ ++o aufs-util tree ++$ git clone git://git.code.sf.net/p/aufs/aufs-util aufs-util.git ++- note that the public aufs-util.git is on SourceForge instead of ++ GitHUB. ++$ cd aufs-util.git ++$ git checkout origin/aufs5.0 ++ ++Note: The 5.x-rcN branch is to be used with `rc' kernel versions ONLY. ++The minor version number, 'x' in '5.x', of aufs may not always ++follow the minor version number of the kernel. ++Because changes in the kernel that cause the use of a new ++minor version number do not always require changes to aufs-util. ++ ++Since aufs-util has its own minor version number, you may not be ++able to find a GIT branch in aufs-util for your kernel's ++exact minor version number. ++In this case, you should git-checkout the branch for the ++nearest lower number. ++ ++For (an unreleased) example: ++If you are using "linux-5.10" and the "aufs5.10" branch ++does not exist in aufs-util repository, then "aufs5.9", "aufs5.8" ++or something numerically smaller is the branch for your kernel. ++ ++Also you can view all branches by ++ $ git branch -a ++ ++ ++3. Configuration and Compilation ++---------------------------------------- ++Make sure you have git-checkout'ed the correct branch. ++ ++For aufs5-linux tree, ++- enable CONFIG_AUFS_FS. ++- set other aufs configurations if necessary. ++ ++For aufs5-standalone tree, ++There are several ways to build. ++ ++1. ++- apply ./aufs5-kbuild.patch to your kernel source files. ++- apply ./aufs5-base.patch too. ++- apply ./aufs5-mmap.patch too. ++- apply ./aufs5-standalone.patch too, if you have a plan to set ++ CONFIG_AUFS_FS=m. otherwise you don't need ./aufs5-standalone.patch. ++- copy ./{Documentation,fs,include/uapi/linux/aufs_type.h} files to your ++ kernel source tree. Never copy $PWD/include/uapi/linux/Kbuild. ++- enable CONFIG_AUFS_FS, you can select either ++ =m or =y. ++- and build your kernel as usual. ++- install the built kernel. ++- install the header files too by "make headers_install" to the ++ directory where you specify. By default, it is $PWD/usr. ++ "make help" shows a brief note for headers_install. ++- and reboot your system. ++ ++2. ++- module only (CONFIG_AUFS_FS=m). ++- apply ./aufs5-base.patch to your kernel source files. ++- apply ./aufs5-mmap.patch too. ++- apply ./aufs5-standalone.patch too. ++- build your kernel, don't forget "make headers_install", and reboot. ++- edit ./config.mk and set other aufs configurations if necessary. ++ Note: You should read $PWD/fs/aufs/Kconfig carefully which describes ++ every aufs configurations. ++- build the module by simple "make". ++- you can specify ${KDIR} make variable which points to your kernel ++ source tree. ++- install the files ++ + run "make install" to install the aufs module, or copy the built ++ $PWD/aufs.ko to /lib/modules/... and run depmod -a (or reboot simply). ++ + run "make install_headers" (instead of headers_install) to install ++ the modified aufs header file (you can specify DESTDIR which is ++ available in aufs standalone version's Makefile only), or copy ++ $PWD/usr/include/linux/aufs_type.h to /usr/include/linux or wherever ++ you like manually. By default, the target directory is $PWD/usr. ++- no need to apply aufs5-kbuild.patch, nor copying source files to your ++ kernel source tree. ++ ++Note: The header file aufs_type.h is necessary to build aufs-util ++ as well as "make headers_install" in the kernel source tree. ++ headers_install is subject to be forgotten, but it is essentially ++ necessary, not only for building aufs-util. ++ You may not meet problems without headers_install in some older ++ version though. ++ ++And then, ++- read README in aufs-util, build and install it ++- note that your distribution may contain an obsoleted version of ++ aufs_type.h in /usr/include/linux or something. When you build aufs ++ utilities, make sure that your compiler refers the correct aufs header ++ file which is built by "make headers_install." ++- if you want to use readdir(3) in userspace or pathconf(3) wrapper, ++ then run "make install_ulib" too. And refer to the aufs manual in ++ detail. ++ ++There several other patches in aufs5-standalone.git. They are all ++optional. When you meet some problems, they will help you. ++- aufs5-loopback.patch ++ Supports a nested loopback mount in a branch-fs. This patch is ++ unnecessary until aufs produces a message like "you may want to try ++ another patch for loopback file". ++- proc_mounts.patch ++ When there are many mountpoints and many mount(2)/umount(2) are ++ running, then /proc/mounts may not show the all mountpoints. This ++ patch makes /proc/mounts always show the full mountpoints list. ++ If you don't want to apply this patch and meet such problem, then you ++ need to increase the value of 'ProcMounts_Times' make-variable in ++ aufs-util.git as a second best solution. ++- vfs-ino.patch ++ Modifies a system global kernel internal function get_next_ino() in ++ order to stop assigning 0 for an inode-number. Not directly related to ++ aufs, but recommended generally. ++- tmpfs-idr.patch ++ Keeps the tmpfs inode number as the lowest value. Effective to reduce ++ the size of aufs XINO files for tmpfs branch. Also it prevents the ++ duplication of inode number, which is important for backup tools and ++ other utilities. When you find aufs XINO files for tmpfs branch ++ growing too much, try this patch. ++- lockdep-debug.patch ++ Because aufs is not only an ordinary filesystem (callee of VFS), but ++ also a caller of VFS functions for branch filesystems, subclassing of ++ the internal locks for LOCKDEP is necessary. LOCKDEP is a debugging ++ feature of linux kernel. If you enable CONFIG_LOCKDEP, then you will ++ need to apply this debug patch to expand several constant values. ++ If don't know what LOCKDEP is, then you don't have apply this patch. ++ ++ ++4. Usage ++---------------------------------------- ++At first, make sure aufs-util are installed, and please read the aufs ++manual, aufs.5 in aufs-util.git tree. ++$ man -l aufs.5 ++ ++And then, ++$ mkdir /tmp/rw /tmp/aufs ++# mount -t aufs -o br=/tmp/rw:${HOME} none /tmp/aufs ++ ++Here is another example. The result is equivalent. ++# mount -t aufs -o br=/tmp/rw=rw:${HOME}=ro none /tmp/aufs ++ Or ++# mount -t aufs -o br:/tmp/rw none /tmp/aufs ++# mount -o remount,append:${HOME} /tmp/aufs ++ ++Then, you can see whole tree of your home dir through /tmp/aufs. If ++you modify a file under /tmp/aufs, the one on your home directory is ++not affected, instead the same named file will be newly created under ++/tmp/rw. And all of your modification to a file will be applied to ++the one under /tmp/rw. This is called the file based Copy on Write ++(COW) method. ++Aufs mount options are described in aufs.5. ++If you run chroot or something and make your aufs as a root directory, ++then you need to customize the shutdown script. See the aufs manual in ++detail. ++ ++Additionally, there are some sample usages of aufs which are a ++diskless system with network booting, and LiveCD over NFS. ++See sample dir in CVS tree on SourceForge. ++ ++ ++5. Contact ++---------------------------------------- ++When you have any problems or strange behaviour in aufs, please let me ++know with: ++- /proc/mounts (instead of the output of mount(8)) ++- /sys/module/aufs/* ++- /sys/fs/aufs/* (if you have them) ++- /debug/aufs/* (if you have them) ++- linux kernel version ++ if your kernel is not plain, for example modified by distributor, ++ the url where i can download its source is necessary too. ++- aufs version which was printed at loading the module or booting the ++ system, instead of the date you downloaded. ++- configuration (define/undefine CONFIG_AUFS_xxx) ++- kernel configuration or /proc/config.gz (if you have it) ++- behaviour which you think to be incorrect ++- actual operation, reproducible one is better ++- mailto: aufs-users at lists.sourceforge.net ++ ++Usually, I don't watch the Public Areas(Bugs, Support Requests, Patches, ++and Feature Requests) on SourceForge. Please join and write to ++aufs-users ML. ++ ++ ++6. Acknowledgements ++---------------------------------------- ++Thanks to everyone who have tried and are using aufs, whoever ++have reported a bug or any feedback. ++ ++Especially donators: ++Tomas Matejicek(slax.org) made a donation (much more than once). ++ Since Apr 2010, Tomas M (the author of Slax and Linux Live ++ scripts) is making "doubling" donations. ++ Unfortunately I cannot list all of the donators, but I really ++ appreciate. ++ It ends Aug 2010, but the ordinary donation URL is still available. ++ ++Dai Itasaka made a donation (2007/8). ++Chuck Smith made a donation (2008/4, 10 and 12). ++Henk Schoneveld made a donation (2008/9). ++Chih-Wei Huang, ASUS, CTC donated Eee PC 4G (2008/10). ++Francois Dupoux made a donation (2008/11). ++Bruno Cesar Ribas and Luis Carlos Erpen de Bona, C3SL serves public ++ aufs2 GIT tree (2009/2). ++William Grant made a donation (2009/3). ++Patrick Lane made a donation (2009/4). ++The Mail Archive (mail-archive.com) made donations (2009/5). ++Nippy Networks (Ed Wildgoose) made a donation (2009/7). ++New Dream Network, LLC (www.dreamhost.com) made a donation (2009/11). ++Pavel Pronskiy made a donation (2011/2). ++Iridium and Inmarsat satellite phone retailer (www.mailasail.com), Nippy ++ Networks (Ed Wildgoose) made a donation for hardware (2011/3). ++Max Lekomcev (DOM-TV project) made a donation (2011/7, 12, 2012/3, 6 and ++11). ++Sam Liddicott made a donation (2011/9). ++Era Scarecrow made a donation (2013/4). ++Bor Ratajc made a donation (2013/4). ++Alessandro Gorreta made a donation (2013/4). ++POIRETTE Marc made a donation (2013/4). ++Alessandro Gorreta made a donation (2013/4). ++lauri kasvandik made a donation (2013/5). ++"pemasu from Finland" made a donation (2013/7). ++The Parted Magic Project made a donation (2013/9 and 11). ++Pavel Barta made a donation (2013/10). ++Nikolay Pertsev made a donation (2014/5). ++James B made a donation (2014/7 and 2015/7). ++Stefano Di Biase made a donation (2014/8). ++Daniel Epellei made a donation (2015/1). ++OmegaPhil made a donation (2016/1, 2018/4). ++Tomasz Szewczyk made a donation (2016/4). ++James Burry made a donation (2016/12). ++Carsten Rose made a donation (2018/9). ++Porteus Kiosk made a donation (2018/10). ++ ++Thank you very much. ++Donations are always, including future donations, very important and ++helpful for me to keep on developing aufs. ++ ++ ++7. ++---------------------------------------- ++If you are an experienced user, no explanation is needed. Aufs is ++just a linux filesystem. ++ ++ ++Enjoy! ++ ++# Local variables: ; ++# mode: text; ++# End: ; +diff -Nurp linux-5.4/drivers/block/loop.c linux-5.4-aufs/drivers/block/loop.c +--- linux-5.4/drivers/block/loop.c 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/drivers/block/loop.c 2019-11-28 01:25:59.062925618 +0200 +@@ -738,6 +738,24 @@ out_err: + return error; + } + ++/* ++ * for AUFS ++ * no get/put for file. ++ */ ++struct file *loop_backing_file(struct super_block *sb) ++{ ++ struct file *ret; ++ struct loop_device *l; ++ ++ ret = NULL; ++ if (MAJOR(sb->s_dev) == LOOP_MAJOR) { ++ l = sb->s_bdev->bd_disk->private_data; ++ ret = l->lo_backing_file; ++ } ++ return ret; ++} ++EXPORT_SYMBOL_GPL(loop_backing_file); ++ + /* loop sysfs attributes */ + + static ssize_t loop_attr_show(struct device *dev, char *page, +diff -Nurp linux-5.4/fs/aufs/aufs.h linux-5.4-aufs/fs/aufs/aufs.h +--- linux-5.4/fs/aufs/aufs.h 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/aufs.h 2019-11-28 01:25:59.062925618 +0200 +@@ -0,0 +1,49 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * all header files ++ */ ++ ++#ifndef __AUFS_H__ ++#define __AUFS_H__ ++ ++#ifdef __KERNEL__ ++ ++#define AuStub(type, name, body, ...) \ ++ static inline type name(__VA_ARGS__) { body; } ++ ++#define AuStubVoid(name, ...) \ ++ AuStub(void, name, , __VA_ARGS__) ++#define AuStubInt0(name, ...) \ ++ AuStub(int, name, return 0, __VA_ARGS__) ++ ++#include "debug.h" ++ ++#include "branch.h" ++#include "cpup.h" ++#include "dcsub.h" ++#include "dbgaufs.h" ++#include "dentry.h" ++#include "dir.h" ++#include "dirren.h" ++#include "dynop.h" ++#include "file.h" ++#include "fstype.h" ++#include "hbl.h" ++#include "inode.h" ++#include "lcnt.h" ++#include "loop.h" ++#include "module.h" ++#include "opts.h" ++#include "rwsem.h" ++#include "super.h" ++#include "sysaufs.h" ++#include "vfsub.h" ++#include "whout.h" ++#include "wkq.h" ++ ++#endif /* __KERNEL__ */ ++#endif /* __AUFS_H__ */ +diff -Nurp linux-5.4/fs/aufs/branch.c linux-5.4-aufs/fs/aufs/branch.c +--- linux-5.4/fs/aufs/branch.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/branch.c 2019-11-28 01:25:59.062925618 +0200 +@@ -0,0 +1,1415 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * branch management ++ */ ++ ++#include ++#include ++#include "aufs.h" ++ ++/* ++ * free a single branch ++ */ ++static void au_br_do_free(struct au_branch *br) ++{ ++ int i; ++ struct au_wbr *wbr; ++ struct au_dykey **key; ++ ++ au_hnotify_fin_br(br); ++ /* always, regardless the mount option */ ++ au_dr_hino_free(&br->br_dirren); ++ au_xino_put(br); ++ ++ AuLCntZero(au_lcnt_read(&br->br_nfiles, /*do_rev*/0)); ++ au_lcnt_fin(&br->br_nfiles, /*do_sync*/0); ++ AuLCntZero(au_lcnt_read(&br->br_count, /*do_rev*/0)); ++ au_lcnt_fin(&br->br_count, /*do_sync*/0); ++ ++ wbr = br->br_wbr; ++ if (wbr) { ++ for (i = 0; i < AuBrWh_Last; i++) ++ dput(wbr->wbr_wh[i]); ++ AuDebugOn(atomic_read(&wbr->wbr_wh_running)); ++ AuRwDestroy(&wbr->wbr_wh_rwsem); ++ } ++ ++ if (br->br_fhsm) { ++ au_br_fhsm_fin(br->br_fhsm); ++ au_kfree_try_rcu(br->br_fhsm); ++ } ++ ++ key = br->br_dykey; ++ for (i = 0; i < AuBrDynOp; i++, key++) ++ if (*key) ++ au_dy_put(*key); ++ else ++ break; ++ ++ /* recursive lock, s_umount of branch's */ ++ /* synchronize_rcu(); */ /* why? */ ++ lockdep_off(); ++ path_put(&br->br_path); ++ lockdep_on(); ++ au_kfree_rcu(wbr); ++ au_lcnt_wait_for_fin(&br->br_nfiles); ++ au_lcnt_wait_for_fin(&br->br_count); ++ /* I don't know why, but percpu_refcount requires this */ ++ /* synchronize_rcu(); */ ++ au_kfree_rcu(br); ++} ++ ++/* ++ * frees all branches ++ */ ++void au_br_free(struct au_sbinfo *sbinfo) ++{ ++ aufs_bindex_t bmax; ++ struct au_branch **br; ++ ++ AuRwMustWriteLock(&sbinfo->si_rwsem); ++ ++ bmax = sbinfo->si_bbot + 1; ++ br = sbinfo->si_branch; ++ while (bmax--) ++ au_br_do_free(*br++); ++} ++ ++/* ++ * find the index of a branch which is specified by @br_id. ++ */ ++int au_br_index(struct super_block *sb, aufs_bindex_t br_id) ++{ ++ aufs_bindex_t bindex, bbot; ++ ++ bbot = au_sbbot(sb); ++ for (bindex = 0; bindex <= bbot; bindex++) ++ if (au_sbr_id(sb, bindex) == br_id) ++ return bindex; ++ return -1; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * add a branch ++ */ ++ ++static int test_overlap(struct super_block *sb, struct dentry *h_adding, ++ struct dentry *h_root) ++{ ++ if (unlikely(h_adding == h_root ++ || au_test_loopback_overlap(sb, h_adding))) ++ return 1; ++ if (h_adding->d_sb != h_root->d_sb) ++ return 0; ++ return au_test_subdir(h_adding, h_root) ++ || au_test_subdir(h_root, h_adding); ++} ++ ++/* ++ * returns a newly allocated branch. @new_nbranch is a number of branches ++ * after adding a branch. ++ */ ++static struct au_branch *au_br_alloc(struct super_block *sb, int new_nbranch, ++ int perm) ++{ ++ struct au_branch *add_branch; ++ struct dentry *root; ++ struct inode *inode; ++ int err; ++ ++ err = -ENOMEM; ++ add_branch = kzalloc(sizeof(*add_branch), GFP_NOFS); ++ if (unlikely(!add_branch)) ++ goto out; ++ add_branch->br_xino = au_xino_alloc(/*nfile*/1); ++ if (unlikely(!add_branch->br_xino)) ++ goto out_br; ++ err = au_hnotify_init_br(add_branch, perm); ++ if (unlikely(err)) ++ goto out_xino; ++ ++ if (au_br_writable(perm)) { ++ /* may be freed separately at changing the branch permission */ ++ add_branch->br_wbr = kzalloc(sizeof(*add_branch->br_wbr), ++ GFP_NOFS); ++ if (unlikely(!add_branch->br_wbr)) ++ goto out_hnotify; ++ } ++ ++ if (au_br_fhsm(perm)) { ++ err = au_fhsm_br_alloc(add_branch); ++ if (unlikely(err)) ++ goto out_wbr; ++ } ++ ++ root = sb->s_root; ++ err = au_sbr_realloc(au_sbi(sb), new_nbranch, /*may_shrink*/0); ++ if (!err) ++ err = au_di_realloc(au_di(root), new_nbranch, /*may_shrink*/0); ++ if (!err) { ++ inode = d_inode(root); ++ err = au_hinode_realloc(au_ii(inode), new_nbranch, ++ /*may_shrink*/0); ++ } ++ if (!err) ++ return add_branch; /* success */ ++ ++out_wbr: ++ au_kfree_rcu(add_branch->br_wbr); ++out_hnotify: ++ au_hnotify_fin_br(add_branch); ++out_xino: ++ au_xino_put(add_branch); ++out_br: ++ au_kfree_rcu(add_branch); ++out: ++ return ERR_PTR(err); ++} ++ ++/* ++ * test if the branch permission is legal or not. ++ */ ++static int test_br(struct inode *inode, int brperm, char *path) ++{ ++ int err; ++ ++ err = (au_br_writable(brperm) && IS_RDONLY(inode)); ++ if (!err) ++ goto out; ++ ++ err = -EINVAL; ++ pr_err("write permission for readonly mount or inode, %s\n", path); ++ ++out: ++ return err; ++} ++ ++/* ++ * returns: ++ * 0: success, the caller will add it ++ * plus: success, it is already unified, the caller should ignore it ++ * minus: error ++ */ ++static int test_add(struct super_block *sb, struct au_opt_add *add, int remount) ++{ ++ int err; ++ aufs_bindex_t bbot, bindex; ++ struct dentry *root, *h_dentry; ++ struct inode *inode, *h_inode; ++ ++ root = sb->s_root; ++ bbot = au_sbbot(sb); ++ if (unlikely(bbot >= 0 ++ && au_find_dbindex(root, add->path.dentry) >= 0)) { ++ err = 1; ++ if (!remount) { ++ err = -EINVAL; ++ pr_err("%s duplicated\n", add->pathname); ++ } ++ goto out; ++ } ++ ++ err = -ENOSPC; /* -E2BIG; */ ++ if (unlikely(AUFS_BRANCH_MAX <= add->bindex ++ || AUFS_BRANCH_MAX - 1 <= bbot)) { ++ pr_err("number of branches exceeded %s\n", add->pathname); ++ goto out; ++ } ++ ++ err = -EDOM; ++ if (unlikely(add->bindex < 0 || bbot + 1 < add->bindex)) { ++ pr_err("bad index %d\n", add->bindex); ++ goto out; ++ } ++ ++ inode = d_inode(add->path.dentry); ++ err = -ENOENT; ++ if (unlikely(!inode->i_nlink)) { ++ pr_err("no existence %s\n", add->pathname); ++ goto out; ++ } ++ ++ err = -EINVAL; ++ if (unlikely(inode->i_sb == sb)) { ++ pr_err("%s must be outside\n", add->pathname); ++ goto out; ++ } ++ ++ if (unlikely(au_test_fs_unsuppoted(inode->i_sb))) { ++ pr_err("unsupported filesystem, %s (%s)\n", ++ add->pathname, au_sbtype(inode->i_sb)); ++ goto out; ++ } ++ ++ if (unlikely(inode->i_sb->s_stack_depth)) { ++ pr_err("already stacked, %s (%s)\n", ++ add->pathname, au_sbtype(inode->i_sb)); ++ goto out; ++ } ++ ++ err = test_br(d_inode(add->path.dentry), add->perm, add->pathname); ++ if (unlikely(err)) ++ goto out; ++ ++ if (bbot < 0) ++ return 0; /* success */ ++ ++ err = -EINVAL; ++ for (bindex = 0; bindex <= bbot; bindex++) ++ if (unlikely(test_overlap(sb, add->path.dentry, ++ au_h_dptr(root, bindex)))) { ++ pr_err("%s is overlapped\n", add->pathname); ++ goto out; ++ } ++ ++ err = 0; ++ if (au_opt_test(au_mntflags(sb), WARN_PERM)) { ++ h_dentry = au_h_dptr(root, 0); ++ h_inode = d_inode(h_dentry); ++ if ((h_inode->i_mode & S_IALLUGO) != (inode->i_mode & S_IALLUGO) ++ || !uid_eq(h_inode->i_uid, inode->i_uid) ++ || !gid_eq(h_inode->i_gid, inode->i_gid)) ++ pr_warn("uid/gid/perm %s %u/%u/0%o, %u/%u/0%o\n", ++ add->pathname, ++ i_uid_read(inode), i_gid_read(inode), ++ (inode->i_mode & S_IALLUGO), ++ i_uid_read(h_inode), i_gid_read(h_inode), ++ (h_inode->i_mode & S_IALLUGO)); ++ } ++ ++out: ++ return err; ++} ++ ++/* ++ * initialize or clean the whiteouts for an adding branch ++ */ ++static int au_br_init_wh(struct super_block *sb, struct au_branch *br, ++ int new_perm) ++{ ++ int err, old_perm; ++ aufs_bindex_t bindex; ++ struct inode *h_inode; ++ struct au_wbr *wbr; ++ struct au_hinode *hdir; ++ struct dentry *h_dentry; ++ ++ err = vfsub_mnt_want_write(au_br_mnt(br)); ++ if (unlikely(err)) ++ goto out; ++ ++ wbr = br->br_wbr; ++ old_perm = br->br_perm; ++ br->br_perm = new_perm; ++ hdir = NULL; ++ h_inode = NULL; ++ bindex = au_br_index(sb, br->br_id); ++ if (0 <= bindex) { ++ hdir = au_hi(d_inode(sb->s_root), bindex); ++ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT); ++ } else { ++ h_dentry = au_br_dentry(br); ++ h_inode = d_inode(h_dentry); ++ inode_lock_nested(h_inode, AuLsc_I_PARENT); ++ } ++ if (!wbr) ++ err = au_wh_init(br, sb); ++ else { ++ wbr_wh_write_lock(wbr); ++ err = au_wh_init(br, sb); ++ wbr_wh_write_unlock(wbr); ++ } ++ if (hdir) ++ au_hn_inode_unlock(hdir); ++ else ++ inode_unlock(h_inode); ++ vfsub_mnt_drop_write(au_br_mnt(br)); ++ br->br_perm = old_perm; ++ ++ if (!err && wbr && !au_br_writable(new_perm)) { ++ au_kfree_rcu(wbr); ++ br->br_wbr = NULL; ++ } ++ ++out: ++ return err; ++} ++ ++static int au_wbr_init(struct au_branch *br, struct super_block *sb, ++ int perm) ++{ ++ int err; ++ struct kstatfs kst; ++ struct au_wbr *wbr; ++ ++ wbr = br->br_wbr; ++ au_rw_init(&wbr->wbr_wh_rwsem); ++ atomic_set(&wbr->wbr_wh_running, 0); ++ ++ /* ++ * a limit for rmdir/rename a dir ++ * cf. AUFS_MAX_NAMELEN in include/uapi/linux/aufs_type.h ++ */ ++ err = vfs_statfs(&br->br_path, &kst); ++ if (unlikely(err)) ++ goto out; ++ err = -EINVAL; ++ if (kst.f_namelen >= NAME_MAX) ++ err = au_br_init_wh(sb, br, perm); ++ else ++ pr_err("%pd(%s), unsupported namelen %ld\n", ++ au_br_dentry(br), ++ au_sbtype(au_br_dentry(br)->d_sb), kst.f_namelen); ++ ++out: ++ return err; ++} ++ ++/* initialize a new branch */ ++static int au_br_init(struct au_branch *br, struct super_block *sb, ++ struct au_opt_add *add) ++{ ++ int err; ++ struct au_branch *brbase; ++ struct file *xf; ++ struct inode *h_inode; ++ ++ err = 0; ++ br->br_perm = add->perm; ++ br->br_path = add->path; /* set first, path_get() later */ ++ spin_lock_init(&br->br_dykey_lock); ++ au_lcnt_init(&br->br_nfiles, /*release*/NULL); ++ au_lcnt_init(&br->br_count, /*release*/NULL); ++ br->br_id = au_new_br_id(sb); ++ AuDebugOn(br->br_id < 0); ++ ++ /* always, regardless the given option */ ++ err = au_dr_br_init(sb, br, &add->path); ++ if (unlikely(err)) ++ goto out_err; ++ ++ if (au_br_writable(add->perm)) { ++ err = au_wbr_init(br, sb, add->perm); ++ if (unlikely(err)) ++ goto out_err; ++ } ++ ++ if (au_opt_test(au_mntflags(sb), XINO)) { ++ brbase = au_sbr(sb, 0); ++ xf = au_xino_file(brbase->br_xino, /*idx*/-1); ++ AuDebugOn(!xf); ++ h_inode = d_inode(add->path.dentry); ++ err = au_xino_init_br(sb, br, h_inode->i_ino, &xf->f_path); ++ if (unlikely(err)) { ++ AuDebugOn(au_xino_file(br->br_xino, /*idx*/-1)); ++ goto out_err; ++ } ++ } ++ ++ sysaufs_br_init(br); ++ path_get(&br->br_path); ++ goto out; /* success */ ++ ++out_err: ++ memset(&br->br_path, 0, sizeof(br->br_path)); ++out: ++ return err; ++} ++ ++static void au_br_do_add_brp(struct au_sbinfo *sbinfo, aufs_bindex_t bindex, ++ struct au_branch *br, aufs_bindex_t bbot, ++ aufs_bindex_t amount) ++{ ++ struct au_branch **brp; ++ ++ AuRwMustWriteLock(&sbinfo->si_rwsem); ++ ++ brp = sbinfo->si_branch + bindex; ++ memmove(brp + 1, brp, sizeof(*brp) * amount); ++ *brp = br; ++ sbinfo->si_bbot++; ++ if (unlikely(bbot < 0)) ++ sbinfo->si_bbot = 0; ++} ++ ++static void au_br_do_add_hdp(struct au_dinfo *dinfo, aufs_bindex_t bindex, ++ aufs_bindex_t bbot, aufs_bindex_t amount) ++{ ++ struct au_hdentry *hdp; ++ ++ AuRwMustWriteLock(&dinfo->di_rwsem); ++ ++ hdp = au_hdentry(dinfo, bindex); ++ memmove(hdp + 1, hdp, sizeof(*hdp) * amount); ++ au_h_dentry_init(hdp); ++ dinfo->di_bbot++; ++ if (unlikely(bbot < 0)) ++ dinfo->di_btop = 0; ++} ++ ++static void au_br_do_add_hip(struct au_iinfo *iinfo, aufs_bindex_t bindex, ++ aufs_bindex_t bbot, aufs_bindex_t amount) ++{ ++ struct au_hinode *hip; ++ ++ AuRwMustWriteLock(&iinfo->ii_rwsem); ++ ++ hip = au_hinode(iinfo, bindex); ++ memmove(hip + 1, hip, sizeof(*hip) * amount); ++ au_hinode_init(hip); ++ iinfo->ii_bbot++; ++ if (unlikely(bbot < 0)) ++ iinfo->ii_btop = 0; ++} ++ ++static void au_br_do_add(struct super_block *sb, struct au_branch *br, ++ aufs_bindex_t bindex) ++{ ++ struct dentry *root, *h_dentry; ++ struct inode *root_inode, *h_inode; ++ aufs_bindex_t bbot, amount; ++ ++ root = sb->s_root; ++ root_inode = d_inode(root); ++ bbot = au_sbbot(sb); ++ amount = bbot + 1 - bindex; ++ h_dentry = au_br_dentry(br); ++ au_sbilist_lock(); ++ au_br_do_add_brp(au_sbi(sb), bindex, br, bbot, amount); ++ au_br_do_add_hdp(au_di(root), bindex, bbot, amount); ++ au_br_do_add_hip(au_ii(root_inode), bindex, bbot, amount); ++ au_set_h_dptr(root, bindex, dget(h_dentry)); ++ h_inode = d_inode(h_dentry); ++ au_set_h_iptr(root_inode, bindex, au_igrab(h_inode), /*flags*/0); ++ au_sbilist_unlock(); ++} ++ ++int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount) ++{ ++ int err; ++ aufs_bindex_t bbot, add_bindex; ++ struct dentry *root, *h_dentry; ++ struct inode *root_inode; ++ struct au_branch *add_branch; ++ ++ root = sb->s_root; ++ root_inode = d_inode(root); ++ IMustLock(root_inode); ++ IiMustWriteLock(root_inode); ++ err = test_add(sb, add, remount); ++ if (unlikely(err < 0)) ++ goto out; ++ if (err) { ++ err = 0; ++ goto out; /* success */ ++ } ++ ++ bbot = au_sbbot(sb); ++ add_branch = au_br_alloc(sb, bbot + 2, add->perm); ++ err = PTR_ERR(add_branch); ++ if (IS_ERR(add_branch)) ++ goto out; ++ ++ err = au_br_init(add_branch, sb, add); ++ if (unlikely(err)) { ++ au_br_do_free(add_branch); ++ goto out; ++ } ++ ++ add_bindex = add->bindex; ++ sysaufs_brs_del(sb, add_bindex); /* remove successors */ ++ au_br_do_add(sb, add_branch, add_bindex); ++ sysaufs_brs_add(sb, add_bindex); /* append successors */ ++ dbgaufs_brs_add(sb, add_bindex, /*topdown*/0); /* rename successors */ ++ ++ h_dentry = add->path.dentry; ++ if (!add_bindex) { ++ au_cpup_attr_all(root_inode, /*force*/1); ++ sb->s_maxbytes = h_dentry->d_sb->s_maxbytes; ++ } else ++ au_add_nlink(root_inode, d_inode(h_dentry)); ++ ++out: ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static unsigned long long au_farray_cb(struct super_block *sb, void *a, ++ unsigned long long max __maybe_unused, ++ void *arg) ++{ ++ unsigned long long n; ++ struct file **p, *f; ++ struct hlist_bl_head *files; ++ struct hlist_bl_node *pos; ++ struct au_finfo *finfo; ++ ++ n = 0; ++ p = a; ++ files = &au_sbi(sb)->si_files; ++ hlist_bl_lock(files); ++ hlist_bl_for_each_entry(finfo, pos, files, fi_hlist) { ++ f = finfo->fi_file; ++ if (file_count(f) ++ && !special_file(file_inode(f)->i_mode)) { ++ get_file(f); ++ *p++ = f; ++ n++; ++ AuDebugOn(n > max); ++ } ++ } ++ hlist_bl_unlock(files); ++ ++ return n; ++} ++ ++static struct file **au_farray_alloc(struct super_block *sb, ++ unsigned long long *max) ++{ ++ struct au_sbinfo *sbi; ++ ++ sbi = au_sbi(sb); ++ *max = au_lcnt_read(&sbi->si_nfiles, /*do_rev*/1); ++ return au_array_alloc(max, au_farray_cb, sb, /*arg*/NULL); ++} ++ ++static void au_farray_free(struct file **a, unsigned long long max) ++{ ++ unsigned long long ull; ++ ++ for (ull = 0; ull < max; ull++) ++ if (a[ull]) ++ fput(a[ull]); ++ kvfree(a); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * delete a branch ++ */ ++ ++/* to show the line number, do not make it inlined function */ ++#define AuVerbose(do_info, fmt, ...) do { \ ++ if (do_info) \ ++ pr_info(fmt, ##__VA_ARGS__); \ ++} while (0) ++ ++static int au_test_ibusy(struct inode *inode, aufs_bindex_t btop, ++ aufs_bindex_t bbot) ++{ ++ return (inode && !S_ISDIR(inode->i_mode)) || btop == bbot; ++} ++ ++static int au_test_dbusy(struct dentry *dentry, aufs_bindex_t btop, ++ aufs_bindex_t bbot) ++{ ++ return au_test_ibusy(d_inode(dentry), btop, bbot); ++} ++ ++/* ++ * test if the branch is deletable or not. ++ */ ++static int test_dentry_busy(struct dentry *root, aufs_bindex_t bindex, ++ unsigned int sigen, const unsigned int verbose) ++{ ++ int err, i, j, ndentry; ++ aufs_bindex_t btop, bbot; ++ struct au_dcsub_pages dpages; ++ struct au_dpage *dpage; ++ struct dentry *d; ++ ++ err = au_dpages_init(&dpages, GFP_NOFS); ++ if (unlikely(err)) ++ goto out; ++ err = au_dcsub_pages(&dpages, root, NULL, NULL); ++ if (unlikely(err)) ++ goto out_dpages; ++ ++ for (i = 0; !err && i < dpages.ndpage; i++) { ++ dpage = dpages.dpages + i; ++ ndentry = dpage->ndentry; ++ for (j = 0; !err && j < ndentry; j++) { ++ d = dpage->dentries[j]; ++ AuDebugOn(au_dcount(d) <= 0); ++ if (!au_digen_test(d, sigen)) { ++ di_read_lock_child(d, AuLock_IR); ++ if (unlikely(au_dbrange_test(d))) { ++ di_read_unlock(d, AuLock_IR); ++ continue; ++ } ++ } else { ++ di_write_lock_child(d); ++ if (unlikely(au_dbrange_test(d))) { ++ di_write_unlock(d); ++ continue; ++ } ++ err = au_reval_dpath(d, sigen); ++ if (!err) ++ di_downgrade_lock(d, AuLock_IR); ++ else { ++ di_write_unlock(d); ++ break; ++ } ++ } ++ ++ /* AuDbgDentry(d); */ ++ btop = au_dbtop(d); ++ bbot = au_dbbot(d); ++ if (btop <= bindex ++ && bindex <= bbot ++ && au_h_dptr(d, bindex) ++ && au_test_dbusy(d, btop, bbot)) { ++ err = -EBUSY; ++ AuVerbose(verbose, "busy %pd\n", d); ++ AuDbgDentry(d); ++ } ++ di_read_unlock(d, AuLock_IR); ++ } ++ } ++ ++out_dpages: ++ au_dpages_free(&dpages); ++out: ++ return err; ++} ++ ++static int test_inode_busy(struct super_block *sb, aufs_bindex_t bindex, ++ unsigned int sigen, const unsigned int verbose) ++{ ++ int err; ++ unsigned long long max, ull; ++ struct inode *i, **array; ++ aufs_bindex_t btop, bbot; ++ ++ array = au_iarray_alloc(sb, &max); ++ err = PTR_ERR(array); ++ if (IS_ERR(array)) ++ goto out; ++ ++ err = 0; ++ AuDbg("b%d\n", bindex); ++ for (ull = 0; !err && ull < max; ull++) { ++ i = array[ull]; ++ if (unlikely(!i)) ++ break; ++ if (i->i_ino == AUFS_ROOT_INO) ++ continue; ++ ++ /* AuDbgInode(i); */ ++ if (au_iigen(i, NULL) == sigen) ++ ii_read_lock_child(i); ++ else { ++ ii_write_lock_child(i); ++ err = au_refresh_hinode_self(i); ++ au_iigen_dec(i); ++ if (!err) ++ ii_downgrade_lock(i); ++ else { ++ ii_write_unlock(i); ++ break; ++ } ++ } ++ ++ btop = au_ibtop(i); ++ bbot = au_ibbot(i); ++ if (btop <= bindex ++ && bindex <= bbot ++ && au_h_iptr(i, bindex) ++ && au_test_ibusy(i, btop, bbot)) { ++ err = -EBUSY; ++ AuVerbose(verbose, "busy i%lu\n", i->i_ino); ++ AuDbgInode(i); ++ } ++ ii_read_unlock(i); ++ } ++ au_iarray_free(array, max); ++ ++out: ++ return err; ++} ++ ++static int test_children_busy(struct dentry *root, aufs_bindex_t bindex, ++ const unsigned int verbose) ++{ ++ int err; ++ unsigned int sigen; ++ ++ sigen = au_sigen(root->d_sb); ++ DiMustNoWaiters(root); ++ IiMustNoWaiters(d_inode(root)); ++ di_write_unlock(root); ++ err = test_dentry_busy(root, bindex, sigen, verbose); ++ if (!err) ++ err = test_inode_busy(root->d_sb, bindex, sigen, verbose); ++ di_write_lock_child(root); /* aufs_write_lock() calls ..._child() */ ++ ++ return err; ++} ++ ++static int test_dir_busy(struct file *file, aufs_bindex_t br_id, ++ struct file **to_free, int *idx) ++{ ++ int err; ++ unsigned char matched, root; ++ aufs_bindex_t bindex, bbot; ++ struct au_fidir *fidir; ++ struct au_hfile *hfile; ++ ++ err = 0; ++ root = IS_ROOT(file->f_path.dentry); ++ if (root) { ++ get_file(file); ++ to_free[*idx] = file; ++ (*idx)++; ++ goto out; ++ } ++ ++ matched = 0; ++ fidir = au_fi(file)->fi_hdir; ++ AuDebugOn(!fidir); ++ bbot = au_fbbot_dir(file); ++ for (bindex = au_fbtop(file); bindex <= bbot; bindex++) { ++ hfile = fidir->fd_hfile + bindex; ++ if (!hfile->hf_file) ++ continue; ++ ++ if (hfile->hf_br->br_id == br_id) { ++ matched = 1; ++ break; ++ } ++ } ++ if (matched) ++ err = -EBUSY; ++ ++out: ++ return err; ++} ++ ++static int test_file_busy(struct super_block *sb, aufs_bindex_t br_id, ++ struct file **to_free, int opened) ++{ ++ int err, idx; ++ unsigned long long ull, max; ++ aufs_bindex_t btop; ++ struct file *file, **array; ++ struct dentry *root; ++ struct au_hfile *hfile; ++ ++ array = au_farray_alloc(sb, &max); ++ err = PTR_ERR(array); ++ if (IS_ERR(array)) ++ goto out; ++ ++ err = 0; ++ idx = 0; ++ root = sb->s_root; ++ di_write_unlock(root); ++ for (ull = 0; ull < max; ull++) { ++ file = array[ull]; ++ if (unlikely(!file)) ++ break; ++ ++ /* AuDbg("%pD\n", file); */ ++ fi_read_lock(file); ++ btop = au_fbtop(file); ++ if (!d_is_dir(file->f_path.dentry)) { ++ hfile = &au_fi(file)->fi_htop; ++ if (hfile->hf_br->br_id == br_id) ++ err = -EBUSY; ++ } else ++ err = test_dir_busy(file, br_id, to_free, &idx); ++ fi_read_unlock(file); ++ if (unlikely(err)) ++ break; ++ } ++ di_write_lock_child(root); ++ au_farray_free(array, max); ++ AuDebugOn(idx > opened); ++ ++out: ++ return err; ++} ++ ++static void br_del_file(struct file **to_free, unsigned long long opened, ++ aufs_bindex_t br_id) ++{ ++ unsigned long long ull; ++ aufs_bindex_t bindex, btop, bbot, bfound; ++ struct file *file; ++ struct au_fidir *fidir; ++ struct au_hfile *hfile; ++ ++ for (ull = 0; ull < opened; ull++) { ++ file = to_free[ull]; ++ if (unlikely(!file)) ++ break; ++ ++ /* AuDbg("%pD\n", file); */ ++ AuDebugOn(!d_is_dir(file->f_path.dentry)); ++ bfound = -1; ++ fidir = au_fi(file)->fi_hdir; ++ AuDebugOn(!fidir); ++ fi_write_lock(file); ++ btop = au_fbtop(file); ++ bbot = au_fbbot_dir(file); ++ for (bindex = btop; bindex <= bbot; bindex++) { ++ hfile = fidir->fd_hfile + bindex; ++ if (!hfile->hf_file) ++ continue; ++ ++ if (hfile->hf_br->br_id == br_id) { ++ bfound = bindex; ++ break; ++ } ++ } ++ AuDebugOn(bfound < 0); ++ au_set_h_fptr(file, bfound, NULL); ++ if (bfound == btop) { ++ for (btop++; btop <= bbot; btop++) ++ if (au_hf_dir(file, btop)) { ++ au_set_fbtop(file, btop); ++ break; ++ } ++ } ++ fi_write_unlock(file); ++ } ++} ++ ++static void au_br_do_del_brp(struct au_sbinfo *sbinfo, ++ const aufs_bindex_t bindex, ++ const aufs_bindex_t bbot) ++{ ++ struct au_branch **brp, **p; ++ ++ AuRwMustWriteLock(&sbinfo->si_rwsem); ++ ++ brp = sbinfo->si_branch + bindex; ++ if (bindex < bbot) ++ memmove(brp, brp + 1, sizeof(*brp) * (bbot - bindex)); ++ sbinfo->si_branch[0 + bbot] = NULL; ++ sbinfo->si_bbot--; ++ ++ p = au_krealloc(sbinfo->si_branch, sizeof(*p) * bbot, AuGFP_SBILIST, ++ /*may_shrink*/1); ++ if (p) ++ sbinfo->si_branch = p; ++ /* harmless error */ ++} ++ ++static void au_br_do_del_hdp(struct au_dinfo *dinfo, const aufs_bindex_t bindex, ++ const aufs_bindex_t bbot) ++{ ++ struct au_hdentry *hdp, *p; ++ ++ AuRwMustWriteLock(&dinfo->di_rwsem); ++ ++ hdp = au_hdentry(dinfo, bindex); ++ if (bindex < bbot) ++ memmove(hdp, hdp + 1, sizeof(*hdp) * (bbot - bindex)); ++ /* au_h_dentry_init(au_hdentry(dinfo, bbot); */ ++ dinfo->di_bbot--; ++ ++ p = au_krealloc(dinfo->di_hdentry, sizeof(*p) * bbot, AuGFP_SBILIST, ++ /*may_shrink*/1); ++ if (p) ++ dinfo->di_hdentry = p; ++ /* harmless error */ ++} ++ ++static void au_br_do_del_hip(struct au_iinfo *iinfo, const aufs_bindex_t bindex, ++ const aufs_bindex_t bbot) ++{ ++ struct au_hinode *hip, *p; ++ ++ AuRwMustWriteLock(&iinfo->ii_rwsem); ++ ++ hip = au_hinode(iinfo, bindex); ++ if (bindex < bbot) ++ memmove(hip, hip + 1, sizeof(*hip) * (bbot - bindex)); ++ /* au_hinode_init(au_hinode(iinfo, bbot)); */ ++ iinfo->ii_bbot--; ++ ++ p = au_krealloc(iinfo->ii_hinode, sizeof(*p) * bbot, AuGFP_SBILIST, ++ /*may_shrink*/1); ++ if (p) ++ iinfo->ii_hinode = p; ++ /* harmless error */ ++} ++ ++static void au_br_do_del(struct super_block *sb, aufs_bindex_t bindex, ++ struct au_branch *br) ++{ ++ aufs_bindex_t bbot; ++ struct au_sbinfo *sbinfo; ++ struct dentry *root, *h_root; ++ struct inode *inode, *h_inode; ++ struct au_hinode *hinode; ++ ++ SiMustWriteLock(sb); ++ ++ root = sb->s_root; ++ inode = d_inode(root); ++ sbinfo = au_sbi(sb); ++ bbot = sbinfo->si_bbot; ++ ++ h_root = au_h_dptr(root, bindex); ++ hinode = au_hi(inode, bindex); ++ h_inode = au_igrab(hinode->hi_inode); ++ au_hiput(hinode); ++ ++ au_sbilist_lock(); ++ au_br_do_del_brp(sbinfo, bindex, bbot); ++ au_br_do_del_hdp(au_di(root), bindex, bbot); ++ au_br_do_del_hip(au_ii(inode), bindex, bbot); ++ au_sbilist_unlock(); ++ ++ /* ignore an error */ ++ au_dr_br_fin(sb, br); /* always, regardless the mount option */ ++ ++ dput(h_root); ++ iput(h_inode); ++ au_br_do_free(br); ++} ++ ++static unsigned long long empty_cb(struct super_block *sb, void *array, ++ unsigned long long max, void *arg) ++{ ++ return max; ++} ++ ++int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount) ++{ ++ int err, rerr, i; ++ unsigned long long opened; ++ unsigned int mnt_flags; ++ aufs_bindex_t bindex, bbot, br_id; ++ unsigned char do_wh, verbose; ++ struct au_branch *br; ++ struct au_wbr *wbr; ++ struct dentry *root; ++ struct file **to_free; ++ ++ err = 0; ++ opened = 0; ++ to_free = NULL; ++ root = sb->s_root; ++ bindex = au_find_dbindex(root, del->h_path.dentry); ++ if (bindex < 0) { ++ if (remount) ++ goto out; /* success */ ++ err = -ENOENT; ++ pr_err("%s no such branch\n", del->pathname); ++ goto out; ++ } ++ AuDbg("bindex b%d\n", bindex); ++ ++ err = -EBUSY; ++ mnt_flags = au_mntflags(sb); ++ verbose = !!au_opt_test(mnt_flags, VERBOSE); ++ bbot = au_sbbot(sb); ++ if (unlikely(!bbot)) { ++ AuVerbose(verbose, "no more branches left\n"); ++ goto out; ++ } ++ ++ br = au_sbr(sb, bindex); ++ AuDebugOn(!path_equal(&br->br_path, &del->h_path)); ++ if (unlikely(au_lcnt_read(&br->br_count, /*do_rev*/1))) { ++ AuVerbose(verbose, "br %pd2 is busy now\n", del->h_path.dentry); ++ goto out; ++ } ++ ++ br_id = br->br_id; ++ opened = au_lcnt_read(&br->br_nfiles, /*do_rev*/1); ++ if (unlikely(opened)) { ++ to_free = au_array_alloc(&opened, empty_cb, sb, NULL); ++ err = PTR_ERR(to_free); ++ if (IS_ERR(to_free)) ++ goto out; ++ ++ err = test_file_busy(sb, br_id, to_free, opened); ++ if (unlikely(err)) { ++ AuVerbose(verbose, "%llu file(s) opened\n", opened); ++ goto out; ++ } ++ } ++ ++ wbr = br->br_wbr; ++ do_wh = wbr && (wbr->wbr_whbase || wbr->wbr_plink || wbr->wbr_orph); ++ if (do_wh) { ++ /* instead of WbrWhMustWriteLock(wbr) */ ++ SiMustWriteLock(sb); ++ for (i = 0; i < AuBrWh_Last; i++) { ++ dput(wbr->wbr_wh[i]); ++ wbr->wbr_wh[i] = NULL; ++ } ++ } ++ ++ err = test_children_busy(root, bindex, verbose); ++ if (unlikely(err)) { ++ if (do_wh) ++ goto out_wh; ++ goto out; ++ } ++ ++ err = 0; ++ if (to_free) { ++ /* ++ * now we confirmed the branch is deletable. ++ * let's free the remaining opened dirs on the branch. ++ */ ++ di_write_unlock(root); ++ br_del_file(to_free, opened, br_id); ++ di_write_lock_child(root); ++ } ++ ++ sysaufs_brs_del(sb, bindex); /* remove successors */ ++ dbgaufs_xino_del(br); /* remove one */ ++ au_br_do_del(sb, bindex, br); ++ sysaufs_brs_add(sb, bindex); /* append successors */ ++ dbgaufs_brs_add(sb, bindex, /*topdown*/1); /* rename successors */ ++ ++ if (!bindex) { ++ au_cpup_attr_all(d_inode(root), /*force*/1); ++ sb->s_maxbytes = au_sbr_sb(sb, 0)->s_maxbytes; ++ } else ++ au_sub_nlink(d_inode(root), d_inode(del->h_path.dentry)); ++ if (au_opt_test(mnt_flags, PLINK)) ++ au_plink_half_refresh(sb, br_id); ++ ++ goto out; /* success */ ++ ++out_wh: ++ /* revert */ ++ rerr = au_br_init_wh(sb, br, br->br_perm); ++ if (rerr) ++ pr_warn("failed re-creating base whiteout, %s. (%d)\n", ++ del->pathname, rerr); ++out: ++ if (to_free) ++ au_farray_free(to_free, opened); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int au_ibusy(struct super_block *sb, struct aufs_ibusy __user *arg) ++{ ++ int err; ++ aufs_bindex_t btop, bbot; ++ struct aufs_ibusy ibusy; ++ struct inode *inode, *h_inode; ++ ++ err = -EPERM; ++ if (unlikely(!capable(CAP_SYS_ADMIN))) ++ goto out; ++ ++ err = copy_from_user(&ibusy, arg, sizeof(ibusy)); ++ if (!err) ++ /* VERIFY_WRITE */ ++ err = !access_ok(&arg->h_ino, sizeof(arg->h_ino)); ++ if (unlikely(err)) { ++ err = -EFAULT; ++ AuTraceErr(err); ++ goto out; ++ } ++ ++ err = -EINVAL; ++ si_read_lock(sb, AuLock_FLUSH); ++ if (unlikely(ibusy.bindex < 0 || ibusy.bindex > au_sbbot(sb))) ++ goto out_unlock; ++ ++ err = 0; ++ ibusy.h_ino = 0; /* invalid */ ++ inode = ilookup(sb, ibusy.ino); ++ if (!inode ++ || inode->i_ino == AUFS_ROOT_INO ++ || au_is_bad_inode(inode)) ++ goto out_unlock; ++ ++ ii_read_lock_child(inode); ++ btop = au_ibtop(inode); ++ bbot = au_ibbot(inode); ++ if (btop <= ibusy.bindex && ibusy.bindex <= bbot) { ++ h_inode = au_h_iptr(inode, ibusy.bindex); ++ if (h_inode && au_test_ibusy(inode, btop, bbot)) ++ ibusy.h_ino = h_inode->i_ino; ++ } ++ ii_read_unlock(inode); ++ iput(inode); ++ ++out_unlock: ++ si_read_unlock(sb); ++ if (!err) { ++ err = __put_user(ibusy.h_ino, &arg->h_ino); ++ if (unlikely(err)) { ++ err = -EFAULT; ++ AuTraceErr(err); ++ } ++ } ++out: ++ return err; ++} ++ ++long au_ibusy_ioctl(struct file *file, unsigned long arg) ++{ ++ return au_ibusy(file->f_path.dentry->d_sb, (void __user *)arg); ++} ++ ++#ifdef CONFIG_COMPAT ++long au_ibusy_compat_ioctl(struct file *file, unsigned long arg) ++{ ++ return au_ibusy(file->f_path.dentry->d_sb, compat_ptr(arg)); ++} ++#endif ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * change a branch permission ++ */ ++ ++static void au_warn_ima(void) ++{ ++#ifdef CONFIG_IMA ++ /* since it doesn't support mark_files_ro() */ ++ AuWarn1("RW -> RO makes IMA to produce wrong message\n"); ++#endif ++} ++ ++static int do_need_sigen_inc(int a, int b) ++{ ++ return au_br_whable(a) && !au_br_whable(b); ++} ++ ++static int need_sigen_inc(int old, int new) ++{ ++ return do_need_sigen_inc(old, new) ++ || do_need_sigen_inc(new, old); ++} ++ ++static int au_br_mod_files_ro(struct super_block *sb, aufs_bindex_t bindex) ++{ ++ int err, do_warn; ++ unsigned int mnt_flags; ++ unsigned long long ull, max; ++ aufs_bindex_t br_id; ++ unsigned char verbose, writer; ++ struct file *file, *hf, **array; ++ struct au_hfile *hfile; ++ struct inode *h_inode; ++ ++ mnt_flags = au_mntflags(sb); ++ verbose = !!au_opt_test(mnt_flags, VERBOSE); ++ ++ array = au_farray_alloc(sb, &max); ++ err = PTR_ERR(array); ++ if (IS_ERR(array)) ++ goto out; ++ ++ do_warn = 0; ++ br_id = au_sbr_id(sb, bindex); ++ for (ull = 0; ull < max; ull++) { ++ file = array[ull]; ++ if (unlikely(!file)) ++ break; ++ ++ /* AuDbg("%pD\n", file); */ ++ fi_read_lock(file); ++ if (unlikely(au_test_mmapped(file))) { ++ err = -EBUSY; ++ AuVerbose(verbose, "mmapped %pD\n", file); ++ AuDbgFile(file); ++ FiMustNoWaiters(file); ++ fi_read_unlock(file); ++ goto out_array; ++ } ++ ++ hfile = &au_fi(file)->fi_htop; ++ hf = hfile->hf_file; ++ if (!d_is_reg(file->f_path.dentry) ++ || !(file->f_mode & FMODE_WRITE) ++ || hfile->hf_br->br_id != br_id ++ || !(hf->f_mode & FMODE_WRITE)) ++ array[ull] = NULL; ++ else { ++ do_warn = 1; ++ get_file(file); ++ } ++ ++ FiMustNoWaiters(file); ++ fi_read_unlock(file); ++ fput(file); ++ } ++ ++ err = 0; ++ if (do_warn) ++ au_warn_ima(); ++ ++ for (ull = 0; ull < max; ull++) { ++ file = array[ull]; ++ if (!file) ++ continue; ++ ++ /* todo: already flushed? */ ++ /* ++ * fs/super.c:mark_files_ro() is gone, but aufs keeps its ++ * approach which resets f_mode and calls mnt_drop_write() and ++ * file_release_write() for each file, because the branch ++ * attribute in aufs world is totally different from the native ++ * fs rw/ro mode. ++ */ ++ /* fi_read_lock(file); */ ++ hfile = &au_fi(file)->fi_htop; ++ hf = hfile->hf_file; ++ /* fi_read_unlock(file); */ ++ spin_lock(&hf->f_lock); ++ writer = !!(hf->f_mode & FMODE_WRITER); ++ hf->f_mode &= ~(FMODE_WRITE | FMODE_WRITER); ++ spin_unlock(&hf->f_lock); ++ if (writer) { ++ h_inode = file_inode(hf); ++ put_write_access(h_inode); ++ __mnt_drop_write(hf->f_path.mnt); ++ if ((hf->f_mode & (FMODE_READ | FMODE_WRITE)) ++ == FMODE_READ) ++ i_readcount_inc(h_inode); ++ } ++ } ++ ++out_array: ++ au_farray_free(array, max); ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount, ++ int *do_refresh) ++{ ++ int err, rerr; ++ aufs_bindex_t bindex; ++ struct dentry *root; ++ struct au_branch *br; ++ struct au_br_fhsm *bf; ++ ++ root = sb->s_root; ++ bindex = au_find_dbindex(root, mod->h_root); ++ if (bindex < 0) { ++ if (remount) ++ return 0; /* success */ ++ err = -ENOENT; ++ pr_err("%s no such branch\n", mod->path); ++ goto out; ++ } ++ AuDbg("bindex b%d\n", bindex); ++ ++ err = test_br(d_inode(mod->h_root), mod->perm, mod->path); ++ if (unlikely(err)) ++ goto out; ++ ++ br = au_sbr(sb, bindex); ++ AuDebugOn(mod->h_root != au_br_dentry(br)); ++ if (br->br_perm == mod->perm) ++ return 0; /* success */ ++ ++ /* pre-allocate for non-fhsm --> fhsm */ ++ bf = NULL; ++ if (!au_br_fhsm(br->br_perm) && au_br_fhsm(mod->perm)) { ++ err = au_fhsm_br_alloc(br); ++ if (unlikely(err)) ++ goto out; ++ bf = br->br_fhsm; ++ br->br_fhsm = NULL; ++ } ++ ++ if (au_br_writable(br->br_perm)) { ++ /* remove whiteout base */ ++ err = au_br_init_wh(sb, br, mod->perm); ++ if (unlikely(err)) ++ goto out_bf; ++ ++ if (!au_br_writable(mod->perm)) { ++ /* rw --> ro, file might be mmapped */ ++ DiMustNoWaiters(root); ++ IiMustNoWaiters(d_inode(root)); ++ di_write_unlock(root); ++ err = au_br_mod_files_ro(sb, bindex); ++ /* aufs_write_lock() calls ..._child() */ ++ di_write_lock_child(root); ++ ++ if (unlikely(err)) { ++ rerr = -ENOMEM; ++ br->br_wbr = kzalloc(sizeof(*br->br_wbr), ++ GFP_NOFS); ++ if (br->br_wbr) ++ rerr = au_wbr_init(br, sb, br->br_perm); ++ if (unlikely(rerr)) { ++ AuIOErr("nested error %d (%d)\n", ++ rerr, err); ++ br->br_perm = mod->perm; ++ } ++ } ++ } ++ } else if (au_br_writable(mod->perm)) { ++ /* ro --> rw */ ++ err = -ENOMEM; ++ br->br_wbr = kzalloc(sizeof(*br->br_wbr), GFP_NOFS); ++ if (br->br_wbr) { ++ err = au_wbr_init(br, sb, mod->perm); ++ if (unlikely(err)) { ++ au_kfree_rcu(br->br_wbr); ++ br->br_wbr = NULL; ++ } ++ } ++ } ++ if (unlikely(err)) ++ goto out_bf; ++ ++ if (au_br_fhsm(br->br_perm)) { ++ if (!au_br_fhsm(mod->perm)) { ++ /* fhsm --> non-fhsm */ ++ au_br_fhsm_fin(br->br_fhsm); ++ au_kfree_rcu(br->br_fhsm); ++ br->br_fhsm = NULL; ++ } ++ } else if (au_br_fhsm(mod->perm)) ++ /* non-fhsm --> fhsm */ ++ br->br_fhsm = bf; ++ ++ *do_refresh |= need_sigen_inc(br->br_perm, mod->perm); ++ br->br_perm = mod->perm; ++ goto out; /* success */ ++ ++out_bf: ++ au_kfree_try_rcu(bf); ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++int au_br_stfs(struct au_branch *br, struct aufs_stfs *stfs) ++{ ++ int err; ++ struct kstatfs kstfs; ++ ++ err = vfs_statfs(&br->br_path, &kstfs); ++ if (!err) { ++ stfs->f_blocks = kstfs.f_blocks; ++ stfs->f_bavail = kstfs.f_bavail; ++ stfs->f_files = kstfs.f_files; ++ stfs->f_ffree = kstfs.f_ffree; ++ } ++ ++ return err; ++} +diff -Nurp linux-5.4/fs/aufs/branch.h linux-5.4-aufs/fs/aufs/branch.h +--- linux-5.4/fs/aufs/branch.h 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/branch.h 2019-11-28 01:25:59.062925618 +0200 +@@ -0,0 +1,353 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * branch filesystems and xino for them ++ */ ++ ++#ifndef __AUFS_BRANCH_H__ ++#define __AUFS_BRANCH_H__ ++ ++#ifdef __KERNEL__ ++ ++#include ++#include "dirren.h" ++#include "dynop.h" ++#include "lcnt.h" ++#include "rwsem.h" ++#include "super.h" ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* a xino file */ ++struct au_xino { ++ struct file **xi_file; ++ unsigned int xi_nfile; ++ ++ struct { ++ spinlock_t spin; ++ ino_t *array; ++ int total; ++ /* reserved for future use */ ++ /* unsigned long *bitmap; */ ++ wait_queue_head_t wqh; ++ } xi_nondir; ++ ++ struct mutex xi_mtx; /* protects xi_file array */ ++ struct hlist_bl_head xi_writing; ++ ++ atomic_t xi_truncating; ++ ++ struct kref xi_kref; ++}; ++ ++/* File-based Hierarchical Storage Management */ ++struct au_br_fhsm { ++#ifdef CONFIG_AUFS_FHSM ++ struct mutex bf_lock; ++ unsigned long bf_jiffy; ++ struct aufs_stfs bf_stfs; ++ int bf_readable; ++#endif ++}; ++ ++/* members for writable branch only */ ++enum {AuBrWh_BASE, AuBrWh_PLINK, AuBrWh_ORPH, AuBrWh_Last}; ++struct au_wbr { ++ struct au_rwsem wbr_wh_rwsem; ++ struct dentry *wbr_wh[AuBrWh_Last]; ++ atomic_t wbr_wh_running; ++#define wbr_whbase wbr_wh[AuBrWh_BASE] /* whiteout base */ ++#define wbr_plink wbr_wh[AuBrWh_PLINK] /* pseudo-link dir */ ++#define wbr_orph wbr_wh[AuBrWh_ORPH] /* dir for orphans */ ++ ++ /* mfs mode */ ++ unsigned long long wbr_bytes; ++}; ++ ++/* ext2 has 3 types of operations at least, ext3 has 4 */ ++#define AuBrDynOp (AuDyLast * 4) ++ ++#ifdef CONFIG_AUFS_HFSNOTIFY ++/* support for asynchronous destruction */ ++struct au_br_hfsnotify { ++ struct fsnotify_group *hfsn_group; ++}; ++#endif ++ ++/* sysfs entries */ ++struct au_brsysfs { ++ char name[16]; ++ struct attribute attr; ++}; ++ ++enum { ++ AuBrSysfs_BR, ++ AuBrSysfs_BRID, ++ AuBrSysfs_Last ++}; ++ ++/* protected by superblock rwsem */ ++struct au_branch { ++ struct au_xino *br_xino; ++ ++ aufs_bindex_t br_id; ++ ++ int br_perm; ++ struct path br_path; ++ spinlock_t br_dykey_lock; ++ struct au_dykey *br_dykey[AuBrDynOp]; ++ au_lcnt_t br_nfiles; /* opened files */ ++ au_lcnt_t br_count; /* in-use for other */ ++ ++ struct au_wbr *br_wbr; ++ struct au_br_fhsm *br_fhsm; ++ ++#ifdef CONFIG_AUFS_HFSNOTIFY ++ struct au_br_hfsnotify *br_hfsn; ++#endif ++ ++#ifdef CONFIG_SYSFS ++ /* entries under sysfs per mount-point */ ++ struct au_brsysfs br_sysfs[AuBrSysfs_Last]; ++#endif ++ ++#ifdef CONFIG_DEBUG_FS ++ struct dentry *br_dbgaufs; /* xino */ ++#endif ++ ++ struct au_dr_br br_dirren; ++}; ++ ++/* ---------------------------------------------------------------------- */ ++ ++static inline struct vfsmount *au_br_mnt(struct au_branch *br) ++{ ++ return br->br_path.mnt; ++} ++ ++static inline struct dentry *au_br_dentry(struct au_branch *br) ++{ ++ return br->br_path.dentry; ++} ++ ++static inline struct super_block *au_br_sb(struct au_branch *br) ++{ ++ return au_br_mnt(br)->mnt_sb; ++} ++ ++static inline int au_br_rdonly(struct au_branch *br) ++{ ++ return (sb_rdonly(au_br_sb(br)) ++ || !au_br_writable(br->br_perm)) ++ ? -EROFS : 0; ++} ++ ++static inline int au_br_hnotifyable(int brperm __maybe_unused) ++{ ++#ifdef CONFIG_AUFS_HNOTIFY ++ return !(brperm & AuBrPerm_RR); ++#else ++ return 0; ++#endif ++} ++ ++static inline int au_br_test_oflag(int oflag, struct au_branch *br) ++{ ++ int err, exec_flag; ++ ++ err = 0; ++ exec_flag = oflag & __FMODE_EXEC; ++ if (unlikely(exec_flag && path_noexec(&br->br_path))) ++ err = -EACCES; ++ ++ return err; ++} ++ ++static inline void au_xino_get(struct au_branch *br) ++{ ++ struct au_xino *xi; ++ ++ xi = br->br_xino; ++ if (xi) ++ kref_get(&xi->xi_kref); ++} ++ ++static inline int au_xino_count(struct au_branch *br) ++{ ++ int v; ++ struct au_xino *xi; ++ ++ v = 0; ++ xi = br->br_xino; ++ if (xi) ++ v = kref_read(&xi->xi_kref); ++ ++ return v; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* branch.c */ ++struct au_sbinfo; ++void au_br_free(struct au_sbinfo *sinfo); ++int au_br_index(struct super_block *sb, aufs_bindex_t br_id); ++struct au_opt_add; ++int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount); ++struct au_opt_del; ++int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount); ++long au_ibusy_ioctl(struct file *file, unsigned long arg); ++#ifdef CONFIG_COMPAT ++long au_ibusy_compat_ioctl(struct file *file, unsigned long arg); ++#endif ++struct au_opt_mod; ++int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount, ++ int *do_refresh); ++struct aufs_stfs; ++int au_br_stfs(struct au_branch *br, struct aufs_stfs *stfs); ++ ++/* xino.c */ ++static const loff_t au_loff_max = LLONG_MAX; ++ ++aufs_bindex_t au_xi_root(struct super_block *sb, struct dentry *dentry); ++struct file *au_xino_create(struct super_block *sb, char *fpath, int silent, ++ int wbrtop); ++struct file *au_xino_create2(struct super_block *sb, struct path *base, ++ struct file *copy_src); ++struct au_xi_new { ++ struct au_xino *xi; /* switch between xino and xigen */ ++ int idx; ++ struct path *base; ++ struct file *copy_src; ++}; ++struct file *au_xi_new(struct super_block *sb, struct au_xi_new *xinew); ++ ++int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, ++ ino_t *ino); ++int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, ++ ino_t ino); ++ssize_t xino_fread(vfs_readf_t func, struct file *file, void *buf, size_t size, ++ loff_t *pos); ++ssize_t xino_fwrite(vfs_writef_t func, struct file *file, void *buf, ++ size_t size, loff_t *pos); ++ ++int au_xib_trunc(struct super_block *sb); ++int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex, int idx_begin); ++ ++struct au_xino *au_xino_alloc(unsigned int nfile); ++int au_xino_put(struct au_branch *br); ++struct file *au_xino_file1(struct au_xino *xi); ++ ++struct au_opt_xino; ++void au_xino_clr(struct super_block *sb); ++int au_xino_set(struct super_block *sb, struct au_opt_xino *xiopt, int remount); ++struct file *au_xino_def(struct super_block *sb); ++int au_xino_init_br(struct super_block *sb, struct au_branch *br, ino_t hino, ++ struct path *base); ++ ++ino_t au_xino_new_ino(struct super_block *sb); ++void au_xino_delete_inode(struct inode *inode, const int unlinked); ++ ++void au_xinondir_leave(struct super_block *sb, aufs_bindex_t bindex, ++ ino_t h_ino, int idx); ++int au_xinondir_enter(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, ++ int *idx); ++ ++int au_xino_path(struct seq_file *seq, struct file *file); ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* @idx is signed to accept -1 meaning the first file */ ++static inline struct file *au_xino_file(struct au_xino *xi, int idx) ++{ ++ struct file *file; ++ ++ file = NULL; ++ if (!xi) ++ goto out; ++ ++ if (idx >= 0) { ++ if (idx < xi->xi_nfile) ++ file = xi->xi_file[idx]; ++ } else ++ file = au_xino_file1(xi); ++ ++out: ++ return file; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* Superblock to branch */ ++static inline ++aufs_bindex_t au_sbr_id(struct super_block *sb, aufs_bindex_t bindex) ++{ ++ return au_sbr(sb, bindex)->br_id; ++} ++ ++static inline ++struct vfsmount *au_sbr_mnt(struct super_block *sb, aufs_bindex_t bindex) ++{ ++ return au_br_mnt(au_sbr(sb, bindex)); ++} ++ ++static inline ++struct super_block *au_sbr_sb(struct super_block *sb, aufs_bindex_t bindex) ++{ ++ return au_br_sb(au_sbr(sb, bindex)); ++} ++ ++static inline int au_sbr_perm(struct super_block *sb, aufs_bindex_t bindex) ++{ ++ return au_sbr(sb, bindex)->br_perm; ++} ++ ++static inline int au_sbr_whable(struct super_block *sb, aufs_bindex_t bindex) ++{ ++ return au_br_whable(au_sbr_perm(sb, bindex)); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++#define wbr_wh_read_lock(wbr) au_rw_read_lock(&(wbr)->wbr_wh_rwsem) ++#define wbr_wh_write_lock(wbr) au_rw_write_lock(&(wbr)->wbr_wh_rwsem) ++#define wbr_wh_read_trylock(wbr) au_rw_read_trylock(&(wbr)->wbr_wh_rwsem) ++#define wbr_wh_write_trylock(wbr) au_rw_write_trylock(&(wbr)->wbr_wh_rwsem) ++/* ++#define wbr_wh_read_trylock_nested(wbr) \ ++ au_rw_read_trylock_nested(&(wbr)->wbr_wh_rwsem) ++#define wbr_wh_write_trylock_nested(wbr) \ ++ au_rw_write_trylock_nested(&(wbr)->wbr_wh_rwsem) ++*/ ++ ++#define wbr_wh_read_unlock(wbr) au_rw_read_unlock(&(wbr)->wbr_wh_rwsem) ++#define wbr_wh_write_unlock(wbr) au_rw_write_unlock(&(wbr)->wbr_wh_rwsem) ++#define wbr_wh_downgrade_lock(wbr) au_rw_dgrade_lock(&(wbr)->wbr_wh_rwsem) ++ ++#define WbrWhMustNoWaiters(wbr) AuRwMustNoWaiters(&(wbr)->wbr_wh_rwsem) ++#define WbrWhMustAnyLock(wbr) AuRwMustAnyLock(&(wbr)->wbr_wh_rwsem) ++#define WbrWhMustWriteLock(wbr) AuRwMustWriteLock(&(wbr)->wbr_wh_rwsem) ++ ++/* ---------------------------------------------------------------------- */ ++ ++#ifdef CONFIG_AUFS_FHSM ++static inline void au_br_fhsm_init(struct au_br_fhsm *brfhsm) ++{ ++ mutex_init(&brfhsm->bf_lock); ++ brfhsm->bf_jiffy = 0; ++ brfhsm->bf_readable = 0; ++} ++ ++static inline void au_br_fhsm_fin(struct au_br_fhsm *brfhsm) ++{ ++ mutex_destroy(&brfhsm->bf_lock); ++} ++#else ++AuStubVoid(au_br_fhsm_init, struct au_br_fhsm *brfhsm) ++AuStubVoid(au_br_fhsm_fin, struct au_br_fhsm *brfhsm) ++#endif ++ ++#endif /* __KERNEL__ */ ++#endif /* __AUFS_BRANCH_H__ */ +diff -Nurp linux-5.4/fs/aufs/cpup.c linux-5.4-aufs/fs/aufs/cpup.c +--- linux-5.4/fs/aufs/cpup.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/cpup.c 2019-11-28 01:25:59.063925618 +0200 +@@ -0,0 +1,1445 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * copy-up functions, see wbr_policy.c for copy-down ++ */ ++ ++#include ++#include ++#include ++#include "aufs.h" ++ ++void au_cpup_attr_flags(struct inode *dst, unsigned int iflags) ++{ ++ const unsigned int mask = S_DEAD | S_SWAPFILE | S_PRIVATE ++ | S_NOATIME | S_NOCMTIME | S_AUTOMOUNT; ++ ++ BUILD_BUG_ON(sizeof(iflags) != sizeof(dst->i_flags)); ++ ++ dst->i_flags |= iflags & ~mask; ++ if (au_test_fs_notime(dst->i_sb)) ++ dst->i_flags |= S_NOATIME | S_NOCMTIME; ++} ++ ++void au_cpup_attr_timesizes(struct inode *inode) ++{ ++ struct inode *h_inode; ++ ++ h_inode = au_h_iptr(inode, au_ibtop(inode)); ++ fsstack_copy_attr_times(inode, h_inode); ++ fsstack_copy_inode_size(inode, h_inode); ++} ++ ++void au_cpup_attr_nlink(struct inode *inode, int force) ++{ ++ struct inode *h_inode; ++ struct super_block *sb; ++ aufs_bindex_t bindex, bbot; ++ ++ sb = inode->i_sb; ++ bindex = au_ibtop(inode); ++ h_inode = au_h_iptr(inode, bindex); ++ if (!force ++ && !S_ISDIR(h_inode->i_mode) ++ && au_opt_test(au_mntflags(sb), PLINK) ++ && au_plink_test(inode)) ++ return; ++ ++ /* ++ * 0 can happen in revalidating. ++ * h_inode->i_mutex may not be held here, but it is harmless since once ++ * i_nlink reaches 0, it will never become positive except O_TMPFILE ++ * case. ++ * todo: O_TMPFILE+linkat(AT_SYMLINK_FOLLOW) bypassing aufs may cause ++ * the incorrect link count. ++ */ ++ set_nlink(inode, h_inode->i_nlink); ++ ++ /* ++ * fewer nlink makes find(1) noisy, but larger nlink doesn't. ++ * it may includes whplink directory. ++ */ ++ if (S_ISDIR(h_inode->i_mode)) { ++ bbot = au_ibbot(inode); ++ for (bindex++; bindex <= bbot; bindex++) { ++ h_inode = au_h_iptr(inode, bindex); ++ if (h_inode) ++ au_add_nlink(inode, h_inode); ++ } ++ } ++} ++ ++void au_cpup_attr_changeable(struct inode *inode) ++{ ++ struct inode *h_inode; ++ ++ h_inode = au_h_iptr(inode, au_ibtop(inode)); ++ inode->i_mode = h_inode->i_mode; ++ inode->i_uid = h_inode->i_uid; ++ inode->i_gid = h_inode->i_gid; ++ au_cpup_attr_timesizes(inode); ++ au_cpup_attr_flags(inode, h_inode->i_flags); ++} ++ ++void au_cpup_igen(struct inode *inode, struct inode *h_inode) ++{ ++ struct au_iinfo *iinfo = au_ii(inode); ++ ++ IiMustWriteLock(inode); ++ ++ iinfo->ii_higen = h_inode->i_generation; ++ iinfo->ii_hsb1 = h_inode->i_sb; ++} ++ ++void au_cpup_attr_all(struct inode *inode, int force) ++{ ++ struct inode *h_inode; ++ ++ h_inode = au_h_iptr(inode, au_ibtop(inode)); ++ au_cpup_attr_changeable(inode); ++ if (inode->i_nlink > 0) ++ au_cpup_attr_nlink(inode, force); ++ inode->i_rdev = h_inode->i_rdev; ++ inode->i_blkbits = h_inode->i_blkbits; ++ au_cpup_igen(inode, h_inode); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* Note: dt_dentry and dt_h_dentry are not dget/dput-ed */ ++ ++/* keep the timestamps of the parent dir when cpup */ ++void au_dtime_store(struct au_dtime *dt, struct dentry *dentry, ++ struct path *h_path) ++{ ++ struct inode *h_inode; ++ ++ dt->dt_dentry = dentry; ++ dt->dt_h_path = *h_path; ++ h_inode = d_inode(h_path->dentry); ++ dt->dt_atime = h_inode->i_atime; ++ dt->dt_mtime = h_inode->i_mtime; ++ /* smp_mb(); */ ++} ++ ++void au_dtime_revert(struct au_dtime *dt) ++{ ++ struct iattr attr; ++ int err; ++ ++ attr.ia_atime = dt->dt_atime; ++ attr.ia_mtime = dt->dt_mtime; ++ attr.ia_valid = ATTR_FORCE | ATTR_MTIME | ATTR_MTIME_SET ++ | ATTR_ATIME | ATTR_ATIME_SET; ++ ++ /* no delegation since this is a directory */ ++ err = vfsub_notify_change(&dt->dt_h_path, &attr, /*delegated*/NULL); ++ if (unlikely(err)) ++ pr_warn("restoring timestamps failed(%d). ignored\n", err); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* internal use only */ ++struct au_cpup_reg_attr { ++ int valid; ++ struct kstat st; ++ unsigned int iflags; /* inode->i_flags */ ++}; ++ ++static noinline_for_stack ++int cpup_iattr(struct dentry *dst, aufs_bindex_t bindex, struct dentry *h_src, ++ struct au_cpup_reg_attr *h_src_attr) ++{ ++ int err, sbits, icex; ++ unsigned int mnt_flags; ++ unsigned char verbose; ++ struct iattr ia; ++ struct path h_path; ++ struct inode *h_isrc, *h_idst; ++ struct kstat *h_st; ++ struct au_branch *br; ++ ++ h_path.dentry = au_h_dptr(dst, bindex); ++ h_idst = d_inode(h_path.dentry); ++ br = au_sbr(dst->d_sb, bindex); ++ h_path.mnt = au_br_mnt(br); ++ h_isrc = d_inode(h_src); ++ ia.ia_valid = ATTR_FORCE | ATTR_UID | ATTR_GID ++ | ATTR_ATIME | ATTR_MTIME ++ | ATTR_ATIME_SET | ATTR_MTIME_SET; ++ if (h_src_attr && h_src_attr->valid) { ++ h_st = &h_src_attr->st; ++ ia.ia_uid = h_st->uid; ++ ia.ia_gid = h_st->gid; ++ ia.ia_atime = h_st->atime; ++ ia.ia_mtime = h_st->mtime; ++ if (h_idst->i_mode != h_st->mode ++ && !S_ISLNK(h_idst->i_mode)) { ++ ia.ia_valid |= ATTR_MODE; ++ ia.ia_mode = h_st->mode; ++ } ++ sbits = !!(h_st->mode & (S_ISUID | S_ISGID)); ++ au_cpup_attr_flags(h_idst, h_src_attr->iflags); ++ } else { ++ ia.ia_uid = h_isrc->i_uid; ++ ia.ia_gid = h_isrc->i_gid; ++ ia.ia_atime = h_isrc->i_atime; ++ ia.ia_mtime = h_isrc->i_mtime; ++ if (h_idst->i_mode != h_isrc->i_mode ++ && !S_ISLNK(h_idst->i_mode)) { ++ ia.ia_valid |= ATTR_MODE; ++ ia.ia_mode = h_isrc->i_mode; ++ } ++ sbits = !!(h_isrc->i_mode & (S_ISUID | S_ISGID)); ++ au_cpup_attr_flags(h_idst, h_isrc->i_flags); ++ } ++ /* no delegation since it is just created */ ++ err = vfsub_notify_change(&h_path, &ia, /*delegated*/NULL); ++ ++ /* is this nfs only? */ ++ if (!err && sbits && au_test_nfs(h_path.dentry->d_sb)) { ++ ia.ia_valid = ATTR_FORCE | ATTR_MODE; ++ ia.ia_mode = h_isrc->i_mode; ++ err = vfsub_notify_change(&h_path, &ia, /*delegated*/NULL); ++ } ++ ++ icex = br->br_perm & AuBrAttr_ICEX; ++ if (!err) { ++ mnt_flags = au_mntflags(dst->d_sb); ++ verbose = !!au_opt_test(mnt_flags, VERBOSE); ++ err = au_cpup_xattr(h_path.dentry, h_src, icex, verbose); ++ } ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int au_do_copy_file(struct file *dst, struct file *src, loff_t len, ++ char *buf, unsigned long blksize) ++{ ++ int err; ++ size_t sz, rbytes, wbytes; ++ unsigned char all_zero; ++ char *p, *zp; ++ struct inode *h_inode; ++ /* reduce stack usage */ ++ struct iattr *ia; ++ ++ zp = page_address(ZERO_PAGE(0)); ++ if (unlikely(!zp)) ++ return -ENOMEM; /* possible? */ ++ ++ err = 0; ++ all_zero = 0; ++ while (len) { ++ AuDbg("len %lld\n", len); ++ sz = blksize; ++ if (len < blksize) ++ sz = len; ++ ++ rbytes = 0; ++ /* todo: signal_pending? */ ++ while (!rbytes || err == -EAGAIN || err == -EINTR) { ++ rbytes = vfsub_read_k(src, buf, sz, &src->f_pos); ++ err = rbytes; ++ } ++ if (unlikely(err < 0)) ++ break; ++ ++ all_zero = 0; ++ if (len >= rbytes && rbytes == blksize) ++ all_zero = !memcmp(buf, zp, rbytes); ++ if (!all_zero) { ++ wbytes = rbytes; ++ p = buf; ++ while (wbytes) { ++ size_t b; ++ ++ b = vfsub_write_k(dst, p, wbytes, &dst->f_pos); ++ err = b; ++ /* todo: signal_pending? */ ++ if (unlikely(err == -EAGAIN || err == -EINTR)) ++ continue; ++ if (unlikely(err < 0)) ++ break; ++ wbytes -= b; ++ p += b; ++ } ++ if (unlikely(err < 0)) ++ break; ++ } else { ++ loff_t res; ++ ++ AuLabel(hole); ++ res = vfsub_llseek(dst, rbytes, SEEK_CUR); ++ err = res; ++ if (unlikely(res < 0)) ++ break; ++ } ++ len -= rbytes; ++ err = 0; ++ } ++ ++ /* the last block may be a hole */ ++ if (!err && all_zero) { ++ AuLabel(last hole); ++ ++ err = 1; ++ if (au_test_nfs(dst->f_path.dentry->d_sb)) { ++ /* nfs requires this step to make last hole */ ++ /* is this only nfs? */ ++ do { ++ /* todo: signal_pending? */ ++ err = vfsub_write_k(dst, "\0", 1, &dst->f_pos); ++ } while (err == -EAGAIN || err == -EINTR); ++ if (err == 1) ++ dst->f_pos--; ++ } ++ ++ if (err == 1) { ++ ia = (void *)buf; ++ ia->ia_size = dst->f_pos; ++ ia->ia_valid = ATTR_SIZE | ATTR_FILE; ++ ia->ia_file = dst; ++ h_inode = file_inode(dst); ++ inode_lock_nested(h_inode, AuLsc_I_CHILD2); ++ /* no delegation since it is just created */ ++ err = vfsub_notify_change(&dst->f_path, ia, ++ /*delegated*/NULL); ++ inode_unlock(h_inode); ++ } ++ } ++ ++ return err; ++} ++ ++int au_copy_file(struct file *dst, struct file *src, loff_t len) ++{ ++ int err; ++ unsigned long blksize; ++ unsigned char do_kfree; ++ char *buf; ++ struct super_block *h_sb; ++ ++ err = -ENOMEM; ++ h_sb = file_inode(dst)->i_sb; ++ blksize = h_sb->s_blocksize; ++ if (!blksize || PAGE_SIZE < blksize) ++ blksize = PAGE_SIZE; ++ AuDbg("blksize %lu\n", blksize); ++ do_kfree = (blksize != PAGE_SIZE && blksize >= sizeof(struct iattr *)); ++ if (do_kfree) ++ buf = kmalloc(blksize, GFP_NOFS); ++ else ++ buf = (void *)__get_free_page(GFP_NOFS); ++ if (unlikely(!buf)) ++ goto out; ++ ++ if (len > (1 << 22)) ++ AuDbg("copying a large file %lld\n", (long long)len); ++ ++ src->f_pos = 0; ++ dst->f_pos = 0; ++ err = au_do_copy_file(dst, src, len, buf, blksize); ++ if (do_kfree) { ++ AuDebugOn(!au_kfree_do_sz_test(blksize)); ++ au_kfree_do_rcu(buf); ++ } else ++ free_page((unsigned long)buf); ++ ++out: ++ return err; ++} ++ ++static int au_do_copy(struct file *dst, struct file *src, loff_t len) ++{ ++ int err; ++ struct super_block *h_src_sb; ++ struct inode *h_src_inode; ++ ++ h_src_inode = file_inode(src); ++ h_src_sb = h_src_inode->i_sb; ++ ++ /* XFS acquires inode_lock */ ++ if (!au_test_xfs(h_src_sb)) ++ err = au_copy_file(dst, src, len); ++ else { ++ inode_unlock_shared(h_src_inode); ++ err = au_copy_file(dst, src, len); ++ inode_lock_shared_nested(h_src_inode, AuLsc_I_CHILD); ++ } ++ ++ return err; ++} ++ ++static int au_clone_or_copy(struct file *dst, struct file *src, loff_t len) ++{ ++ int err; ++ loff_t lo; ++ struct super_block *h_src_sb; ++ struct inode *h_src_inode; ++ ++ h_src_inode = file_inode(src); ++ h_src_sb = h_src_inode->i_sb; ++ if (h_src_sb != file_inode(dst)->i_sb ++ || !dst->f_op->remap_file_range) { ++ err = au_do_copy(dst, src, len); ++ goto out; ++ } ++ ++ if (!au_test_nfs(h_src_sb)) { ++ inode_unlock_shared(h_src_inode); ++ lo = vfsub_clone_file_range(src, dst, len); ++ inode_lock_shared_nested(h_src_inode, AuLsc_I_CHILD); ++ } else ++ lo = vfsub_clone_file_range(src, dst, len); ++ if (lo == len) { ++ err = 0; ++ goto out; /* success */ ++ } else if (lo >= 0) ++ /* todo: possible? */ ++ /* paritially succeeded */ ++ AuDbg("lo %lld, len %lld. Retrying.\n", lo, len); ++ else if (lo != -EOPNOTSUPP) { ++ /* older XFS has a condition in cloning */ ++ err = lo; ++ goto out; ++ } ++ ++ /* the backend fs on NFS may not support cloning */ ++ err = au_do_copy(dst, src, len); ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++/* ++ * to support a sparse file which is opened with O_APPEND, ++ * we need to close the file. ++ */ ++static int au_cp_regular(struct au_cp_generic *cpg) ++{ ++ int err, i; ++ enum { SRC, DST }; ++ struct { ++ aufs_bindex_t bindex; ++ unsigned int flags; ++ struct dentry *dentry; ++ int force_wr; ++ struct file *file; ++ } *f, file[] = { ++ { ++ .bindex = cpg->bsrc, ++ .flags = O_RDONLY | O_NOATIME | O_LARGEFILE, ++ }, ++ { ++ .bindex = cpg->bdst, ++ .flags = O_WRONLY | O_NOATIME | O_LARGEFILE, ++ .force_wr = !!au_ftest_cpup(cpg->flags, RWDST), ++ } ++ }; ++ struct au_branch *br; ++ struct super_block *sb, *h_src_sb; ++ struct inode *h_src_inode; ++ struct task_struct *tsk = current; ++ ++ /* bsrc branch can be ro/rw. */ ++ sb = cpg->dentry->d_sb; ++ f = file; ++ for (i = 0; i < 2; i++, f++) { ++ f->dentry = au_h_dptr(cpg->dentry, f->bindex); ++ f->file = au_h_open(cpg->dentry, f->bindex, f->flags, ++ /*file*/NULL, f->force_wr); ++ if (IS_ERR(f->file)) { ++ err = PTR_ERR(f->file); ++ if (i == SRC) ++ goto out; ++ else ++ goto out_src; ++ } ++ } ++ ++ /* try stopping to update while we copyup */ ++ h_src_inode = d_inode(file[SRC].dentry); ++ h_src_sb = h_src_inode->i_sb; ++ if (!au_test_nfs(h_src_sb)) ++ IMustLock(h_src_inode); ++ err = au_clone_or_copy(file[DST].file, file[SRC].file, cpg->len); ++ ++ /* i wonder if we had O_NO_DELAY_FPUT flag */ ++ if (tsk->flags & PF_KTHREAD) ++ __fput_sync(file[DST].file); ++ else { ++ /* it happened actually */ ++ fput(file[DST].file); ++ /* ++ * too bad. ++ * we have to call both since we don't know which place the file ++ * was added to. ++ */ ++ task_work_run(); ++ flush_delayed_fput(); ++ } ++ br = au_sbr(sb, file[DST].bindex); ++ au_lcnt_dec(&br->br_nfiles); ++ ++out_src: ++ fput(file[SRC].file); ++ br = au_sbr(sb, file[SRC].bindex); ++ au_lcnt_dec(&br->br_nfiles); ++out: ++ return err; ++} ++ ++static int au_do_cpup_regular(struct au_cp_generic *cpg, ++ struct au_cpup_reg_attr *h_src_attr) ++{ ++ int err, rerr; ++ loff_t l; ++ struct path h_path; ++ struct inode *h_src_inode, *h_dst_inode; ++ ++ err = 0; ++ h_src_inode = au_h_iptr(d_inode(cpg->dentry), cpg->bsrc); ++ l = i_size_read(h_src_inode); ++ if (cpg->len == -1 || l < cpg->len) ++ cpg->len = l; ++ if (cpg->len) { ++ /* try stopping to update while we are referencing */ ++ inode_lock_shared_nested(h_src_inode, AuLsc_I_CHILD); ++ au_pin_hdir_unlock(cpg->pin); ++ ++ h_path.dentry = au_h_dptr(cpg->dentry, cpg->bsrc); ++ h_path.mnt = au_sbr_mnt(cpg->dentry->d_sb, cpg->bsrc); ++ h_src_attr->iflags = h_src_inode->i_flags; ++ if (!au_test_nfs(h_src_inode->i_sb)) ++ err = vfsub_getattr(&h_path, &h_src_attr->st); ++ else { ++ inode_unlock_shared(h_src_inode); ++ err = vfsub_getattr(&h_path, &h_src_attr->st); ++ inode_lock_shared_nested(h_src_inode, AuLsc_I_CHILD); ++ } ++ if (unlikely(err)) { ++ inode_unlock_shared(h_src_inode); ++ goto out; ++ } ++ h_src_attr->valid = 1; ++ if (!au_test_nfs(h_src_inode->i_sb)) { ++ err = au_cp_regular(cpg); ++ inode_unlock_shared(h_src_inode); ++ } else { ++ inode_unlock_shared(h_src_inode); ++ err = au_cp_regular(cpg); ++ } ++ rerr = au_pin_hdir_relock(cpg->pin); ++ if (!err && rerr) ++ err = rerr; ++ } ++ if (!err && (h_src_inode->i_state & I_LINKABLE)) { ++ h_path.dentry = au_h_dptr(cpg->dentry, cpg->bdst); ++ h_dst_inode = d_inode(h_path.dentry); ++ spin_lock(&h_dst_inode->i_lock); ++ h_dst_inode->i_state |= I_LINKABLE; ++ spin_unlock(&h_dst_inode->i_lock); ++ } ++ ++out: ++ return err; ++} ++ ++static int au_do_cpup_symlink(struct path *h_path, struct dentry *h_src, ++ struct inode *h_dir) ++{ ++ int err, symlen; ++ mm_segment_t old_fs; ++ union { ++ char *k; ++ char __user *u; ++ } sym; ++ ++ err = -ENOMEM; ++ sym.k = (void *)__get_free_page(GFP_NOFS); ++ if (unlikely(!sym.k)) ++ goto out; ++ ++ /* unnecessary to support mmap_sem since symlink is not mmap-able */ ++ old_fs = get_fs(); ++ set_fs(KERNEL_DS); ++ symlen = vfs_readlink(h_src, sym.u, PATH_MAX); ++ err = symlen; ++ set_fs(old_fs); ++ ++ if (symlen > 0) { ++ sym.k[symlen] = 0; ++ err = vfsub_symlink(h_dir, h_path, sym.k); ++ } ++ free_page((unsigned long)sym.k); ++ ++out: ++ return err; ++} ++ ++/* ++ * regardless 'acl' option, reset all ACL. ++ * All ACL will be copied up later from the original entry on the lower branch. ++ */ ++static int au_reset_acl(struct inode *h_dir, struct path *h_path, umode_t mode) ++{ ++ int err; ++ struct dentry *h_dentry; ++ struct inode *h_inode; ++ ++ h_dentry = h_path->dentry; ++ h_inode = d_inode(h_dentry); ++ /* forget_all_cached_acls(h_inode)); */ ++ err = vfsub_removexattr(h_dentry, XATTR_NAME_POSIX_ACL_ACCESS); ++ AuTraceErr(err); ++ if (err == -EOPNOTSUPP) ++ err = 0; ++ if (!err) ++ err = vfsub_acl_chmod(h_inode, mode); ++ ++ AuTraceErr(err); ++ return err; ++} ++ ++static int au_do_cpup_dir(struct au_cp_generic *cpg, struct dentry *dst_parent, ++ struct inode *h_dir, struct path *h_path) ++{ ++ int err; ++ struct inode *dir, *inode; ++ ++ err = vfsub_removexattr(h_path->dentry, XATTR_NAME_POSIX_ACL_DEFAULT); ++ AuTraceErr(err); ++ if (err == -EOPNOTSUPP) ++ err = 0; ++ if (unlikely(err)) ++ goto out; ++ ++ /* ++ * strange behaviour from the users view, ++ * particularly setattr case ++ */ ++ dir = d_inode(dst_parent); ++ if (au_ibtop(dir) == cpg->bdst) ++ au_cpup_attr_nlink(dir, /*force*/1); ++ inode = d_inode(cpg->dentry); ++ au_cpup_attr_nlink(inode, /*force*/1); ++ ++out: ++ return err; ++} ++ ++static noinline_for_stack ++int cpup_entry(struct au_cp_generic *cpg, struct dentry *dst_parent, ++ struct au_cpup_reg_attr *h_src_attr) ++{ ++ int err; ++ umode_t mode; ++ unsigned int mnt_flags; ++ unsigned char isdir, isreg, force; ++ const unsigned char do_dt = !!au_ftest_cpup(cpg->flags, DTIME); ++ struct au_dtime dt; ++ struct path h_path; ++ struct dentry *h_src, *h_dst, *h_parent; ++ struct inode *h_inode, *h_dir; ++ struct super_block *sb; ++ ++ /* bsrc branch can be ro/rw. */ ++ h_src = au_h_dptr(cpg->dentry, cpg->bsrc); ++ h_inode = d_inode(h_src); ++ AuDebugOn(h_inode != au_h_iptr(d_inode(cpg->dentry), cpg->bsrc)); ++ ++ /* try stopping to be referenced while we are creating */ ++ h_dst = au_h_dptr(cpg->dentry, cpg->bdst); ++ if (au_ftest_cpup(cpg->flags, RENAME)) ++ AuDebugOn(strncmp(h_dst->d_name.name, AUFS_WH_PFX, ++ AUFS_WH_PFX_LEN)); ++ h_parent = h_dst->d_parent; /* dir inode is locked */ ++ h_dir = d_inode(h_parent); ++ IMustLock(h_dir); ++ AuDebugOn(h_parent != h_dst->d_parent); ++ ++ sb = cpg->dentry->d_sb; ++ h_path.mnt = au_sbr_mnt(sb, cpg->bdst); ++ if (do_dt) { ++ h_path.dentry = h_parent; ++ au_dtime_store(&dt, dst_parent, &h_path); ++ } ++ h_path.dentry = h_dst; ++ ++ isreg = 0; ++ isdir = 0; ++ mode = h_inode->i_mode; ++ switch (mode & S_IFMT) { ++ case S_IFREG: ++ isreg = 1; ++ err = vfsub_create(h_dir, &h_path, 0600, /*want_excl*/true); ++ if (!err) ++ err = au_do_cpup_regular(cpg, h_src_attr); ++ break; ++ case S_IFDIR: ++ isdir = 1; ++ err = vfsub_mkdir(h_dir, &h_path, mode); ++ if (!err) ++ err = au_do_cpup_dir(cpg, dst_parent, h_dir, &h_path); ++ break; ++ case S_IFLNK: ++ err = au_do_cpup_symlink(&h_path, h_src, h_dir); ++ break; ++ case S_IFCHR: ++ case S_IFBLK: ++ AuDebugOn(!capable(CAP_MKNOD)); ++ /*FALLTHROUGH*/ ++ case S_IFIFO: ++ case S_IFSOCK: ++ err = vfsub_mknod(h_dir, &h_path, mode, h_inode->i_rdev); ++ break; ++ default: ++ AuIOErr("Unknown inode type 0%o\n", mode); ++ err = -EIO; ++ } ++ if (!err) ++ err = au_reset_acl(h_dir, &h_path, mode); ++ ++ mnt_flags = au_mntflags(sb); ++ if (!au_opt_test(mnt_flags, UDBA_NONE) ++ && !isdir ++ && au_opt_test(mnt_flags, XINO) ++ && (h_inode->i_nlink == 1 ++ || (h_inode->i_state & I_LINKABLE)) ++ /* todo: unnecessary? */ ++ /* && d_inode(cpg->dentry)->i_nlink == 1 */ ++ && cpg->bdst < cpg->bsrc ++ && !au_ftest_cpup(cpg->flags, KEEPLINO)) ++ au_xino_write(sb, cpg->bsrc, h_inode->i_ino, /*ino*/0); ++ /* ignore this error */ ++ ++ if (!err) { ++ force = 0; ++ if (isreg) { ++ force = !!cpg->len; ++ if (cpg->len == -1) ++ force = !!i_size_read(h_inode); ++ } ++ au_fhsm_wrote(sb, cpg->bdst, force); ++ } ++ ++ if (do_dt) ++ au_dtime_revert(&dt); ++ return err; ++} ++ ++static int au_do_ren_after_cpup(struct au_cp_generic *cpg, struct path *h_path) ++{ ++ int err; ++ struct dentry *dentry, *h_dentry, *h_parent, *parent; ++ struct inode *h_dir; ++ aufs_bindex_t bdst; ++ ++ dentry = cpg->dentry; ++ bdst = cpg->bdst; ++ h_dentry = au_h_dptr(dentry, bdst); ++ if (!au_ftest_cpup(cpg->flags, OVERWRITE)) { ++ dget(h_dentry); ++ au_set_h_dptr(dentry, bdst, NULL); ++ err = au_lkup_neg(dentry, bdst, /*wh*/0); ++ if (!err) ++ h_path->dentry = dget(au_h_dptr(dentry, bdst)); ++ au_set_h_dptr(dentry, bdst, h_dentry); ++ } else { ++ err = 0; ++ parent = dget_parent(dentry); ++ h_parent = au_h_dptr(parent, bdst); ++ dput(parent); ++ h_path->dentry = vfsub_lkup_one(&dentry->d_name, h_parent); ++ if (IS_ERR(h_path->dentry)) ++ err = PTR_ERR(h_path->dentry); ++ } ++ if (unlikely(err)) ++ goto out; ++ ++ h_parent = h_dentry->d_parent; /* dir inode is locked */ ++ h_dir = d_inode(h_parent); ++ IMustLock(h_dir); ++ AuDbg("%pd %pd\n", h_dentry, h_path->dentry); ++ /* no delegation since it is just created */ ++ err = vfsub_rename(h_dir, h_dentry, h_dir, h_path, /*delegated*/NULL, ++ /*flags*/0); ++ dput(h_path->dentry); ++ ++out: ++ return err; ++} ++ ++/* ++ * copyup the @dentry from @bsrc to @bdst. ++ * the caller must set the both of lower dentries. ++ * @len is for truncating when it is -1 copyup the entire file. ++ * in link/rename cases, @dst_parent may be different from the real one. ++ * basic->bsrc can be larger than basic->bdst. ++ * aufs doesn't touch the credential so ++ * security_inode_copy_up{,_xattr}() are unnecessary. ++ */ ++static int au_cpup_single(struct au_cp_generic *cpg, struct dentry *dst_parent) ++{ ++ int err, rerr; ++ aufs_bindex_t old_ibtop; ++ unsigned char isdir, plink; ++ struct dentry *h_src, *h_dst, *h_parent; ++ struct inode *dst_inode, *h_dir, *inode, *delegated, *src_inode; ++ struct super_block *sb; ++ struct au_branch *br; ++ /* to reduce stack size */ ++ struct { ++ struct au_dtime dt; ++ struct path h_path; ++ struct au_cpup_reg_attr h_src_attr; ++ } *a; ++ ++ err = -ENOMEM; ++ a = kmalloc(sizeof(*a), GFP_NOFS); ++ if (unlikely(!a)) ++ goto out; ++ a->h_src_attr.valid = 0; ++ ++ sb = cpg->dentry->d_sb; ++ br = au_sbr(sb, cpg->bdst); ++ a->h_path.mnt = au_br_mnt(br); ++ h_dst = au_h_dptr(cpg->dentry, cpg->bdst); ++ h_parent = h_dst->d_parent; /* dir inode is locked */ ++ h_dir = d_inode(h_parent); ++ IMustLock(h_dir); ++ ++ h_src = au_h_dptr(cpg->dentry, cpg->bsrc); ++ inode = d_inode(cpg->dentry); ++ ++ if (!dst_parent) ++ dst_parent = dget_parent(cpg->dentry); ++ else ++ dget(dst_parent); ++ ++ plink = !!au_opt_test(au_mntflags(sb), PLINK); ++ dst_inode = au_h_iptr(inode, cpg->bdst); ++ if (dst_inode) { ++ if (unlikely(!plink)) { ++ err = -EIO; ++ AuIOErr("hi%lu(i%lu) exists on b%d " ++ "but plink is disabled\n", ++ dst_inode->i_ino, inode->i_ino, cpg->bdst); ++ goto out_parent; ++ } ++ ++ if (dst_inode->i_nlink) { ++ const int do_dt = au_ftest_cpup(cpg->flags, DTIME); ++ ++ h_src = au_plink_lkup(inode, cpg->bdst); ++ err = PTR_ERR(h_src); ++ if (IS_ERR(h_src)) ++ goto out_parent; ++ if (unlikely(d_is_negative(h_src))) { ++ err = -EIO; ++ AuIOErr("i%lu exists on b%d " ++ "but not pseudo-linked\n", ++ inode->i_ino, cpg->bdst); ++ dput(h_src); ++ goto out_parent; ++ } ++ ++ if (do_dt) { ++ a->h_path.dentry = h_parent; ++ au_dtime_store(&a->dt, dst_parent, &a->h_path); ++ } ++ ++ a->h_path.dentry = h_dst; ++ delegated = NULL; ++ err = vfsub_link(h_src, h_dir, &a->h_path, &delegated); ++ if (!err && au_ftest_cpup(cpg->flags, RENAME)) ++ err = au_do_ren_after_cpup(cpg, &a->h_path); ++ if (do_dt) ++ au_dtime_revert(&a->dt); ++ if (unlikely(err == -EWOULDBLOCK)) { ++ pr_warn("cannot retry for NFSv4 delegation" ++ " for an internal link\n"); ++ iput(delegated); ++ } ++ dput(h_src); ++ goto out_parent; ++ } else ++ /* todo: cpup_wh_file? */ ++ /* udba work */ ++ au_update_ibrange(inode, /*do_put_zero*/1); ++ } ++ ++ isdir = S_ISDIR(inode->i_mode); ++ old_ibtop = au_ibtop(inode); ++ err = cpup_entry(cpg, dst_parent, &a->h_src_attr); ++ if (unlikely(err)) ++ goto out_rev; ++ dst_inode = d_inode(h_dst); ++ inode_lock_nested(dst_inode, AuLsc_I_CHILD2); ++ /* todo: necessary? */ ++ /* au_pin_hdir_unlock(cpg->pin); */ ++ ++ err = cpup_iattr(cpg->dentry, cpg->bdst, h_src, &a->h_src_attr); ++ if (unlikely(err)) { ++ /* todo: necessary? */ ++ /* au_pin_hdir_relock(cpg->pin); */ /* ignore an error */ ++ inode_unlock(dst_inode); ++ goto out_rev; ++ } ++ ++ if (cpg->bdst < old_ibtop) { ++ if (S_ISREG(inode->i_mode)) { ++ err = au_dy_iaop(inode, cpg->bdst, dst_inode); ++ if (unlikely(err)) { ++ /* ignore an error */ ++ /* au_pin_hdir_relock(cpg->pin); */ ++ inode_unlock(dst_inode); ++ goto out_rev; ++ } ++ } ++ au_set_ibtop(inode, cpg->bdst); ++ } else ++ au_set_ibbot(inode, cpg->bdst); ++ au_set_h_iptr(inode, cpg->bdst, au_igrab(dst_inode), ++ au_hi_flags(inode, isdir)); ++ ++ /* todo: necessary? */ ++ /* err = au_pin_hdir_relock(cpg->pin); */ ++ inode_unlock(dst_inode); ++ if (unlikely(err)) ++ goto out_rev; ++ ++ src_inode = d_inode(h_src); ++ if (!isdir ++ && (src_inode->i_nlink > 1 ++ || src_inode->i_state & I_LINKABLE) ++ && plink) ++ au_plink_append(inode, cpg->bdst, h_dst); ++ ++ if (au_ftest_cpup(cpg->flags, RENAME)) { ++ a->h_path.dentry = h_dst; ++ err = au_do_ren_after_cpup(cpg, &a->h_path); ++ } ++ if (!err) ++ goto out_parent; /* success */ ++ ++ /* revert */ ++out_rev: ++ a->h_path.dentry = h_parent; ++ au_dtime_store(&a->dt, dst_parent, &a->h_path); ++ a->h_path.dentry = h_dst; ++ rerr = 0; ++ if (d_is_positive(h_dst)) { ++ if (!isdir) { ++ /* no delegation since it is just created */ ++ rerr = vfsub_unlink(h_dir, &a->h_path, ++ /*delegated*/NULL, /*force*/0); ++ } else ++ rerr = vfsub_rmdir(h_dir, &a->h_path); ++ } ++ au_dtime_revert(&a->dt); ++ if (rerr) { ++ AuIOErr("failed removing broken entry(%d, %d)\n", err, rerr); ++ err = -EIO; ++ } ++out_parent: ++ dput(dst_parent); ++ au_kfree_rcu(a); ++out: ++ return err; ++} ++ ++#if 0 /* reserved */ ++struct au_cpup_single_args { ++ int *errp; ++ struct au_cp_generic *cpg; ++ struct dentry *dst_parent; ++}; ++ ++static void au_call_cpup_single(void *args) ++{ ++ struct au_cpup_single_args *a = args; ++ ++ au_pin_hdir_acquire_nest(a->cpg->pin); ++ *a->errp = au_cpup_single(a->cpg, a->dst_parent); ++ au_pin_hdir_release(a->cpg->pin); ++} ++#endif ++ ++/* ++ * prevent SIGXFSZ in copy-up. ++ * testing CAP_MKNOD is for generic fs, ++ * but CAP_FSETID is for xfs only, currently. ++ */ ++static int au_cpup_sio_test(struct au_pin *pin, umode_t mode) ++{ ++ int do_sio; ++ struct super_block *sb; ++ struct inode *h_dir; ++ ++ do_sio = 0; ++ sb = au_pinned_parent(pin)->d_sb; ++ if (!au_wkq_test() ++ && (!au_sbi(sb)->si_plink_maint_pid ++ || au_plink_maint(sb, AuLock_NOPLM))) { ++ switch (mode & S_IFMT) { ++ case S_IFREG: ++ /* no condition about RLIMIT_FSIZE and the file size */ ++ do_sio = 1; ++ break; ++ case S_IFCHR: ++ case S_IFBLK: ++ do_sio = !capable(CAP_MKNOD); ++ break; ++ } ++ if (!do_sio) ++ do_sio = ((mode & (S_ISUID | S_ISGID)) ++ && !capable(CAP_FSETID)); ++ /* this workaround may be removed in the future */ ++ if (!do_sio) { ++ h_dir = au_pinned_h_dir(pin); ++ do_sio = h_dir->i_mode & S_ISVTX; ++ } ++ } ++ ++ return do_sio; ++} ++ ++#if 0 /* reserved */ ++int au_sio_cpup_single(struct au_cp_generic *cpg, struct dentry *dst_parent) ++{ ++ int err, wkq_err; ++ struct dentry *h_dentry; ++ ++ h_dentry = au_h_dptr(cpg->dentry, cpg->bsrc); ++ if (!au_cpup_sio_test(pin, d_inode(h_dentry)->i_mode)) ++ err = au_cpup_single(cpg, dst_parent); ++ else { ++ struct au_cpup_single_args args = { ++ .errp = &err, ++ .cpg = cpg, ++ .dst_parent = dst_parent ++ }; ++ wkq_err = au_wkq_wait(au_call_cpup_single, &args); ++ if (unlikely(wkq_err)) ++ err = wkq_err; ++ } ++ ++ return err; ++} ++#endif ++ ++/* ++ * copyup the @dentry from the first active lower branch to @bdst, ++ * using au_cpup_single(). ++ */ ++static int au_cpup_simple(struct au_cp_generic *cpg) ++{ ++ int err; ++ unsigned int flags_orig; ++ struct dentry *dentry; ++ ++ AuDebugOn(cpg->bsrc < 0); ++ ++ dentry = cpg->dentry; ++ DiMustWriteLock(dentry); ++ ++ err = au_lkup_neg(dentry, cpg->bdst, /*wh*/1); ++ if (!err) { ++ flags_orig = cpg->flags; ++ au_fset_cpup(cpg->flags, RENAME); ++ err = au_cpup_single(cpg, NULL); ++ cpg->flags = flags_orig; ++ if (!err) ++ return 0; /* success */ ++ ++ /* revert */ ++ au_set_h_dptr(dentry, cpg->bdst, NULL); ++ au_set_dbtop(dentry, cpg->bsrc); ++ } ++ ++ return err; ++} ++ ++struct au_cpup_simple_args { ++ int *errp; ++ struct au_cp_generic *cpg; ++}; ++ ++static void au_call_cpup_simple(void *args) ++{ ++ struct au_cpup_simple_args *a = args; ++ ++ au_pin_hdir_acquire_nest(a->cpg->pin); ++ *a->errp = au_cpup_simple(a->cpg); ++ au_pin_hdir_release(a->cpg->pin); ++} ++ ++static int au_do_sio_cpup_simple(struct au_cp_generic *cpg) ++{ ++ int err, wkq_err; ++ struct dentry *dentry, *parent; ++ struct file *h_file; ++ struct inode *h_dir; ++ ++ dentry = cpg->dentry; ++ h_file = NULL; ++ if (au_ftest_cpup(cpg->flags, HOPEN)) { ++ AuDebugOn(cpg->bsrc < 0); ++ h_file = au_h_open_pre(dentry, cpg->bsrc, /*force_wr*/0); ++ err = PTR_ERR(h_file); ++ if (IS_ERR(h_file)) ++ goto out; ++ } ++ ++ parent = dget_parent(dentry); ++ h_dir = au_h_iptr(d_inode(parent), cpg->bdst); ++ if (!au_test_h_perm_sio(h_dir, MAY_EXEC | MAY_WRITE) ++ && !au_cpup_sio_test(cpg->pin, d_inode(dentry)->i_mode)) ++ err = au_cpup_simple(cpg); ++ else { ++ struct au_cpup_simple_args args = { ++ .errp = &err, ++ .cpg = cpg ++ }; ++ wkq_err = au_wkq_wait(au_call_cpup_simple, &args); ++ if (unlikely(wkq_err)) ++ err = wkq_err; ++ } ++ ++ dput(parent); ++ if (h_file) ++ au_h_open_post(dentry, cpg->bsrc, h_file); ++ ++out: ++ return err; ++} ++ ++int au_sio_cpup_simple(struct au_cp_generic *cpg) ++{ ++ aufs_bindex_t bsrc, bbot; ++ struct dentry *dentry, *h_dentry; ++ ++ if (cpg->bsrc < 0) { ++ dentry = cpg->dentry; ++ bbot = au_dbbot(dentry); ++ for (bsrc = cpg->bdst + 1; bsrc <= bbot; bsrc++) { ++ h_dentry = au_h_dptr(dentry, bsrc); ++ if (h_dentry) { ++ AuDebugOn(d_is_negative(h_dentry)); ++ break; ++ } ++ } ++ AuDebugOn(bsrc > bbot); ++ cpg->bsrc = bsrc; ++ } ++ AuDebugOn(cpg->bsrc <= cpg->bdst); ++ return au_do_sio_cpup_simple(cpg); ++} ++ ++int au_sio_cpdown_simple(struct au_cp_generic *cpg) ++{ ++ AuDebugOn(cpg->bdst <= cpg->bsrc); ++ return au_do_sio_cpup_simple(cpg); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * copyup the deleted file for writing. ++ */ ++static int au_do_cpup_wh(struct au_cp_generic *cpg, struct dentry *wh_dentry, ++ struct file *file) ++{ ++ int err; ++ unsigned int flags_orig; ++ aufs_bindex_t bsrc_orig; ++ struct au_dinfo *dinfo; ++ struct { ++ struct au_hdentry *hd; ++ struct dentry *h_dentry; ++ } hdst, hsrc; ++ ++ dinfo = au_di(cpg->dentry); ++ AuRwMustWriteLock(&dinfo->di_rwsem); ++ ++ bsrc_orig = cpg->bsrc; ++ cpg->bsrc = dinfo->di_btop; ++ hdst.hd = au_hdentry(dinfo, cpg->bdst); ++ hdst.h_dentry = hdst.hd->hd_dentry; ++ hdst.hd->hd_dentry = wh_dentry; ++ dinfo->di_btop = cpg->bdst; ++ ++ hsrc.h_dentry = NULL; ++ if (file) { ++ hsrc.hd = au_hdentry(dinfo, cpg->bsrc); ++ hsrc.h_dentry = hsrc.hd->hd_dentry; ++ hsrc.hd->hd_dentry = au_hf_top(file)->f_path.dentry; ++ } ++ flags_orig = cpg->flags; ++ cpg->flags = !AuCpup_DTIME; ++ err = au_cpup_single(cpg, /*h_parent*/NULL); ++ cpg->flags = flags_orig; ++ if (file) { ++ if (!err) ++ err = au_reopen_nondir(file); ++ hsrc.hd->hd_dentry = hsrc.h_dentry; ++ } ++ hdst.hd->hd_dentry = hdst.h_dentry; ++ dinfo->di_btop = cpg->bsrc; ++ cpg->bsrc = bsrc_orig; ++ ++ return err; ++} ++ ++static int au_cpup_wh(struct au_cp_generic *cpg, struct file *file) ++{ ++ int err; ++ aufs_bindex_t bdst; ++ struct au_dtime dt; ++ struct dentry *dentry, *parent, *h_parent, *wh_dentry; ++ struct au_branch *br; ++ struct path h_path; ++ ++ dentry = cpg->dentry; ++ bdst = cpg->bdst; ++ br = au_sbr(dentry->d_sb, bdst); ++ parent = dget_parent(dentry); ++ h_parent = au_h_dptr(parent, bdst); ++ wh_dentry = au_whtmp_lkup(h_parent, br, &dentry->d_name); ++ err = PTR_ERR(wh_dentry); ++ if (IS_ERR(wh_dentry)) ++ goto out; ++ ++ h_path.dentry = h_parent; ++ h_path.mnt = au_br_mnt(br); ++ au_dtime_store(&dt, parent, &h_path); ++ err = au_do_cpup_wh(cpg, wh_dentry, file); ++ if (unlikely(err)) ++ goto out_wh; ++ ++ dget(wh_dentry); ++ h_path.dentry = wh_dentry; ++ if (!d_is_dir(wh_dentry)) { ++ /* no delegation since it is just created */ ++ err = vfsub_unlink(d_inode(h_parent), &h_path, ++ /*delegated*/NULL, /*force*/0); ++ } else ++ err = vfsub_rmdir(d_inode(h_parent), &h_path); ++ if (unlikely(err)) { ++ AuIOErr("failed remove copied-up tmp file %pd(%d)\n", ++ wh_dentry, err); ++ err = -EIO; ++ } ++ au_dtime_revert(&dt); ++ au_set_hi_wh(d_inode(dentry), bdst, wh_dentry); ++ ++out_wh: ++ dput(wh_dentry); ++out: ++ dput(parent); ++ return err; ++} ++ ++struct au_cpup_wh_args { ++ int *errp; ++ struct au_cp_generic *cpg; ++ struct file *file; ++}; ++ ++static void au_call_cpup_wh(void *args) ++{ ++ struct au_cpup_wh_args *a = args; ++ ++ au_pin_hdir_acquire_nest(a->cpg->pin); ++ *a->errp = au_cpup_wh(a->cpg, a->file); ++ au_pin_hdir_release(a->cpg->pin); ++} ++ ++int au_sio_cpup_wh(struct au_cp_generic *cpg, struct file *file) ++{ ++ int err, wkq_err; ++ aufs_bindex_t bdst; ++ struct dentry *dentry, *parent, *h_orph, *h_parent; ++ struct inode *dir, *h_dir, *h_tmpdir; ++ struct au_wbr *wbr; ++ struct au_pin wh_pin, *pin_orig; ++ ++ dentry = cpg->dentry; ++ bdst = cpg->bdst; ++ parent = dget_parent(dentry); ++ dir = d_inode(parent); ++ h_orph = NULL; ++ h_parent = NULL; ++ h_dir = au_igrab(au_h_iptr(dir, bdst)); ++ h_tmpdir = h_dir; ++ pin_orig = NULL; ++ if (!h_dir->i_nlink) { ++ wbr = au_sbr(dentry->d_sb, bdst)->br_wbr; ++ h_orph = wbr->wbr_orph; ++ ++ h_parent = dget(au_h_dptr(parent, bdst)); ++ au_set_h_dptr(parent, bdst, dget(h_orph)); ++ h_tmpdir = d_inode(h_orph); ++ au_set_h_iptr(dir, bdst, au_igrab(h_tmpdir), /*flags*/0); ++ ++ inode_lock_nested(h_tmpdir, AuLsc_I_PARENT3); ++ /* todo: au_h_open_pre()? */ ++ ++ pin_orig = cpg->pin; ++ au_pin_init(&wh_pin, dentry, bdst, AuLsc_DI_PARENT, ++ AuLsc_I_PARENT3, cpg->pin->udba, AuPin_DI_LOCKED); ++ cpg->pin = &wh_pin; ++ } ++ ++ if (!au_test_h_perm_sio(h_tmpdir, MAY_EXEC | MAY_WRITE) ++ && !au_cpup_sio_test(cpg->pin, d_inode(dentry)->i_mode)) ++ err = au_cpup_wh(cpg, file); ++ else { ++ struct au_cpup_wh_args args = { ++ .errp = &err, ++ .cpg = cpg, ++ .file = file ++ }; ++ wkq_err = au_wkq_wait(au_call_cpup_wh, &args); ++ if (unlikely(wkq_err)) ++ err = wkq_err; ++ } ++ ++ if (h_orph) { ++ inode_unlock(h_tmpdir); ++ /* todo: au_h_open_post()? */ ++ au_set_h_iptr(dir, bdst, au_igrab(h_dir), /*flags*/0); ++ au_set_h_dptr(parent, bdst, h_parent); ++ AuDebugOn(!pin_orig); ++ cpg->pin = pin_orig; ++ } ++ iput(h_dir); ++ dput(parent); ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * generic routine for both of copy-up and copy-down. ++ */ ++/* cf. revalidate function in file.c */ ++int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst, ++ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst, ++ struct au_pin *pin, ++ struct dentry *h_parent, void *arg), ++ void *arg) ++{ ++ int err; ++ struct au_pin pin; ++ struct dentry *d, *parent, *h_parent, *real_parent, *h_dentry; ++ ++ err = 0; ++ parent = dget_parent(dentry); ++ if (IS_ROOT(parent)) ++ goto out; ++ ++ au_pin_init(&pin, dentry, bdst, AuLsc_DI_PARENT2, AuLsc_I_PARENT2, ++ au_opt_udba(dentry->d_sb), AuPin_MNT_WRITE); ++ ++ /* do not use au_dpage */ ++ real_parent = parent; ++ while (1) { ++ dput(parent); ++ parent = dget_parent(dentry); ++ h_parent = au_h_dptr(parent, bdst); ++ if (h_parent) ++ goto out; /* success */ ++ ++ /* find top dir which is necessary to cpup */ ++ do { ++ d = parent; ++ dput(parent); ++ parent = dget_parent(d); ++ di_read_lock_parent3(parent, !AuLock_IR); ++ h_parent = au_h_dptr(parent, bdst); ++ di_read_unlock(parent, !AuLock_IR); ++ } while (!h_parent); ++ ++ if (d != real_parent) ++ di_write_lock_child3(d); ++ ++ /* somebody else might create while we were sleeping */ ++ h_dentry = au_h_dptr(d, bdst); ++ if (!h_dentry || d_is_negative(h_dentry)) { ++ if (h_dentry) ++ au_update_dbtop(d); ++ ++ au_pin_set_dentry(&pin, d); ++ err = au_do_pin(&pin); ++ if (!err) { ++ err = cp(d, bdst, &pin, h_parent, arg); ++ au_unpin(&pin); ++ } ++ } ++ ++ if (d != real_parent) ++ di_write_unlock(d); ++ if (unlikely(err)) ++ break; ++ } ++ ++out: ++ dput(parent); ++ return err; ++} ++ ++static int au_cpup_dir(struct dentry *dentry, aufs_bindex_t bdst, ++ struct au_pin *pin, ++ struct dentry *h_parent __maybe_unused, ++ void *arg __maybe_unused) ++{ ++ struct au_cp_generic cpg = { ++ .dentry = dentry, ++ .bdst = bdst, ++ .bsrc = -1, ++ .len = 0, ++ .pin = pin, ++ .flags = AuCpup_DTIME ++ }; ++ return au_sio_cpup_simple(&cpg); ++} ++ ++int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst) ++{ ++ return au_cp_dirs(dentry, bdst, au_cpup_dir, NULL); ++} ++ ++int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst) ++{ ++ int err; ++ struct dentry *parent; ++ struct inode *dir; ++ ++ parent = dget_parent(dentry); ++ dir = d_inode(parent); ++ err = 0; ++ if (au_h_iptr(dir, bdst)) ++ goto out; ++ ++ di_read_unlock(parent, AuLock_IR); ++ di_write_lock_parent(parent); ++ /* someone else might change our inode while we were sleeping */ ++ if (!au_h_iptr(dir, bdst)) ++ err = au_cpup_dirs(dentry, bdst); ++ di_downgrade_lock(parent, AuLock_IR); ++ ++out: ++ dput(parent); ++ return err; ++} +diff -Nurp linux-5.4/fs/aufs/cpup.h linux-5.4-aufs/fs/aufs/cpup.h +--- linux-5.4/fs/aufs/cpup.h 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/cpup.h 2019-11-28 01:25:59.063925618 +0200 +@@ -0,0 +1,87 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * copy-up/down functions ++ */ ++ ++#ifndef __AUFS_CPUP_H__ ++#define __AUFS_CPUP_H__ ++ ++#ifdef __KERNEL__ ++ ++#include ++ ++struct inode; ++struct file; ++struct au_pin; ++ ++void au_cpup_attr_flags(struct inode *dst, unsigned int iflags); ++void au_cpup_attr_timesizes(struct inode *inode); ++void au_cpup_attr_nlink(struct inode *inode, int force); ++void au_cpup_attr_changeable(struct inode *inode); ++void au_cpup_igen(struct inode *inode, struct inode *h_inode); ++void au_cpup_attr_all(struct inode *inode, int force); ++ ++/* ---------------------------------------------------------------------- */ ++ ++struct au_cp_generic { ++ struct dentry *dentry; ++ aufs_bindex_t bdst, bsrc; ++ loff_t len; ++ struct au_pin *pin; ++ unsigned int flags; ++}; ++ ++/* cpup flags */ ++#define AuCpup_DTIME 1 /* do dtime_store/revert */ ++#define AuCpup_KEEPLINO (1 << 1) /* do not clear the lower xino, ++ for link(2) */ ++#define AuCpup_RENAME (1 << 2) /* rename after cpup */ ++#define AuCpup_HOPEN (1 << 3) /* call h_open_pre/post() in ++ cpup */ ++#define AuCpup_OVERWRITE (1 << 4) /* allow overwriting the ++ existing entry */ ++#define AuCpup_RWDST (1 << 5) /* force write target even if ++ the branch is marked as RO */ ++ ++#ifndef CONFIG_AUFS_BR_HFSPLUS ++#undef AuCpup_HOPEN ++#define AuCpup_HOPEN 0 ++#endif ++ ++#define au_ftest_cpup(flags, name) ((flags) & AuCpup_##name) ++#define au_fset_cpup(flags, name) \ ++ do { (flags) |= AuCpup_##name; } while (0) ++#define au_fclr_cpup(flags, name) \ ++ do { (flags) &= ~AuCpup_##name; } while (0) ++ ++int au_copy_file(struct file *dst, struct file *src, loff_t len); ++int au_sio_cpup_simple(struct au_cp_generic *cpg); ++int au_sio_cpdown_simple(struct au_cp_generic *cpg); ++int au_sio_cpup_wh(struct au_cp_generic *cpg, struct file *file); ++ ++int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst, ++ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst, ++ struct au_pin *pin, ++ struct dentry *h_parent, void *arg), ++ void *arg); ++int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst); ++int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst); ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* keep timestamps when copyup */ ++struct au_dtime { ++ struct dentry *dt_dentry; ++ struct path dt_h_path; ++ struct timespec64 dt_atime, dt_mtime; ++}; ++void au_dtime_store(struct au_dtime *dt, struct dentry *dentry, ++ struct path *h_path); ++void au_dtime_revert(struct au_dtime *dt); ++ ++#endif /* __KERNEL__ */ ++#endif /* __AUFS_CPUP_H__ */ +diff -Nurp linux-5.4/fs/aufs/dbgaufs.c linux-5.4-aufs/fs/aufs/dbgaufs.c +--- linux-5.4/fs/aufs/dbgaufs.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/dbgaufs.c 2019-11-28 01:25:59.063925618 +0200 +@@ -0,0 +1,513 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * debugfs interface ++ */ ++ ++#include ++#include "aufs.h" ++ ++#ifndef CONFIG_SYSFS ++#error DEBUG_FS depends upon SYSFS ++#endif ++ ++static struct dentry *dbgaufs; ++static const mode_t dbgaufs_mode = 0444; ++ ++/* 20 is max digits length of ulong 64 */ ++struct dbgaufs_arg { ++ int n; ++ char a[20 * 4]; ++}; ++ ++/* ++ * common function for all XINO files ++ */ ++static int dbgaufs_xi_release(struct inode *inode __maybe_unused, ++ struct file *file) ++{ ++ void *p; ++ ++ p = file->private_data; ++ if (p) { ++ /* this is struct dbgaufs_arg */ ++ AuDebugOn(!au_kfree_sz_test(p)); ++ au_kfree_do_rcu(p); ++ } ++ return 0; ++} ++ ++static int dbgaufs_xi_open(struct file *xf, struct file *file, int do_fcnt, ++ int cnt) ++{ ++ int err; ++ struct kstat st; ++ struct dbgaufs_arg *p; ++ ++ err = -ENOMEM; ++ p = kmalloc(sizeof(*p), GFP_NOFS); ++ if (unlikely(!p)) ++ goto out; ++ ++ err = 0; ++ p->n = 0; ++ file->private_data = p; ++ if (!xf) ++ goto out; ++ ++ err = vfsub_getattr(&xf->f_path, &st); ++ if (!err) { ++ if (do_fcnt) ++ p->n = snprintf ++ (p->a, sizeof(p->a), "%d, %llux%u %lld\n", ++ cnt, st.blocks, st.blksize, ++ (long long)st.size); ++ else ++ p->n = snprintf(p->a, sizeof(p->a), "%llux%u %lld\n", ++ st.blocks, st.blksize, ++ (long long)st.size); ++ AuDebugOn(p->n >= sizeof(p->a)); ++ } else { ++ p->n = snprintf(p->a, sizeof(p->a), "err %d\n", err); ++ err = 0; ++ } ++ ++out: ++ return err; ++} ++ ++static ssize_t dbgaufs_xi_read(struct file *file, char __user *buf, ++ size_t count, loff_t *ppos) ++{ ++ struct dbgaufs_arg *p; ++ ++ p = file->private_data; ++ return simple_read_from_buffer(buf, count, ppos, p->a, p->n); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++struct dbgaufs_plink_arg { ++ int n; ++ char a[]; ++}; ++ ++static int dbgaufs_plink_release(struct inode *inode __maybe_unused, ++ struct file *file) ++{ ++ free_page((unsigned long)file->private_data); ++ return 0; ++} ++ ++static int dbgaufs_plink_open(struct inode *inode, struct file *file) ++{ ++ int err, i, limit; ++ unsigned long n, sum; ++ struct dbgaufs_plink_arg *p; ++ struct au_sbinfo *sbinfo; ++ struct super_block *sb; ++ struct hlist_bl_head *hbl; ++ ++ err = -ENOMEM; ++ p = (void *)get_zeroed_page(GFP_NOFS); ++ if (unlikely(!p)) ++ goto out; ++ ++ err = -EFBIG; ++ sbinfo = inode->i_private; ++ sb = sbinfo->si_sb; ++ si_noflush_read_lock(sb); ++ if (au_opt_test(au_mntflags(sb), PLINK)) { ++ limit = PAGE_SIZE - sizeof(p->n); ++ ++ /* the number of buckets */ ++ n = snprintf(p->a + p->n, limit, "%d\n", AuPlink_NHASH); ++ p->n += n; ++ limit -= n; ++ ++ sum = 0; ++ for (i = 0, hbl = sbinfo->si_plink; i < AuPlink_NHASH; ++ i++, hbl++) { ++ n = au_hbl_count(hbl); ++ sum += n; ++ ++ n = snprintf(p->a + p->n, limit, "%lu ", n); ++ p->n += n; ++ limit -= n; ++ if (unlikely(limit <= 0)) ++ goto out_free; ++ } ++ p->a[p->n - 1] = '\n'; ++ ++ /* the sum of plinks */ ++ n = snprintf(p->a + p->n, limit, "%lu\n", sum); ++ p->n += n; ++ limit -= n; ++ if (unlikely(limit <= 0)) ++ goto out_free; ++ } else { ++#define str "1\n0\n0\n" ++ p->n = sizeof(str) - 1; ++ strcpy(p->a, str); ++#undef str ++ } ++ si_read_unlock(sb); ++ ++ err = 0; ++ file->private_data = p; ++ goto out; /* success */ ++ ++out_free: ++ free_page((unsigned long)p); ++out: ++ return err; ++} ++ ++static ssize_t dbgaufs_plink_read(struct file *file, char __user *buf, ++ size_t count, loff_t *ppos) ++{ ++ struct dbgaufs_plink_arg *p; ++ ++ p = file->private_data; ++ return simple_read_from_buffer(buf, count, ppos, p->a, p->n); ++} ++ ++static const struct file_operations dbgaufs_plink_fop = { ++ .owner = THIS_MODULE, ++ .open = dbgaufs_plink_open, ++ .release = dbgaufs_plink_release, ++ .read = dbgaufs_plink_read ++}; ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int dbgaufs_xib_open(struct inode *inode, struct file *file) ++{ ++ int err; ++ struct au_sbinfo *sbinfo; ++ struct super_block *sb; ++ ++ sbinfo = inode->i_private; ++ sb = sbinfo->si_sb; ++ si_noflush_read_lock(sb); ++ err = dbgaufs_xi_open(sbinfo->si_xib, file, /*do_fcnt*/0, /*cnt*/0); ++ si_read_unlock(sb); ++ return err; ++} ++ ++static const struct file_operations dbgaufs_xib_fop = { ++ .owner = THIS_MODULE, ++ .open = dbgaufs_xib_open, ++ .release = dbgaufs_xi_release, ++ .read = dbgaufs_xi_read ++}; ++ ++/* ---------------------------------------------------------------------- */ ++ ++#define DbgaufsXi_PREFIX "xi" ++ ++static int dbgaufs_xino_open(struct inode *inode, struct file *file) ++{ ++ int err, idx; ++ long l; ++ aufs_bindex_t bindex; ++ char *p, a[sizeof(DbgaufsXi_PREFIX) + 8]; ++ struct au_sbinfo *sbinfo; ++ struct super_block *sb; ++ struct au_xino *xi; ++ struct file *xf; ++ struct qstr *name; ++ struct au_branch *br; ++ ++ err = -ENOENT; ++ name = &file->f_path.dentry->d_name; ++ if (unlikely(name->len < sizeof(DbgaufsXi_PREFIX) ++ || memcmp(name->name, DbgaufsXi_PREFIX, ++ sizeof(DbgaufsXi_PREFIX) - 1))) ++ goto out; ++ ++ AuDebugOn(name->len >= sizeof(a)); ++ memcpy(a, name->name, name->len); ++ a[name->len] = '\0'; ++ p = strchr(a, '-'); ++ if (p) ++ *p = '\0'; ++ err = kstrtol(a + sizeof(DbgaufsXi_PREFIX) - 1, 10, &l); ++ if (unlikely(err)) ++ goto out; ++ bindex = l; ++ idx = 0; ++ if (p) { ++ err = kstrtol(p + 1, 10, &l); ++ if (unlikely(err)) ++ goto out; ++ idx = l; ++ } ++ ++ err = -ENOENT; ++ sbinfo = inode->i_private; ++ sb = sbinfo->si_sb; ++ si_noflush_read_lock(sb); ++ if (unlikely(bindex < 0 || bindex > au_sbbot(sb))) ++ goto out_si; ++ br = au_sbr(sb, bindex); ++ xi = br->br_xino; ++ if (unlikely(idx >= xi->xi_nfile)) ++ goto out_si; ++ xf = au_xino_file(xi, idx); ++ if (xf) ++ err = dbgaufs_xi_open(xf, file, /*do_fcnt*/1, ++ au_xino_count(br)); ++ ++out_si: ++ si_read_unlock(sb); ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++static const struct file_operations dbgaufs_xino_fop = { ++ .owner = THIS_MODULE, ++ .open = dbgaufs_xino_open, ++ .release = dbgaufs_xi_release, ++ .read = dbgaufs_xi_read ++}; ++ ++void dbgaufs_xino_del(struct au_branch *br) ++{ ++ struct dentry *dbgaufs; ++ ++ dbgaufs = br->br_dbgaufs; ++ if (!dbgaufs) ++ return; ++ ++ br->br_dbgaufs = NULL; ++ /* debugfs acquires the parent i_mutex */ ++ lockdep_off(); ++ debugfs_remove(dbgaufs); ++ lockdep_on(); ++} ++ ++void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex) ++{ ++ aufs_bindex_t bbot; ++ struct au_branch *br; ++ ++ if (!au_sbi(sb)->si_dbgaufs) ++ return; ++ ++ bbot = au_sbbot(sb); ++ for (; bindex <= bbot; bindex++) { ++ br = au_sbr(sb, bindex); ++ dbgaufs_xino_del(br); ++ } ++} ++ ++static void dbgaufs_br_do_add(struct super_block *sb, aufs_bindex_t bindex, ++ unsigned int idx, struct dentry *parent, ++ struct au_sbinfo *sbinfo) ++{ ++ struct au_branch *br; ++ struct dentry *d; ++ /* "xi" bindex(5) "-" idx(2) NULL */ ++ char name[sizeof(DbgaufsXi_PREFIX) + 8]; ++ ++ if (!idx) ++ snprintf(name, sizeof(name), DbgaufsXi_PREFIX "%d", bindex); ++ else ++ snprintf(name, sizeof(name), DbgaufsXi_PREFIX "%d-%u", ++ bindex, idx); ++ br = au_sbr(sb, bindex); ++ if (br->br_dbgaufs) { ++ struct qstr qstr = QSTR_INIT(name, strlen(name)); ++ ++ if (!au_qstreq(&br->br_dbgaufs->d_name, &qstr)) { ++ /* debugfs acquires the parent i_mutex */ ++ lockdep_off(); ++ d = debugfs_rename(parent, br->br_dbgaufs, parent, ++ name); ++ lockdep_on(); ++ if (unlikely(!d)) ++ pr_warn("failed renaming %pd/%s, ignored.\n", ++ parent, name); ++ } ++ } else { ++ lockdep_off(); ++ br->br_dbgaufs = debugfs_create_file(name, dbgaufs_mode, parent, ++ sbinfo, &dbgaufs_xino_fop); ++ lockdep_on(); ++ if (unlikely(!br->br_dbgaufs)) ++ pr_warn("failed creating %pd/%s, ignored.\n", ++ parent, name); ++ } ++} ++ ++static void dbgaufs_br_add(struct super_block *sb, aufs_bindex_t bindex, ++ struct dentry *parent, struct au_sbinfo *sbinfo) ++{ ++ struct au_branch *br; ++ struct au_xino *xi; ++ unsigned int u; ++ ++ br = au_sbr(sb, bindex); ++ xi = br->br_xino; ++ for (u = 0; u < xi->xi_nfile; u++) ++ dbgaufs_br_do_add(sb, bindex, u, parent, sbinfo); ++} ++ ++void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex, int topdown) ++{ ++ struct au_sbinfo *sbinfo; ++ struct dentry *parent; ++ aufs_bindex_t bbot; ++ ++ if (!au_opt_test(au_mntflags(sb), XINO)) ++ return; ++ ++ sbinfo = au_sbi(sb); ++ parent = sbinfo->si_dbgaufs; ++ if (!parent) ++ return; ++ ++ bbot = au_sbbot(sb); ++ if (topdown) ++ for (; bindex <= bbot; bindex++) ++ dbgaufs_br_add(sb, bindex, parent, sbinfo); ++ else ++ for (; bbot >= bindex; bbot--) ++ dbgaufs_br_add(sb, bbot, parent, sbinfo); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++#ifdef CONFIG_AUFS_EXPORT ++static int dbgaufs_xigen_open(struct inode *inode, struct file *file) ++{ ++ int err; ++ struct au_sbinfo *sbinfo; ++ struct super_block *sb; ++ ++ sbinfo = inode->i_private; ++ sb = sbinfo->si_sb; ++ si_noflush_read_lock(sb); ++ err = dbgaufs_xi_open(sbinfo->si_xigen, file, /*do_fcnt*/0, /*cnt*/0); ++ si_read_unlock(sb); ++ return err; ++} ++ ++static const struct file_operations dbgaufs_xigen_fop = { ++ .owner = THIS_MODULE, ++ .open = dbgaufs_xigen_open, ++ .release = dbgaufs_xi_release, ++ .read = dbgaufs_xi_read ++}; ++ ++static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo) ++{ ++ int err; ++ ++ /* ++ * This function is a dynamic '__init' function actually, ++ * so the tiny check for si_rwsem is unnecessary. ++ */ ++ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */ ++ ++ err = -EIO; ++ sbinfo->si_dbgaufs_xigen = debugfs_create_file ++ ("xigen", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo, ++ &dbgaufs_xigen_fop); ++ if (sbinfo->si_dbgaufs_xigen) ++ err = 0; ++ ++ return err; ++} ++#else ++static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo) ++{ ++ return 0; ++} ++#endif /* CONFIG_AUFS_EXPORT */ ++ ++/* ---------------------------------------------------------------------- */ ++ ++void dbgaufs_si_fin(struct au_sbinfo *sbinfo) ++{ ++ /* ++ * This function is a dynamic '__fin' function actually, ++ * so the tiny check for si_rwsem is unnecessary. ++ */ ++ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */ ++ ++ debugfs_remove_recursive(sbinfo->si_dbgaufs); ++ sbinfo->si_dbgaufs = NULL; ++} ++ ++int dbgaufs_si_init(struct au_sbinfo *sbinfo) ++{ ++ int err; ++ char name[SysaufsSiNameLen]; ++ ++ /* ++ * This function is a dynamic '__init' function actually, ++ * so the tiny check for si_rwsem is unnecessary. ++ */ ++ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */ ++ ++ err = -ENOENT; ++ if (!dbgaufs) { ++ AuErr1("/debug/aufs is uninitialized\n"); ++ goto out; ++ } ++ ++ err = -EIO; ++ sysaufs_name(sbinfo, name); ++ sbinfo->si_dbgaufs = debugfs_create_dir(name, dbgaufs); ++ if (unlikely(!sbinfo->si_dbgaufs)) ++ goto out; ++ ++ /* regardless plink/noplink option */ ++ sbinfo->si_dbgaufs_plink = debugfs_create_file ++ ("plink", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo, ++ &dbgaufs_plink_fop); ++ if (unlikely(!sbinfo->si_dbgaufs_plink)) ++ goto out_dir; ++ ++ /* regardless xino/noxino option */ ++ sbinfo->si_dbgaufs_xib = debugfs_create_file ++ ("xib", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo, ++ &dbgaufs_xib_fop); ++ if (unlikely(!sbinfo->si_dbgaufs_xib)) ++ goto out_dir; ++ ++ err = dbgaufs_xigen_init(sbinfo); ++ if (!err) ++ goto out; /* success */ ++ ++out_dir: ++ dbgaufs_si_fin(sbinfo); ++out: ++ if (unlikely(err)) ++ pr_err("debugfs/aufs failed\n"); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++void dbgaufs_fin(void) ++{ ++ debugfs_remove(dbgaufs); ++} ++ ++int __init dbgaufs_init(void) ++{ ++ int err; ++ ++ err = -EIO; ++ dbgaufs = debugfs_create_dir(AUFS_NAME, NULL); ++ if (dbgaufs) ++ err = 0; ++ return err; ++} +diff -Nurp linux-5.4/fs/aufs/dbgaufs.h linux-5.4-aufs/fs/aufs/dbgaufs.h +--- linux-5.4/fs/aufs/dbgaufs.h 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/dbgaufs.h 2019-11-28 01:25:59.063925618 +0200 +@@ -0,0 +1,40 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * debugfs interface ++ */ ++ ++#ifndef __DBGAUFS_H__ ++#define __DBGAUFS_H__ ++ ++#ifdef __KERNEL__ ++ ++struct super_block; ++struct au_sbinfo; ++struct au_branch; ++ ++#ifdef CONFIG_DEBUG_FS ++/* dbgaufs.c */ ++void dbgaufs_xino_del(struct au_branch *br); ++void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex); ++void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex, int topdown); ++void dbgaufs_si_fin(struct au_sbinfo *sbinfo); ++int dbgaufs_si_init(struct au_sbinfo *sbinfo); ++void dbgaufs_fin(void); ++int __init dbgaufs_init(void); ++#else ++AuStubVoid(dbgaufs_xino_del, struct au_branch *br) ++AuStubVoid(dbgaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex) ++AuStubVoid(dbgaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex, ++ int topdown) ++AuStubVoid(dbgaufs_si_fin, struct au_sbinfo *sbinfo) ++AuStubInt0(dbgaufs_si_init, struct au_sbinfo *sbinfo) ++AuStubVoid(dbgaufs_fin, void) ++AuStubInt0(__init dbgaufs_init, void) ++#endif /* CONFIG_DEBUG_FS */ ++ ++#endif /* __KERNEL__ */ ++#endif /* __DBGAUFS_H__ */ +diff -Nurp linux-5.4/fs/aufs/dcsub.c linux-5.4-aufs/fs/aufs/dcsub.c +--- linux-5.4/fs/aufs/dcsub.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/dcsub.c 2019-11-28 01:25:59.063925618 +0200 +@@ -0,0 +1,212 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * sub-routines for dentry cache ++ */ ++ ++#include "aufs.h" ++ ++static void au_dpage_free(struct au_dpage *dpage) ++{ ++ int i; ++ struct dentry **p; ++ ++ p = dpage->dentries; ++ for (i = 0; i < dpage->ndentry; i++) ++ dput(*p++); ++ free_page((unsigned long)dpage->dentries); ++} ++ ++int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp) ++{ ++ int err; ++ void *p; ++ ++ err = -ENOMEM; ++ dpages->dpages = kmalloc(sizeof(*dpages->dpages), gfp); ++ if (unlikely(!dpages->dpages)) ++ goto out; ++ ++ p = (void *)__get_free_page(gfp); ++ if (unlikely(!p)) ++ goto out_dpages; ++ ++ dpages->dpages[0].ndentry = 0; ++ dpages->dpages[0].dentries = p; ++ dpages->ndpage = 1; ++ return 0; /* success */ ++ ++out_dpages: ++ au_kfree_try_rcu(dpages->dpages); ++out: ++ return err; ++} ++ ++void au_dpages_free(struct au_dcsub_pages *dpages) ++{ ++ int i; ++ struct au_dpage *p; ++ ++ p = dpages->dpages; ++ for (i = 0; i < dpages->ndpage; i++) ++ au_dpage_free(p++); ++ au_kfree_try_rcu(dpages->dpages); ++} ++ ++static int au_dpages_append(struct au_dcsub_pages *dpages, ++ struct dentry *dentry, gfp_t gfp) ++{ ++ int err, sz; ++ struct au_dpage *dpage; ++ void *p; ++ ++ dpage = dpages->dpages + dpages->ndpage - 1; ++ sz = PAGE_SIZE / sizeof(dentry); ++ if (unlikely(dpage->ndentry >= sz)) { ++ AuLabel(new dpage); ++ err = -ENOMEM; ++ sz = dpages->ndpage * sizeof(*dpages->dpages); ++ p = au_kzrealloc(dpages->dpages, sz, ++ sz + sizeof(*dpages->dpages), gfp, ++ /*may_shrink*/0); ++ if (unlikely(!p)) ++ goto out; ++ ++ dpages->dpages = p; ++ dpage = dpages->dpages + dpages->ndpage; ++ p = (void *)__get_free_page(gfp); ++ if (unlikely(!p)) ++ goto out; ++ ++ dpage->ndentry = 0; ++ dpage->dentries = p; ++ dpages->ndpage++; ++ } ++ ++ AuDebugOn(au_dcount(dentry) <= 0); ++ dpage->dentries[dpage->ndentry++] = dget_dlock(dentry); ++ return 0; /* success */ ++ ++out: ++ return err; ++} ++ ++/* todo: BAD approach */ ++/* copied from linux/fs/dcache.c */ ++enum d_walk_ret { ++ D_WALK_CONTINUE, ++ D_WALK_QUIT, ++ D_WALK_NORETRY, ++ D_WALK_SKIP, ++}; ++ ++extern void d_walk(struct dentry *parent, void *data, ++ enum d_walk_ret (*enter)(void *, struct dentry *)); ++ ++struct ac_dpages_arg { ++ int err; ++ struct au_dcsub_pages *dpages; ++ struct super_block *sb; ++ au_dpages_test test; ++ void *arg; ++}; ++ ++static enum d_walk_ret au_call_dpages_append(void *_arg, struct dentry *dentry) ++{ ++ enum d_walk_ret ret; ++ struct ac_dpages_arg *arg = _arg; ++ ++ ret = D_WALK_CONTINUE; ++ if (dentry->d_sb == arg->sb ++ && !IS_ROOT(dentry) ++ && au_dcount(dentry) > 0 ++ && au_di(dentry) ++ && (!arg->test || arg->test(dentry, arg->arg))) { ++ arg->err = au_dpages_append(arg->dpages, dentry, GFP_ATOMIC); ++ if (unlikely(arg->err)) ++ ret = D_WALK_QUIT; ++ } ++ ++ return ret; ++} ++ ++int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root, ++ au_dpages_test test, void *arg) ++{ ++ struct ac_dpages_arg args = { ++ .err = 0, ++ .dpages = dpages, ++ .sb = root->d_sb, ++ .test = test, ++ .arg = arg ++ }; ++ ++ d_walk(root, &args, au_call_dpages_append); ++ ++ return args.err; ++} ++ ++int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry, ++ int do_include, au_dpages_test test, void *arg) ++{ ++ int err; ++ ++ err = 0; ++ write_seqlock(&rename_lock); ++ spin_lock(&dentry->d_lock); ++ if (do_include ++ && au_dcount(dentry) > 0 ++ && (!test || test(dentry, arg))) ++ err = au_dpages_append(dpages, dentry, GFP_ATOMIC); ++ spin_unlock(&dentry->d_lock); ++ if (unlikely(err)) ++ goto out; ++ ++ /* ++ * RCU for vfsmount is unnecessary since this is a traverse in a single ++ * mount ++ */ ++ while (!IS_ROOT(dentry)) { ++ dentry = dentry->d_parent; /* rename_lock is locked */ ++ spin_lock(&dentry->d_lock); ++ if (au_dcount(dentry) > 0 ++ && (!test || test(dentry, arg))) ++ err = au_dpages_append(dpages, dentry, GFP_ATOMIC); ++ spin_unlock(&dentry->d_lock); ++ if (unlikely(err)) ++ break; ++ } ++ ++out: ++ write_sequnlock(&rename_lock); ++ return err; ++} ++ ++static inline int au_dcsub_dpages_aufs(struct dentry *dentry, void *arg) ++{ ++ return au_di(dentry) && dentry->d_sb == arg; ++} ++ ++int au_dcsub_pages_rev_aufs(struct au_dcsub_pages *dpages, ++ struct dentry *dentry, int do_include) ++{ ++ return au_dcsub_pages_rev(dpages, dentry, do_include, ++ au_dcsub_dpages_aufs, dentry->d_sb); ++} ++ ++int au_test_subdir(struct dentry *d1, struct dentry *d2) ++{ ++ struct path path[2] = { ++ { ++ .dentry = d1 ++ }, ++ { ++ .dentry = d2 ++ } ++ }; ++ ++ return path_is_under(path + 0, path + 1); ++} +diff -Nurp linux-5.4/fs/aufs/dcsub.h linux-5.4-aufs/fs/aufs/dcsub.h +--- linux-5.4/fs/aufs/dcsub.h 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/dcsub.h 2019-11-28 01:25:59.063925618 +0200 +@@ -0,0 +1,124 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * sub-routines for dentry cache ++ */ ++ ++#ifndef __AUFS_DCSUB_H__ ++#define __AUFS_DCSUB_H__ ++ ++#ifdef __KERNEL__ ++ ++#include ++#include ++ ++struct au_dpage { ++ int ndentry; ++ struct dentry **dentries; ++}; ++ ++struct au_dcsub_pages { ++ int ndpage; ++ struct au_dpage *dpages; ++}; ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* dcsub.c */ ++int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp); ++void au_dpages_free(struct au_dcsub_pages *dpages); ++typedef int (*au_dpages_test)(struct dentry *dentry, void *arg); ++int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root, ++ au_dpages_test test, void *arg); ++int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry, ++ int do_include, au_dpages_test test, void *arg); ++int au_dcsub_pages_rev_aufs(struct au_dcsub_pages *dpages, ++ struct dentry *dentry, int do_include); ++int au_test_subdir(struct dentry *d1, struct dentry *d2); ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * todo: in linux-3.13, several similar (but faster) helpers are added to ++ * include/linux/dcache.h. Try them (in the future). ++ */ ++ ++static inline int au_d_hashed_positive(struct dentry *d) ++{ ++ int err; ++ struct inode *inode = d_inode(d); ++ ++ err = 0; ++ if (unlikely(d_unhashed(d) ++ || d_is_negative(d) ++ || !inode->i_nlink)) ++ err = -ENOENT; ++ return err; ++} ++ ++static inline int au_d_linkable(struct dentry *d) ++{ ++ int err; ++ struct inode *inode = d_inode(d); ++ ++ err = au_d_hashed_positive(d); ++ if (err ++ && d_is_positive(d) ++ && (inode->i_state & I_LINKABLE)) ++ err = 0; ++ return err; ++} ++ ++static inline int au_d_alive(struct dentry *d) ++{ ++ int err; ++ struct inode *inode; ++ ++ err = 0; ++ if (!IS_ROOT(d)) ++ err = au_d_hashed_positive(d); ++ else { ++ inode = d_inode(d); ++ if (unlikely(d_unlinked(d) ++ || d_is_negative(d) ++ || !inode->i_nlink)) ++ err = -ENOENT; ++ } ++ return err; ++} ++ ++static inline int au_alive_dir(struct dentry *d) ++{ ++ int err; ++ ++ err = au_d_alive(d); ++ if (unlikely(err || IS_DEADDIR(d_inode(d)))) ++ err = -ENOENT; ++ return err; ++} ++ ++static inline int au_qstreq(struct qstr *a, struct qstr *b) ++{ ++ return a->len == b->len ++ && !memcmp(a->name, b->name, a->len); ++} ++ ++/* ++ * by the commit ++ * 360f547 2015-01-25 dcache: let the dentry count go down to zero without ++ * taking d_lock ++ * the type of d_lockref.count became int, but the inlined function d_count() ++ * still returns unsigned int. ++ * I don't know why. Maybe it is for every d_count() users? ++ * Anyway au_dcount() lives on. ++ */ ++static inline int au_dcount(struct dentry *d) ++{ ++ return (int)d_count(d); ++} ++ ++#endif /* __KERNEL__ */ ++#endif /* __AUFS_DCSUB_H__ */ +diff -Nurp linux-5.4/fs/aufs/debug.c linux-5.4-aufs/fs/aufs/debug.c +--- linux-5.4/fs/aufs/debug.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/debug.c 2019-11-28 01:25:59.063925618 +0200 +@@ -0,0 +1,428 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * debug print functions ++ */ ++ ++#include ++#include "aufs.h" ++ ++/* Returns 0, or -errno. arg is in kp->arg. */ ++static int param_atomic_t_set(const char *val, const struct kernel_param *kp) ++{ ++ int err, n; ++ ++ err = kstrtoint(val, 0, &n); ++ if (!err) { ++ if (n > 0) ++ au_debug_on(); ++ else ++ au_debug_off(); ++ } ++ return err; ++} ++ ++/* Returns length written or -errno. Buffer is 4k (ie. be short!) */ ++static int param_atomic_t_get(char *buffer, const struct kernel_param *kp) ++{ ++ atomic_t *a; ++ ++ a = kp->arg; ++ return sprintf(buffer, "%d", atomic_read(a)); ++} ++ ++static struct kernel_param_ops param_ops_atomic_t = { ++ .set = param_atomic_t_set, ++ .get = param_atomic_t_get ++ /* void (*free)(void *arg) */ ++}; ++ ++atomic_t aufs_debug = ATOMIC_INIT(0); ++MODULE_PARM_DESC(debug, "debug print"); ++module_param_named(debug, aufs_debug, atomic_t, 0664); ++ ++DEFINE_MUTEX(au_dbg_mtx); /* just to serialize the dbg msgs */ ++char *au_plevel = KERN_DEBUG; ++#define dpri(fmt, ...) do { \ ++ if ((au_plevel \ ++ && strcmp(au_plevel, KERN_DEBUG)) \ ++ || au_debug_test()) \ ++ printk("%s" fmt, au_plevel, ##__VA_ARGS__); \ ++} while (0) ++ ++/* ---------------------------------------------------------------------- */ ++ ++void au_dpri_whlist(struct au_nhash *whlist) ++{ ++ unsigned long ul, n; ++ struct hlist_head *head; ++ struct au_vdir_wh *pos; ++ ++ n = whlist->nh_num; ++ head = whlist->nh_head; ++ for (ul = 0; ul < n; ul++) { ++ hlist_for_each_entry(pos, head, wh_hash) ++ dpri("b%d, %.*s, %d\n", ++ pos->wh_bindex, ++ pos->wh_str.len, pos->wh_str.name, ++ pos->wh_str.len); ++ head++; ++ } ++} ++ ++void au_dpri_vdir(struct au_vdir *vdir) ++{ ++ unsigned long ul; ++ union au_vdir_deblk_p p; ++ unsigned char *o; ++ ++ if (!vdir || IS_ERR(vdir)) { ++ dpri("err %ld\n", PTR_ERR(vdir)); ++ return; ++ } ++ ++ dpri("deblk %u, nblk %lu, deblk %p, last{%lu, %p}, ver %llu\n", ++ vdir->vd_deblk_sz, vdir->vd_nblk, vdir->vd_deblk, ++ vdir->vd_last.ul, vdir->vd_last.p.deblk, vdir->vd_version); ++ for (ul = 0; ul < vdir->vd_nblk; ul++) { ++ p.deblk = vdir->vd_deblk[ul]; ++ o = p.deblk; ++ dpri("[%lu]: %p\n", ul, o); ++ } ++} ++ ++static int do_pri_inode(aufs_bindex_t bindex, struct inode *inode, int hn, ++ struct dentry *wh) ++{ ++ char *n = NULL; ++ int l = 0; ++ ++ if (!inode || IS_ERR(inode)) { ++ dpri("i%d: err %ld\n", bindex, PTR_ERR(inode)); ++ return -1; ++ } ++ ++ /* the type of i_blocks depends upon CONFIG_LBDAF */ ++ BUILD_BUG_ON(sizeof(inode->i_blocks) != sizeof(unsigned long) ++ && sizeof(inode->i_blocks) != sizeof(u64)); ++ if (wh) { ++ n = (void *)wh->d_name.name; ++ l = wh->d_name.len; ++ } ++ ++ dpri("i%d: %p, i%lu, %s, cnt %d, nl %u, 0%o, sz %llu, blk %llu," ++ " hn %d, ct %lld, np %lu, st 0x%lx, f 0x%x, v %llu, g %x%s%.*s\n", ++ bindex, inode, ++ inode->i_ino, inode->i_sb ? au_sbtype(inode->i_sb) : "??", ++ atomic_read(&inode->i_count), inode->i_nlink, inode->i_mode, ++ i_size_read(inode), (unsigned long long)inode->i_blocks, ++ hn, (long long)timespec64_to_ns(&inode->i_ctime) & 0x0ffff, ++ inode->i_mapping ? inode->i_mapping->nrpages : 0, ++ inode->i_state, inode->i_flags, inode_peek_iversion(inode), ++ inode->i_generation, ++ l ? ", wh " : "", l, n); ++ return 0; ++} ++ ++void au_dpri_inode(struct inode *inode) ++{ ++ struct au_iinfo *iinfo; ++ struct au_hinode *hi; ++ aufs_bindex_t bindex; ++ int err, hn; ++ ++ err = do_pri_inode(-1, inode, -1, NULL); ++ if (err || !au_test_aufs(inode->i_sb) || au_is_bad_inode(inode)) ++ return; ++ ++ iinfo = au_ii(inode); ++ dpri("i-1: btop %d, bbot %d, gen %d\n", ++ iinfo->ii_btop, iinfo->ii_bbot, au_iigen(inode, NULL)); ++ if (iinfo->ii_btop < 0) ++ return; ++ hn = 0; ++ for (bindex = iinfo->ii_btop; bindex <= iinfo->ii_bbot; bindex++) { ++ hi = au_hinode(iinfo, bindex); ++ hn = !!au_hn(hi); ++ do_pri_inode(bindex, hi->hi_inode, hn, hi->hi_whdentry); ++ } ++} ++ ++void au_dpri_dalias(struct inode *inode) ++{ ++ struct dentry *d; ++ ++ spin_lock(&inode->i_lock); ++ hlist_for_each_entry(d, &inode->i_dentry, d_u.d_alias) ++ au_dpri_dentry(d); ++ spin_unlock(&inode->i_lock); ++} ++ ++static int do_pri_dentry(aufs_bindex_t bindex, struct dentry *dentry) ++{ ++ struct dentry *wh = NULL; ++ int hn; ++ struct inode *inode; ++ struct au_iinfo *iinfo; ++ struct au_hinode *hi; ++ ++ if (!dentry || IS_ERR(dentry)) { ++ dpri("d%d: err %ld\n", bindex, PTR_ERR(dentry)); ++ return -1; ++ } ++ /* do not call dget_parent() here */ ++ /* note: access d_xxx without d_lock */ ++ dpri("d%d: %p, %pd2?, %s, cnt %d, flags 0x%x, %shashed\n", ++ bindex, dentry, dentry, ++ dentry->d_sb ? au_sbtype(dentry->d_sb) : "??", ++ au_dcount(dentry), dentry->d_flags, ++ d_unhashed(dentry) ? "un" : ""); ++ hn = -1; ++ inode = NULL; ++ if (d_is_positive(dentry)) ++ inode = d_inode(dentry); ++ if (inode ++ && au_test_aufs(dentry->d_sb) ++ && bindex >= 0 ++ && !au_is_bad_inode(inode)) { ++ iinfo = au_ii(inode); ++ hi = au_hinode(iinfo, bindex); ++ hn = !!au_hn(hi); ++ wh = hi->hi_whdentry; ++ } ++ do_pri_inode(bindex, inode, hn, wh); ++ return 0; ++} ++ ++void au_dpri_dentry(struct dentry *dentry) ++{ ++ struct au_dinfo *dinfo; ++ aufs_bindex_t bindex; ++ int err; ++ ++ err = do_pri_dentry(-1, dentry); ++ if (err || !au_test_aufs(dentry->d_sb)) ++ return; ++ ++ dinfo = au_di(dentry); ++ if (!dinfo) ++ return; ++ dpri("d-1: btop %d, bbot %d, bwh %d, bdiropq %d, gen %d, tmp %d\n", ++ dinfo->di_btop, dinfo->di_bbot, ++ dinfo->di_bwh, dinfo->di_bdiropq, au_digen(dentry), ++ dinfo->di_tmpfile); ++ if (dinfo->di_btop < 0) ++ return; ++ for (bindex = dinfo->di_btop; bindex <= dinfo->di_bbot; bindex++) ++ do_pri_dentry(bindex, au_hdentry(dinfo, bindex)->hd_dentry); ++} ++ ++static int do_pri_file(aufs_bindex_t bindex, struct file *file) ++{ ++ char a[32]; ++ ++ if (!file || IS_ERR(file)) { ++ dpri("f%d: err %ld\n", bindex, PTR_ERR(file)); ++ return -1; ++ } ++ a[0] = 0; ++ if (bindex < 0 ++ && !IS_ERR_OR_NULL(file->f_path.dentry) ++ && au_test_aufs(file->f_path.dentry->d_sb) ++ && au_fi(file)) ++ snprintf(a, sizeof(a), ", gen %d, mmapped %d", ++ au_figen(file), atomic_read(&au_fi(file)->fi_mmapped)); ++ dpri("f%d: mode 0x%x, flags 0%o, cnt %ld, v %llu, pos %llu%s\n", ++ bindex, file->f_mode, file->f_flags, (long)file_count(file), ++ file->f_version, file->f_pos, a); ++ if (!IS_ERR_OR_NULL(file->f_path.dentry)) ++ do_pri_dentry(bindex, file->f_path.dentry); ++ return 0; ++} ++ ++void au_dpri_file(struct file *file) ++{ ++ struct au_finfo *finfo; ++ struct au_fidir *fidir; ++ struct au_hfile *hfile; ++ aufs_bindex_t bindex; ++ int err; ++ ++ err = do_pri_file(-1, file); ++ if (err ++ || IS_ERR_OR_NULL(file->f_path.dentry) ++ || !au_test_aufs(file->f_path.dentry->d_sb)) ++ return; ++ ++ finfo = au_fi(file); ++ if (!finfo) ++ return; ++ if (finfo->fi_btop < 0) ++ return; ++ fidir = finfo->fi_hdir; ++ if (!fidir) ++ do_pri_file(finfo->fi_btop, finfo->fi_htop.hf_file); ++ else ++ for (bindex = finfo->fi_btop; ++ bindex >= 0 && bindex <= fidir->fd_bbot; ++ bindex++) { ++ hfile = fidir->fd_hfile + bindex; ++ do_pri_file(bindex, hfile ? hfile->hf_file : NULL); ++ } ++} ++ ++static int do_pri_br(aufs_bindex_t bindex, struct au_branch *br) ++{ ++ struct vfsmount *mnt; ++ struct super_block *sb; ++ ++ if (!br || IS_ERR(br)) ++ goto out; ++ mnt = au_br_mnt(br); ++ if (!mnt || IS_ERR(mnt)) ++ goto out; ++ sb = mnt->mnt_sb; ++ if (!sb || IS_ERR(sb)) ++ goto out; ++ ++ dpri("s%d: {perm 0x%x, id %d, wbr %p}, " ++ "%s, dev 0x%02x%02x, flags 0x%lx, cnt %d, active %d, " ++ "xino %d\n", ++ bindex, br->br_perm, br->br_id, br->br_wbr, ++ au_sbtype(sb), MAJOR(sb->s_dev), MINOR(sb->s_dev), ++ sb->s_flags, sb->s_count, ++ atomic_read(&sb->s_active), ++ !!au_xino_file(br->br_xino, /*idx*/-1)); ++ return 0; ++ ++out: ++ dpri("s%d: err %ld\n", bindex, PTR_ERR(br)); ++ return -1; ++} ++ ++void au_dpri_sb(struct super_block *sb) ++{ ++ struct au_sbinfo *sbinfo; ++ aufs_bindex_t bindex; ++ int err; ++ /* to reduce stack size */ ++ struct { ++ struct vfsmount mnt; ++ struct au_branch fake; ++ } *a; ++ ++ /* this function can be called from magic sysrq */ ++ a = kzalloc(sizeof(*a), GFP_ATOMIC); ++ if (unlikely(!a)) { ++ dpri("no memory\n"); ++ return; ++ } ++ ++ a->mnt.mnt_sb = sb; ++ a->fake.br_path.mnt = &a->mnt; ++ err = do_pri_br(-1, &a->fake); ++ au_kfree_rcu(a); ++ dpri("dev 0x%x\n", sb->s_dev); ++ if (err || !au_test_aufs(sb)) ++ return; ++ ++ sbinfo = au_sbi(sb); ++ if (!sbinfo) ++ return; ++ dpri("nw %d, gen %u, kobj %d\n", ++ atomic_read(&sbinfo->si_nowait.nw_len), sbinfo->si_generation, ++ kref_read(&sbinfo->si_kobj.kref)); ++ for (bindex = 0; bindex <= sbinfo->si_bbot; bindex++) ++ do_pri_br(bindex, sbinfo->si_branch[0 + bindex]); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++void __au_dbg_verify_dinode(struct dentry *dentry, const char *func, int line) ++{ ++ struct inode *h_inode, *inode = d_inode(dentry); ++ struct dentry *h_dentry; ++ aufs_bindex_t bindex, bbot, bi; ++ ++ if (!inode /* || au_di(dentry)->di_lsc == AuLsc_DI_TMP */) ++ return; ++ ++ bbot = au_dbbot(dentry); ++ bi = au_ibbot(inode); ++ if (bi < bbot) ++ bbot = bi; ++ bindex = au_dbtop(dentry); ++ bi = au_ibtop(inode); ++ if (bi > bindex) ++ bindex = bi; ++ ++ for (; bindex <= bbot; bindex++) { ++ h_dentry = au_h_dptr(dentry, bindex); ++ if (!h_dentry) ++ continue; ++ h_inode = au_h_iptr(inode, bindex); ++ if (unlikely(h_inode != d_inode(h_dentry))) { ++ au_debug_on(); ++ AuDbg("b%d, %s:%d\n", bindex, func, line); ++ AuDbgDentry(dentry); ++ AuDbgInode(inode); ++ au_debug_off(); ++ BUG(); ++ } ++ } ++} ++ ++void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen) ++{ ++ int err, i, j; ++ struct au_dcsub_pages dpages; ++ struct au_dpage *dpage; ++ struct dentry **dentries; ++ ++ err = au_dpages_init(&dpages, GFP_NOFS); ++ AuDebugOn(err); ++ err = au_dcsub_pages_rev_aufs(&dpages, parent, /*do_include*/1); ++ AuDebugOn(err); ++ for (i = dpages.ndpage - 1; !err && i >= 0; i--) { ++ dpage = dpages.dpages + i; ++ dentries = dpage->dentries; ++ for (j = dpage->ndentry - 1; !err && j >= 0; j--) ++ AuDebugOn(au_digen_test(dentries[j], sigen)); ++ } ++ au_dpages_free(&dpages); ++} ++ ++void au_dbg_verify_kthread(void) ++{ ++ if (au_wkq_test()) { ++ au_dbg_blocked(); ++ /* ++ * It may be recursive, but udba=notify between two aufs mounts, ++ * where a single ro branch is shared, is not a problem. ++ */ ++ /* WARN_ON(1); */ ++ } ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++int __init au_debug_init(void) ++{ ++ aufs_bindex_t bindex; ++ struct au_vdir_destr destr; ++ ++ bindex = -1; ++ AuDebugOn(bindex >= 0); ++ ++ destr.len = -1; ++ AuDebugOn(destr.len < NAME_MAX); ++ ++#ifdef CONFIG_4KSTACKS ++ pr_warn("CONFIG_4KSTACKS is defined.\n"); ++#endif ++ ++ return 0; ++} +diff -Nurp linux-5.4/fs/aufs/debug.h linux-5.4-aufs/fs/aufs/debug.h +--- linux-5.4/fs/aufs/debug.h 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/debug.h 2019-11-28 01:25:59.063925618 +0200 +@@ -0,0 +1,213 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * debug print functions ++ */ ++ ++#ifndef __AUFS_DEBUG_H__ ++#define __AUFS_DEBUG_H__ ++ ++#ifdef __KERNEL__ ++ ++#include ++#include ++#include ++#include ++ ++#ifdef CONFIG_AUFS_DEBUG ++#define AuDebugOn(a) BUG_ON(a) ++ ++/* module parameter */ ++extern atomic_t aufs_debug; ++static inline void au_debug_on(void) ++{ ++ atomic_inc(&aufs_debug); ++} ++static inline void au_debug_off(void) ++{ ++ atomic_dec_if_positive(&aufs_debug); ++} ++ ++static inline int au_debug_test(void) ++{ ++ return atomic_read(&aufs_debug) > 0; ++} ++#else ++#define AuDebugOn(a) do {} while (0) ++AuStubVoid(au_debug_on, void) ++AuStubVoid(au_debug_off, void) ++AuStubInt0(au_debug_test, void) ++#endif /* CONFIG_AUFS_DEBUG */ ++ ++#define param_check_atomic_t(name, p) __param_check(name, p, atomic_t) ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* debug print */ ++ ++#define AuDbg(fmt, ...) do { \ ++ if (au_debug_test()) \ ++ pr_debug("DEBUG: " fmt, ##__VA_ARGS__); \ ++} while (0) ++#define AuLabel(l) AuDbg(#l "\n") ++#define AuIOErr(fmt, ...) pr_err("I/O Error, " fmt, ##__VA_ARGS__) ++#define AuWarn1(fmt, ...) do { \ ++ static unsigned char _c; \ ++ if (!_c++) \ ++ pr_warn(fmt, ##__VA_ARGS__); \ ++} while (0) ++ ++#define AuErr1(fmt, ...) do { \ ++ static unsigned char _c; \ ++ if (!_c++) \ ++ pr_err(fmt, ##__VA_ARGS__); \ ++} while (0) ++ ++#define AuIOErr1(fmt, ...) do { \ ++ static unsigned char _c; \ ++ if (!_c++) \ ++ AuIOErr(fmt, ##__VA_ARGS__); \ ++} while (0) ++ ++#define AuUnsupportMsg "This operation is not supported." \ ++ " Please report this application to aufs-users ML." ++#define AuUnsupport(fmt, ...) do { \ ++ pr_err(AuUnsupportMsg "\n" fmt, ##__VA_ARGS__); \ ++ dump_stack(); \ ++} while (0) ++ ++#define AuTraceErr(e) do { \ ++ if (unlikely((e) < 0)) \ ++ AuDbg("err %d\n", (int)(e)); \ ++} while (0) ++ ++#define AuTraceErrPtr(p) do { \ ++ if (IS_ERR(p)) \ ++ AuDbg("err %ld\n", PTR_ERR(p)); \ ++} while (0) ++ ++/* dirty macros for debug print, use with "%.*s" and caution */ ++#define AuLNPair(qstr) (qstr)->len, (qstr)->name ++ ++/* ---------------------------------------------------------------------- */ ++ ++struct dentry; ++#ifdef CONFIG_AUFS_DEBUG ++extern struct mutex au_dbg_mtx; ++extern char *au_plevel; ++struct au_nhash; ++void au_dpri_whlist(struct au_nhash *whlist); ++struct au_vdir; ++void au_dpri_vdir(struct au_vdir *vdir); ++struct inode; ++void au_dpri_inode(struct inode *inode); ++void au_dpri_dalias(struct inode *inode); ++void au_dpri_dentry(struct dentry *dentry); ++struct file; ++void au_dpri_file(struct file *filp); ++struct super_block; ++void au_dpri_sb(struct super_block *sb); ++ ++#define au_dbg_verify_dinode(d) __au_dbg_verify_dinode(d, __func__, __LINE__) ++void __au_dbg_verify_dinode(struct dentry *dentry, const char *func, int line); ++void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen); ++void au_dbg_verify_kthread(void); ++ ++int __init au_debug_init(void); ++ ++#define AuDbgWhlist(w) do { \ ++ mutex_lock(&au_dbg_mtx); \ ++ AuDbg(#w "\n"); \ ++ au_dpri_whlist(w); \ ++ mutex_unlock(&au_dbg_mtx); \ ++} while (0) ++ ++#define AuDbgVdir(v) do { \ ++ mutex_lock(&au_dbg_mtx); \ ++ AuDbg(#v "\n"); \ ++ au_dpri_vdir(v); \ ++ mutex_unlock(&au_dbg_mtx); \ ++} while (0) ++ ++#define AuDbgInode(i) do { \ ++ mutex_lock(&au_dbg_mtx); \ ++ AuDbg(#i "\n"); \ ++ au_dpri_inode(i); \ ++ mutex_unlock(&au_dbg_mtx); \ ++} while (0) ++ ++#define AuDbgDAlias(i) do { \ ++ mutex_lock(&au_dbg_mtx); \ ++ AuDbg(#i "\n"); \ ++ au_dpri_dalias(i); \ ++ mutex_unlock(&au_dbg_mtx); \ ++} while (0) ++ ++#define AuDbgDentry(d) do { \ ++ mutex_lock(&au_dbg_mtx); \ ++ AuDbg(#d "\n"); \ ++ au_dpri_dentry(d); \ ++ mutex_unlock(&au_dbg_mtx); \ ++} while (0) ++ ++#define AuDbgFile(f) do { \ ++ mutex_lock(&au_dbg_mtx); \ ++ AuDbg(#f "\n"); \ ++ au_dpri_file(f); \ ++ mutex_unlock(&au_dbg_mtx); \ ++} while (0) ++ ++#define AuDbgSb(sb) do { \ ++ mutex_lock(&au_dbg_mtx); \ ++ AuDbg(#sb "\n"); \ ++ au_dpri_sb(sb); \ ++ mutex_unlock(&au_dbg_mtx); \ ++} while (0) ++ ++#define AuDbgSym(addr) do { \ ++ char sym[KSYM_SYMBOL_LEN]; \ ++ sprint_symbol(sym, (unsigned long)addr); \ ++ AuDbg("%s\n", sym); \ ++} while (0) ++#else ++AuStubVoid(au_dbg_verify_dinode, struct dentry *dentry) ++AuStubVoid(au_dbg_verify_gen, struct dentry *parent, unsigned int sigen) ++AuStubVoid(au_dbg_verify_kthread, void) ++AuStubInt0(__init au_debug_init, void) ++ ++#define AuDbgWhlist(w) do {} while (0) ++#define AuDbgVdir(v) do {} while (0) ++#define AuDbgInode(i) do {} while (0) ++#define AuDbgDAlias(i) do {} while (0) ++#define AuDbgDentry(d) do {} while (0) ++#define AuDbgFile(f) do {} while (0) ++#define AuDbgSb(sb) do {} while (0) ++#define AuDbgSym(addr) do {} while (0) ++#endif /* CONFIG_AUFS_DEBUG */ ++ ++/* ---------------------------------------------------------------------- */ ++ ++#ifdef CONFIG_AUFS_MAGIC_SYSRQ ++int __init au_sysrq_init(void); ++void au_sysrq_fin(void); ++ ++#ifdef CONFIG_HW_CONSOLE ++#define au_dbg_blocked() do { \ ++ WARN_ON(1); \ ++ handle_sysrq('w'); \ ++} while (0) ++#else ++AuStubVoid(au_dbg_blocked, void) ++#endif ++ ++#else ++AuStubInt0(__init au_sysrq_init, void) ++AuStubVoid(au_sysrq_fin, void) ++AuStubVoid(au_dbg_blocked, void) ++#endif /* CONFIG_AUFS_MAGIC_SYSRQ */ ++ ++#endif /* __KERNEL__ */ ++#endif /* __AUFS_DEBUG_H__ */ +diff -Nurp linux-5.4/fs/aufs/dentry.c linux-5.4-aufs/fs/aufs/dentry.c +--- linux-5.4/fs/aufs/dentry.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/dentry.c 2019-11-28 01:25:59.063925618 +0200 +@@ -0,0 +1,1141 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * lookup and dentry operations ++ */ ++ ++#include ++#include ++#include "aufs.h" ++ ++/* ++ * returns positive/negative dentry, NULL or an error. ++ * NULL means whiteout-ed or not-found. ++ */ ++static struct dentry* ++au_do_lookup(struct dentry *h_parent, struct dentry *dentry, ++ aufs_bindex_t bindex, struct au_do_lookup_args *args) ++{ ++ struct dentry *h_dentry; ++ struct inode *h_inode; ++ struct au_branch *br; ++ int wh_found, opq; ++ unsigned char wh_able; ++ const unsigned char allow_neg = !!au_ftest_lkup(args->flags, ALLOW_NEG); ++ const unsigned char ignore_perm = !!au_ftest_lkup(args->flags, ++ IGNORE_PERM); ++ ++ wh_found = 0; ++ br = au_sbr(dentry->d_sb, bindex); ++ wh_able = !!au_br_whable(br->br_perm); ++ if (wh_able) ++ wh_found = au_wh_test(h_parent, &args->whname, ignore_perm); ++ h_dentry = ERR_PTR(wh_found); ++ if (!wh_found) ++ goto real_lookup; ++ if (unlikely(wh_found < 0)) ++ goto out; ++ ++ /* We found a whiteout */ ++ /* au_set_dbbot(dentry, bindex); */ ++ au_set_dbwh(dentry, bindex); ++ if (!allow_neg) ++ return NULL; /* success */ ++ ++real_lookup: ++ if (!ignore_perm) ++ h_dentry = vfsub_lkup_one(args->name, h_parent); ++ else ++ h_dentry = au_sio_lkup_one(args->name, h_parent); ++ if (IS_ERR(h_dentry)) { ++ if (PTR_ERR(h_dentry) == -ENAMETOOLONG ++ && !allow_neg) ++ h_dentry = NULL; ++ goto out; ++ } ++ ++ h_inode = d_inode(h_dentry); ++ if (d_is_negative(h_dentry)) { ++ if (!allow_neg) ++ goto out_neg; ++ } else if (wh_found ++ || (args->type && args->type != (h_inode->i_mode & S_IFMT))) ++ goto out_neg; ++ else if (au_ftest_lkup(args->flags, DIRREN) ++ /* && h_inode */ ++ && !au_dr_lkup_h_ino(args, bindex, h_inode->i_ino)) { ++ AuDbg("b%d %pd ignored hi%llu\n", bindex, h_dentry, ++ (unsigned long long)h_inode->i_ino); ++ goto out_neg; ++ } ++ ++ if (au_dbbot(dentry) <= bindex) ++ au_set_dbbot(dentry, bindex); ++ if (au_dbtop(dentry) < 0 || bindex < au_dbtop(dentry)) ++ au_set_dbtop(dentry, bindex); ++ au_set_h_dptr(dentry, bindex, h_dentry); ++ ++ if (!d_is_dir(h_dentry) ++ || !wh_able ++ || (d_really_is_positive(dentry) && !d_is_dir(dentry))) ++ goto out; /* success */ ++ ++ inode_lock_shared_nested(h_inode, AuLsc_I_CHILD); ++ opq = au_diropq_test(h_dentry); ++ inode_unlock_shared(h_inode); ++ if (opq > 0) ++ au_set_dbdiropq(dentry, bindex); ++ else if (unlikely(opq < 0)) { ++ au_set_h_dptr(dentry, bindex, NULL); ++ h_dentry = ERR_PTR(opq); ++ } ++ goto out; ++ ++out_neg: ++ dput(h_dentry); ++ h_dentry = NULL; ++out: ++ return h_dentry; ++} ++ ++static int au_test_shwh(struct super_block *sb, const struct qstr *name) ++{ ++ if (unlikely(!au_opt_test(au_mntflags(sb), SHWH) ++ && !strncmp(name->name, AUFS_WH_PFX, AUFS_WH_PFX_LEN))) ++ return -EPERM; ++ return 0; ++} ++ ++/* ++ * returns the number of lower positive dentries, ++ * otherwise an error. ++ * can be called at unlinking with @type is zero. ++ */ ++int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t btop, ++ unsigned int flags) ++{ ++ int npositive, err; ++ aufs_bindex_t bindex, btail, bdiropq; ++ unsigned char isdir, dirperm1, dirren; ++ struct au_do_lookup_args args = { ++ .flags = flags, ++ .name = &dentry->d_name ++ }; ++ struct dentry *parent; ++ struct super_block *sb; ++ ++ sb = dentry->d_sb; ++ err = au_test_shwh(sb, args.name); ++ if (unlikely(err)) ++ goto out; ++ ++ err = au_wh_name_alloc(&args.whname, args.name); ++ if (unlikely(err)) ++ goto out; ++ ++ isdir = !!d_is_dir(dentry); ++ dirperm1 = !!au_opt_test(au_mntflags(sb), DIRPERM1); ++ dirren = !!au_opt_test(au_mntflags(sb), DIRREN); ++ if (dirren) ++ au_fset_lkup(args.flags, DIRREN); ++ ++ npositive = 0; ++ parent = dget_parent(dentry); ++ btail = au_dbtaildir(parent); ++ for (bindex = btop; bindex <= btail; bindex++) { ++ struct dentry *h_parent, *h_dentry; ++ struct inode *h_inode, *h_dir; ++ struct au_branch *br; ++ ++ h_dentry = au_h_dptr(dentry, bindex); ++ if (h_dentry) { ++ if (d_is_positive(h_dentry)) ++ npositive++; ++ break; ++ } ++ h_parent = au_h_dptr(parent, bindex); ++ if (!h_parent || !d_is_dir(h_parent)) ++ continue; ++ ++ if (dirren) { ++ /* if the inum matches, then use the prepared name */ ++ err = au_dr_lkup_name(&args, bindex); ++ if (unlikely(err)) ++ goto out_parent; ++ } ++ ++ h_dir = d_inode(h_parent); ++ inode_lock_shared_nested(h_dir, AuLsc_I_PARENT); ++ h_dentry = au_do_lookup(h_parent, dentry, bindex, &args); ++ inode_unlock_shared(h_dir); ++ err = PTR_ERR(h_dentry); ++ if (IS_ERR(h_dentry)) ++ goto out_parent; ++ if (h_dentry) ++ au_fclr_lkup(args.flags, ALLOW_NEG); ++ if (dirperm1) ++ au_fset_lkup(args.flags, IGNORE_PERM); ++ ++ if (au_dbwh(dentry) == bindex) ++ break; ++ if (!h_dentry) ++ continue; ++ if (d_is_negative(h_dentry)) ++ continue; ++ h_inode = d_inode(h_dentry); ++ npositive++; ++ if (!args.type) ++ args.type = h_inode->i_mode & S_IFMT; ++ if (args.type != S_IFDIR) ++ break; ++ else if (isdir) { ++ /* the type of lower may be different */ ++ bdiropq = au_dbdiropq(dentry); ++ if (bdiropq >= 0 && bdiropq <= bindex) ++ break; ++ } ++ br = au_sbr(sb, bindex); ++ if (dirren ++ && au_dr_hino_test_add(&br->br_dirren, h_inode->i_ino, ++ /*add_ent*/NULL)) { ++ /* prepare next name to lookup */ ++ err = au_dr_lkup(&args, dentry, bindex); ++ if (unlikely(err)) ++ goto out_parent; ++ } ++ } ++ ++ if (npositive) { ++ AuLabel(positive); ++ au_update_dbtop(dentry); ++ } ++ err = npositive; ++ if (unlikely(!au_opt_test(au_mntflags(sb), UDBA_NONE) ++ && au_dbtop(dentry) < 0)) { ++ err = -EIO; ++ AuIOErr("both of real entry and whiteout found, %pd, err %d\n", ++ dentry, err); ++ } ++ ++out_parent: ++ dput(parent); ++ au_kfree_try_rcu(args.whname.name); ++ if (dirren) ++ au_dr_lkup_fin(&args); ++out: ++ return err; ++} ++ ++struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent) ++{ ++ struct dentry *dentry; ++ int wkq_err; ++ ++ if (!au_test_h_perm_sio(d_inode(parent), MAY_EXEC)) ++ dentry = vfsub_lkup_one(name, parent); ++ else { ++ struct vfsub_lkup_one_args args = { ++ .errp = &dentry, ++ .name = name, ++ .parent = parent ++ }; ++ ++ wkq_err = au_wkq_wait(vfsub_call_lkup_one, &args); ++ if (unlikely(wkq_err)) ++ dentry = ERR_PTR(wkq_err); ++ } ++ ++ return dentry; ++} ++ ++/* ++ * lookup @dentry on @bindex which should be negative. ++ */ ++int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex, int wh) ++{ ++ int err; ++ struct dentry *parent, *h_parent, *h_dentry; ++ struct au_branch *br; ++ ++ parent = dget_parent(dentry); ++ h_parent = au_h_dptr(parent, bindex); ++ br = au_sbr(dentry->d_sb, bindex); ++ if (wh) ++ h_dentry = au_whtmp_lkup(h_parent, br, &dentry->d_name); ++ else ++ h_dentry = au_sio_lkup_one(&dentry->d_name, h_parent); ++ err = PTR_ERR(h_dentry); ++ if (IS_ERR(h_dentry)) ++ goto out; ++ if (unlikely(d_is_positive(h_dentry))) { ++ err = -EIO; ++ AuIOErr("%pd should be negative on b%d.\n", h_dentry, bindex); ++ dput(h_dentry); ++ goto out; ++ } ++ ++ err = 0; ++ if (bindex < au_dbtop(dentry)) ++ au_set_dbtop(dentry, bindex); ++ if (au_dbbot(dentry) < bindex) ++ au_set_dbbot(dentry, bindex); ++ au_set_h_dptr(dentry, bindex, h_dentry); ++ ++out: ++ dput(parent); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* subset of struct inode */ ++struct au_iattr { ++ unsigned long i_ino; ++ /* unsigned int i_nlink; */ ++ kuid_t i_uid; ++ kgid_t i_gid; ++ u64 i_version; ++/* ++ loff_t i_size; ++ blkcnt_t i_blocks; ++*/ ++ umode_t i_mode; ++}; ++ ++static void au_iattr_save(struct au_iattr *ia, struct inode *h_inode) ++{ ++ ia->i_ino = h_inode->i_ino; ++ /* ia->i_nlink = h_inode->i_nlink; */ ++ ia->i_uid = h_inode->i_uid; ++ ia->i_gid = h_inode->i_gid; ++ ia->i_version = inode_query_iversion(h_inode); ++/* ++ ia->i_size = h_inode->i_size; ++ ia->i_blocks = h_inode->i_blocks; ++*/ ++ ia->i_mode = (h_inode->i_mode & S_IFMT); ++} ++ ++static int au_iattr_test(struct au_iattr *ia, struct inode *h_inode) ++{ ++ return ia->i_ino != h_inode->i_ino ++ /* || ia->i_nlink != h_inode->i_nlink */ ++ || !uid_eq(ia->i_uid, h_inode->i_uid) ++ || !gid_eq(ia->i_gid, h_inode->i_gid) ++ || !inode_eq_iversion(h_inode, ia->i_version) ++/* ++ || ia->i_size != h_inode->i_size ++ || ia->i_blocks != h_inode->i_blocks ++*/ ++ || ia->i_mode != (h_inode->i_mode & S_IFMT); ++} ++ ++static int au_h_verify_dentry(struct dentry *h_dentry, struct dentry *h_parent, ++ struct au_branch *br) ++{ ++ int err; ++ struct au_iattr ia; ++ struct inode *h_inode; ++ struct dentry *h_d; ++ struct super_block *h_sb; ++ ++ err = 0; ++ memset(&ia, -1, sizeof(ia)); ++ h_sb = h_dentry->d_sb; ++ h_inode = NULL; ++ if (d_is_positive(h_dentry)) { ++ h_inode = d_inode(h_dentry); ++ au_iattr_save(&ia, h_inode); ++ } else if (au_test_nfs(h_sb) || au_test_fuse(h_sb)) ++ /* nfs d_revalidate may return 0 for negative dentry */ ++ /* fuse d_revalidate always return 0 for negative dentry */ ++ goto out; ++ ++ /* main purpose is namei.c:cached_lookup() and d_revalidate */ ++ h_d = vfsub_lkup_one(&h_dentry->d_name, h_parent); ++ err = PTR_ERR(h_d); ++ if (IS_ERR(h_d)) ++ goto out; ++ ++ err = 0; ++ if (unlikely(h_d != h_dentry ++ || d_inode(h_d) != h_inode ++ || (h_inode && au_iattr_test(&ia, h_inode)))) ++ err = au_busy_or_stale(); ++ dput(h_d); ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir, ++ struct dentry *h_parent, struct au_branch *br) ++{ ++ int err; ++ ++ err = 0; ++ if (udba == AuOpt_UDBA_REVAL ++ && !au_test_fs_remote(h_dentry->d_sb)) { ++ IMustLock(h_dir); ++ err = (d_inode(h_dentry->d_parent) != h_dir); ++ } else if (udba != AuOpt_UDBA_NONE) ++ err = au_h_verify_dentry(h_dentry, h_parent, br); ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int au_do_refresh_hdentry(struct dentry *dentry, struct dentry *parent) ++{ ++ int err; ++ aufs_bindex_t new_bindex, bindex, bbot, bwh, bdiropq; ++ struct au_hdentry tmp, *p, *q; ++ struct au_dinfo *dinfo; ++ struct super_block *sb; ++ ++ DiMustWriteLock(dentry); ++ ++ sb = dentry->d_sb; ++ dinfo = au_di(dentry); ++ bbot = dinfo->di_bbot; ++ bwh = dinfo->di_bwh; ++ bdiropq = dinfo->di_bdiropq; ++ bindex = dinfo->di_btop; ++ p = au_hdentry(dinfo, bindex); ++ for (; bindex <= bbot; bindex++, p++) { ++ if (!p->hd_dentry) ++ continue; ++ ++ new_bindex = au_br_index(sb, p->hd_id); ++ if (new_bindex == bindex) ++ continue; ++ ++ if (dinfo->di_bwh == bindex) ++ bwh = new_bindex; ++ if (dinfo->di_bdiropq == bindex) ++ bdiropq = new_bindex; ++ if (new_bindex < 0) { ++ au_hdput(p); ++ p->hd_dentry = NULL; ++ continue; ++ } ++ ++ /* swap two lower dentries, and loop again */ ++ q = au_hdentry(dinfo, new_bindex); ++ tmp = *q; ++ *q = *p; ++ *p = tmp; ++ if (tmp.hd_dentry) { ++ bindex--; ++ p--; ++ } ++ } ++ ++ dinfo->di_bwh = -1; ++ if (bwh >= 0 && bwh <= au_sbbot(sb) && au_sbr_whable(sb, bwh)) ++ dinfo->di_bwh = bwh; ++ ++ dinfo->di_bdiropq = -1; ++ if (bdiropq >= 0 ++ && bdiropq <= au_sbbot(sb) ++ && au_sbr_whable(sb, bdiropq)) ++ dinfo->di_bdiropq = bdiropq; ++ ++ err = -EIO; ++ dinfo->di_btop = -1; ++ dinfo->di_bbot = -1; ++ bbot = au_dbbot(parent); ++ bindex = 0; ++ p = au_hdentry(dinfo, bindex); ++ for (; bindex <= bbot; bindex++, p++) ++ if (p->hd_dentry) { ++ dinfo->di_btop = bindex; ++ break; ++ } ++ ++ if (dinfo->di_btop >= 0) { ++ bindex = bbot; ++ p = au_hdentry(dinfo, bindex); ++ for (; bindex >= 0; bindex--, p--) ++ if (p->hd_dentry) { ++ dinfo->di_bbot = bindex; ++ err = 0; ++ break; ++ } ++ } ++ ++ return err; ++} ++ ++static void au_do_hide(struct dentry *dentry) ++{ ++ struct inode *inode; ++ ++ if (d_really_is_positive(dentry)) { ++ inode = d_inode(dentry); ++ if (!d_is_dir(dentry)) { ++ if (inode->i_nlink && !d_unhashed(dentry)) ++ drop_nlink(inode); ++ } else { ++ clear_nlink(inode); ++ /* stop next lookup */ ++ inode->i_flags |= S_DEAD; ++ } ++ smp_mb(); /* necessary? */ ++ } ++ d_drop(dentry); ++} ++ ++static int au_hide_children(struct dentry *parent) ++{ ++ int err, i, j, ndentry; ++ struct au_dcsub_pages dpages; ++ struct au_dpage *dpage; ++ struct dentry *dentry; ++ ++ err = au_dpages_init(&dpages, GFP_NOFS); ++ if (unlikely(err)) ++ goto out; ++ err = au_dcsub_pages(&dpages, parent, NULL, NULL); ++ if (unlikely(err)) ++ goto out_dpages; ++ ++ /* in reverse order */ ++ for (i = dpages.ndpage - 1; i >= 0; i--) { ++ dpage = dpages.dpages + i; ++ ndentry = dpage->ndentry; ++ for (j = ndentry - 1; j >= 0; j--) { ++ dentry = dpage->dentries[j]; ++ if (dentry != parent) ++ au_do_hide(dentry); ++ } ++ } ++ ++out_dpages: ++ au_dpages_free(&dpages); ++out: ++ return err; ++} ++ ++static void au_hide(struct dentry *dentry) ++{ ++ int err; ++ ++ AuDbgDentry(dentry); ++ if (d_is_dir(dentry)) { ++ /* shrink_dcache_parent(dentry); */ ++ err = au_hide_children(dentry); ++ if (unlikely(err)) ++ AuIOErr("%pd, failed hiding children, ignored %d\n", ++ dentry, err); ++ } ++ au_do_hide(dentry); ++} ++ ++/* ++ * By adding a dirty branch, a cached dentry may be affected in various ways. ++ * ++ * a dirty branch is added ++ * - on the top of layers ++ * - in the middle of layers ++ * - to the bottom of layers ++ * ++ * on the added branch there exists ++ * - a whiteout ++ * - a diropq ++ * - a same named entry ++ * + exist ++ * * negative --> positive ++ * * positive --> positive ++ * - type is unchanged ++ * - type is changed ++ * + doesn't exist ++ * * negative --> negative ++ * * positive --> negative (rejected by au_br_del() for non-dir case) ++ * - none ++ */ ++static int au_refresh_by_dinfo(struct dentry *dentry, struct au_dinfo *dinfo, ++ struct au_dinfo *tmp) ++{ ++ int err; ++ aufs_bindex_t bindex, bbot; ++ struct { ++ struct dentry *dentry; ++ struct inode *inode; ++ mode_t mode; ++ } orig_h, tmp_h = { ++ .dentry = NULL ++ }; ++ struct au_hdentry *hd; ++ struct inode *inode, *h_inode; ++ struct dentry *h_dentry; ++ ++ err = 0; ++ AuDebugOn(dinfo->di_btop < 0); ++ orig_h.mode = 0; ++ orig_h.dentry = au_hdentry(dinfo, dinfo->di_btop)->hd_dentry; ++ orig_h.inode = NULL; ++ if (d_is_positive(orig_h.dentry)) { ++ orig_h.inode = d_inode(orig_h.dentry); ++ orig_h.mode = orig_h.inode->i_mode & S_IFMT; ++ } ++ if (tmp->di_btop >= 0) { ++ tmp_h.dentry = au_hdentry(tmp, tmp->di_btop)->hd_dentry; ++ if (d_is_positive(tmp_h.dentry)) { ++ tmp_h.inode = d_inode(tmp_h.dentry); ++ tmp_h.mode = tmp_h.inode->i_mode & S_IFMT; ++ } ++ } ++ ++ inode = NULL; ++ if (d_really_is_positive(dentry)) ++ inode = d_inode(dentry); ++ if (!orig_h.inode) { ++ AuDbg("negative originally\n"); ++ if (inode) { ++ au_hide(dentry); ++ goto out; ++ } ++ AuDebugOn(inode); ++ AuDebugOn(dinfo->di_btop != dinfo->di_bbot); ++ AuDebugOn(dinfo->di_bdiropq != -1); ++ ++ if (!tmp_h.inode) { ++ AuDbg("negative --> negative\n"); ++ /* should have only one negative lower */ ++ if (tmp->di_btop >= 0 ++ && tmp->di_btop < dinfo->di_btop) { ++ AuDebugOn(tmp->di_btop != tmp->di_bbot); ++ AuDebugOn(dinfo->di_btop != dinfo->di_bbot); ++ au_set_h_dptr(dentry, dinfo->di_btop, NULL); ++ au_di_cp(dinfo, tmp); ++ hd = au_hdentry(tmp, tmp->di_btop); ++ au_set_h_dptr(dentry, tmp->di_btop, ++ dget(hd->hd_dentry)); ++ } ++ au_dbg_verify_dinode(dentry); ++ } else { ++ AuDbg("negative --> positive\n"); ++ /* ++ * similar to the behaviour of creating with bypassing ++ * aufs. ++ * unhash it in order to force an error in the ++ * succeeding create operation. ++ * we should not set S_DEAD here. ++ */ ++ d_drop(dentry); ++ /* au_di_swap(tmp, dinfo); */ ++ au_dbg_verify_dinode(dentry); ++ } ++ } else { ++ AuDbg("positive originally\n"); ++ /* inode may be NULL */ ++ AuDebugOn(inode && (inode->i_mode & S_IFMT) != orig_h.mode); ++ if (!tmp_h.inode) { ++ AuDbg("positive --> negative\n"); ++ /* or bypassing aufs */ ++ au_hide(dentry); ++ if (tmp->di_bwh >= 0 && tmp->di_bwh <= dinfo->di_btop) ++ dinfo->di_bwh = tmp->di_bwh; ++ if (inode) ++ err = au_refresh_hinode_self(inode); ++ au_dbg_verify_dinode(dentry); ++ } else if (orig_h.mode == tmp_h.mode) { ++ AuDbg("positive --> positive, same type\n"); ++ if (!S_ISDIR(orig_h.mode) ++ && dinfo->di_btop > tmp->di_btop) { ++ /* ++ * similar to the behaviour of removing and ++ * creating. ++ */ ++ au_hide(dentry); ++ if (inode) ++ err = au_refresh_hinode_self(inode); ++ au_dbg_verify_dinode(dentry); ++ } else { ++ /* fill empty slots */ ++ if (dinfo->di_btop > tmp->di_btop) ++ dinfo->di_btop = tmp->di_btop; ++ if (dinfo->di_bbot < tmp->di_bbot) ++ dinfo->di_bbot = tmp->di_bbot; ++ dinfo->di_bwh = tmp->di_bwh; ++ dinfo->di_bdiropq = tmp->di_bdiropq; ++ bbot = dinfo->di_bbot; ++ bindex = tmp->di_btop; ++ hd = au_hdentry(tmp, bindex); ++ for (; bindex <= bbot; bindex++, hd++) { ++ if (au_h_dptr(dentry, bindex)) ++ continue; ++ h_dentry = hd->hd_dentry; ++ if (!h_dentry) ++ continue; ++ AuDebugOn(d_is_negative(h_dentry)); ++ h_inode = d_inode(h_dentry); ++ AuDebugOn(orig_h.mode ++ != (h_inode->i_mode ++ & S_IFMT)); ++ au_set_h_dptr(dentry, bindex, ++ dget(h_dentry)); ++ } ++ if (inode) ++ err = au_refresh_hinode(inode, dentry); ++ au_dbg_verify_dinode(dentry); ++ } ++ } else { ++ AuDbg("positive --> positive, different type\n"); ++ /* similar to the behaviour of removing and creating */ ++ au_hide(dentry); ++ if (inode) ++ err = au_refresh_hinode_self(inode); ++ au_dbg_verify_dinode(dentry); ++ } ++ } ++ ++out: ++ return err; ++} ++ ++void au_refresh_dop(struct dentry *dentry, int force_reval) ++{ ++ const struct dentry_operations *dop ++ = force_reval ? &aufs_dop : dentry->d_sb->s_d_op; ++ static const unsigned int mask ++ = DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE; ++ ++ BUILD_BUG_ON(sizeof(mask) != sizeof(dentry->d_flags)); ++ ++ if (dentry->d_op == dop) ++ return; ++ ++ AuDbg("%pd\n", dentry); ++ spin_lock(&dentry->d_lock); ++ if (dop == &aufs_dop) ++ dentry->d_flags |= mask; ++ else ++ dentry->d_flags &= ~mask; ++ dentry->d_op = dop; ++ spin_unlock(&dentry->d_lock); ++} ++ ++int au_refresh_dentry(struct dentry *dentry, struct dentry *parent) ++{ ++ int err, ebrange, nbr; ++ unsigned int sigen; ++ struct au_dinfo *dinfo, *tmp; ++ struct super_block *sb; ++ struct inode *inode; ++ ++ DiMustWriteLock(dentry); ++ AuDebugOn(IS_ROOT(dentry)); ++ AuDebugOn(d_really_is_negative(parent)); ++ ++ sb = dentry->d_sb; ++ sigen = au_sigen(sb); ++ err = au_digen_test(parent, sigen); ++ if (unlikely(err)) ++ goto out; ++ ++ nbr = au_sbbot(sb) + 1; ++ dinfo = au_di(dentry); ++ err = au_di_realloc(dinfo, nbr, /*may_shrink*/0); ++ if (unlikely(err)) ++ goto out; ++ ebrange = au_dbrange_test(dentry); ++ if (!ebrange) ++ ebrange = au_do_refresh_hdentry(dentry, parent); ++ ++ if (d_unhashed(dentry) || ebrange /* || dinfo->di_tmpfile */) { ++ AuDebugOn(au_dbtop(dentry) < 0 && au_dbbot(dentry) >= 0); ++ if (d_really_is_positive(dentry)) { ++ inode = d_inode(dentry); ++ err = au_refresh_hinode_self(inode); ++ } ++ au_dbg_verify_dinode(dentry); ++ if (!err) ++ goto out_dgen; /* success */ ++ goto out; ++ } ++ ++ /* temporary dinfo */ ++ AuDbgDentry(dentry); ++ err = -ENOMEM; ++ tmp = au_di_alloc(sb, AuLsc_DI_TMP); ++ if (unlikely(!tmp)) ++ goto out; ++ au_di_swap(tmp, dinfo); ++ /* returns the number of positive dentries */ ++ /* ++ * if current working dir is removed, it returns an error. ++ * but the dentry is legal. ++ */ ++ err = au_lkup_dentry(dentry, /*btop*/0, AuLkup_ALLOW_NEG); ++ AuDbgDentry(dentry); ++ au_di_swap(tmp, dinfo); ++ if (err == -ENOENT) ++ err = 0; ++ if (err >= 0) { ++ /* compare/refresh by dinfo */ ++ AuDbgDentry(dentry); ++ err = au_refresh_by_dinfo(dentry, dinfo, tmp); ++ au_dbg_verify_dinode(dentry); ++ AuTraceErr(err); ++ } ++ au_di_realloc(dinfo, nbr, /*may_shrink*/1); /* harmless if err */ ++ au_rw_write_unlock(&tmp->di_rwsem); ++ au_di_free(tmp); ++ if (unlikely(err)) ++ goto out; ++ ++out_dgen: ++ au_update_digen(dentry); ++out: ++ if (unlikely(err && !(dentry->d_flags & DCACHE_NFSFS_RENAMED))) { ++ AuIOErr("failed refreshing %pd, %d\n", dentry, err); ++ AuDbgDentry(dentry); ++ } ++ AuTraceErr(err); ++ return err; ++} ++ ++static int au_do_h_d_reval(struct dentry *h_dentry, unsigned int flags, ++ struct dentry *dentry, aufs_bindex_t bindex) ++{ ++ int err, valid; ++ ++ err = 0; ++ if (!(h_dentry->d_flags & DCACHE_OP_REVALIDATE)) ++ goto out; ++ ++ AuDbg("b%d\n", bindex); ++ /* ++ * gave up supporting LOOKUP_CREATE/OPEN for lower fs, ++ * due to whiteout and branch permission. ++ */ ++ flags &= ~(/*LOOKUP_PARENT |*/ LOOKUP_OPEN | LOOKUP_CREATE ++ | LOOKUP_FOLLOW | LOOKUP_EXCL); ++ /* it may return tri-state */ ++ valid = h_dentry->d_op->d_revalidate(h_dentry, flags); ++ ++ if (unlikely(valid < 0)) ++ err = valid; ++ else if (!valid) ++ err = -EINVAL; ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++/* todo: remove this */ ++static int h_d_revalidate(struct dentry *dentry, struct inode *inode, ++ unsigned int flags, int do_udba, int dirren) ++{ ++ int err; ++ umode_t mode, h_mode; ++ aufs_bindex_t bindex, btail, btop, ibs, ibe; ++ unsigned char plus, unhashed, is_root, h_plus, h_nfs, tmpfile; ++ struct inode *h_inode, *h_cached_inode; ++ struct dentry *h_dentry; ++ struct qstr *name, *h_name; ++ ++ err = 0; ++ plus = 0; ++ mode = 0; ++ ibs = -1; ++ ibe = -1; ++ unhashed = !!d_unhashed(dentry); ++ is_root = !!IS_ROOT(dentry); ++ name = &dentry->d_name; ++ tmpfile = au_di(dentry)->di_tmpfile; ++ ++ /* ++ * Theoretically, REVAL test should be unnecessary in case of ++ * {FS,I}NOTIFY. ++ * But {fs,i}notify doesn't fire some necessary events, ++ * IN_ATTRIB for atime/nlink/pageio ++ * Let's do REVAL test too. ++ */ ++ if (do_udba && inode) { ++ mode = (inode->i_mode & S_IFMT); ++ plus = (inode->i_nlink > 0); ++ ibs = au_ibtop(inode); ++ ibe = au_ibbot(inode); ++ } ++ ++ btop = au_dbtop(dentry); ++ btail = btop; ++ if (inode && S_ISDIR(inode->i_mode)) ++ btail = au_dbtaildir(dentry); ++ for (bindex = btop; bindex <= btail; bindex++) { ++ h_dentry = au_h_dptr(dentry, bindex); ++ if (!h_dentry) ++ continue; ++ ++ AuDbg("b%d, %pd\n", bindex, h_dentry); ++ h_nfs = !!au_test_nfs(h_dentry->d_sb); ++ spin_lock(&h_dentry->d_lock); ++ h_name = &h_dentry->d_name; ++ if (unlikely(do_udba ++ && !is_root ++ && ((!h_nfs ++ && (unhashed != !!d_unhashed(h_dentry) ++ || (!tmpfile && !dirren ++ && !au_qstreq(name, h_name)) ++ )) ++ || (h_nfs ++ && !(flags & LOOKUP_OPEN) ++ && (h_dentry->d_flags ++ & DCACHE_NFSFS_RENAMED))) ++ )) { ++ int h_unhashed; ++ ++ h_unhashed = d_unhashed(h_dentry); ++ spin_unlock(&h_dentry->d_lock); ++ AuDbg("unhash 0x%x 0x%x, %pd %pd\n", ++ unhashed, h_unhashed, dentry, h_dentry); ++ goto err; ++ } ++ spin_unlock(&h_dentry->d_lock); ++ ++ err = au_do_h_d_reval(h_dentry, flags, dentry, bindex); ++ if (unlikely(err)) ++ /* do not goto err, to keep the errno */ ++ break; ++ ++ /* todo: plink too? */ ++ if (!do_udba) ++ continue; ++ ++ /* UDBA tests */ ++ if (unlikely(!!inode != d_is_positive(h_dentry))) ++ goto err; ++ ++ h_inode = NULL; ++ if (d_is_positive(h_dentry)) ++ h_inode = d_inode(h_dentry); ++ h_plus = plus; ++ h_mode = mode; ++ h_cached_inode = h_inode; ++ if (h_inode) { ++ h_mode = (h_inode->i_mode & S_IFMT); ++ h_plus = (h_inode->i_nlink > 0); ++ } ++ if (inode && ibs <= bindex && bindex <= ibe) ++ h_cached_inode = au_h_iptr(inode, bindex); ++ ++ if (!h_nfs) { ++ if (unlikely(plus != h_plus && !tmpfile)) ++ goto err; ++ } else { ++ if (unlikely(!(h_dentry->d_flags & DCACHE_NFSFS_RENAMED) ++ && !is_root ++ && !IS_ROOT(h_dentry) ++ && unhashed != d_unhashed(h_dentry))) ++ goto err; ++ } ++ if (unlikely(mode != h_mode ++ || h_cached_inode != h_inode)) ++ goto err; ++ continue; ++ ++err: ++ err = -EINVAL; ++ break; ++ } ++ ++ AuTraceErr(err); ++ return err; ++} ++ ++/* todo: consolidate with do_refresh() and au_reval_for_attr() */ ++static int simple_reval_dpath(struct dentry *dentry, unsigned int sigen) ++{ ++ int err; ++ struct dentry *parent; ++ ++ if (!au_digen_test(dentry, sigen)) ++ return 0; ++ ++ parent = dget_parent(dentry); ++ di_read_lock_parent(parent, AuLock_IR); ++ AuDebugOn(au_digen_test(parent, sigen)); ++ au_dbg_verify_gen(parent, sigen); ++ err = au_refresh_dentry(dentry, parent); ++ di_read_unlock(parent, AuLock_IR); ++ dput(parent); ++ AuTraceErr(err); ++ return err; ++} ++ ++int au_reval_dpath(struct dentry *dentry, unsigned int sigen) ++{ ++ int err; ++ struct dentry *d, *parent; ++ ++ if (!au_ftest_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIR)) ++ return simple_reval_dpath(dentry, sigen); ++ ++ /* slow loop, keep it simple and stupid */ ++ /* cf: au_cpup_dirs() */ ++ err = 0; ++ parent = NULL; ++ while (au_digen_test(dentry, sigen)) { ++ d = dentry; ++ while (1) { ++ dput(parent); ++ parent = dget_parent(d); ++ if (!au_digen_test(parent, sigen)) ++ break; ++ d = parent; ++ } ++ ++ if (d != dentry) ++ di_write_lock_child2(d); ++ ++ /* someone might update our dentry while we were sleeping */ ++ if (au_digen_test(d, sigen)) { ++ /* ++ * todo: consolidate with simple_reval_dpath(), ++ * do_refresh() and au_reval_for_attr(). ++ */ ++ di_read_lock_parent(parent, AuLock_IR); ++ err = au_refresh_dentry(d, parent); ++ di_read_unlock(parent, AuLock_IR); ++ } ++ ++ if (d != dentry) ++ di_write_unlock(d); ++ dput(parent); ++ if (unlikely(err)) ++ break; ++ } ++ ++ return err; ++} ++ ++/* ++ * if valid returns 1, otherwise 0. ++ */ ++static int aufs_d_revalidate(struct dentry *dentry, unsigned int flags) ++{ ++ int valid, err; ++ unsigned int sigen; ++ unsigned char do_udba, dirren; ++ struct super_block *sb; ++ struct inode *inode; ++ ++ /* todo: support rcu-walk? */ ++ if (flags & LOOKUP_RCU) ++ return -ECHILD; ++ ++ valid = 0; ++ if (unlikely(!au_di(dentry))) ++ goto out; ++ ++ valid = 1; ++ sb = dentry->d_sb; ++ /* ++ * todo: very ugly ++ * i_mutex of parent dir may be held, ++ * but we should not return 'invalid' due to busy. ++ */ ++ err = aufs_read_lock(dentry, AuLock_FLUSH | AuLock_DW | AuLock_NOPLM); ++ if (unlikely(err)) { ++ valid = err; ++ AuTraceErr(err); ++ goto out; ++ } ++ inode = NULL; ++ if (d_really_is_positive(dentry)) ++ inode = d_inode(dentry); ++ if (unlikely(inode && au_is_bad_inode(inode))) { ++ err = -EINVAL; ++ AuTraceErr(err); ++ goto out_dgrade; ++ } ++ if (unlikely(au_dbrange_test(dentry))) { ++ err = -EINVAL; ++ AuTraceErr(err); ++ goto out_dgrade; ++ } ++ ++ sigen = au_sigen(sb); ++ if (au_digen_test(dentry, sigen)) { ++ AuDebugOn(IS_ROOT(dentry)); ++ err = au_reval_dpath(dentry, sigen); ++ if (unlikely(err)) { ++ AuTraceErr(err); ++ goto out_dgrade; ++ } ++ } ++ di_downgrade_lock(dentry, AuLock_IR); ++ ++ err = -EINVAL; ++ if (!(flags & (LOOKUP_OPEN | LOOKUP_EMPTY)) ++ && inode ++ && !(inode->i_state && I_LINKABLE) ++ && (IS_DEADDIR(inode) || !inode->i_nlink)) { ++ AuTraceErr(err); ++ goto out_inval; ++ } ++ ++ do_udba = !au_opt_test(au_mntflags(sb), UDBA_NONE); ++ if (do_udba && inode) { ++ aufs_bindex_t btop = au_ibtop(inode); ++ struct inode *h_inode; ++ ++ if (btop >= 0) { ++ h_inode = au_h_iptr(inode, btop); ++ if (h_inode && au_test_higen(inode, h_inode)) { ++ AuTraceErr(err); ++ goto out_inval; ++ } ++ } ++ } ++ ++ dirren = !!au_opt_test(au_mntflags(sb), DIRREN); ++ err = h_d_revalidate(dentry, inode, flags, do_udba, dirren); ++ if (unlikely(!err && do_udba && au_dbtop(dentry) < 0)) { ++ err = -EIO; ++ AuDbg("both of real entry and whiteout found, %p, err %d\n", ++ dentry, err); ++ } ++ goto out_inval; ++ ++out_dgrade: ++ di_downgrade_lock(dentry, AuLock_IR); ++out_inval: ++ aufs_read_unlock(dentry, AuLock_IR); ++ AuTraceErr(err); ++ valid = !err; ++out: ++ if (!valid) { ++ AuDbg("%pd invalid, %d\n", dentry, valid); ++ d_drop(dentry); ++ } ++ return valid; ++} ++ ++static void aufs_d_release(struct dentry *dentry) ++{ ++ if (au_di(dentry)) { ++ au_di_fin(dentry); ++ au_hn_di_reinit(dentry); ++ } ++} ++ ++const struct dentry_operations aufs_dop = { ++ .d_revalidate = aufs_d_revalidate, ++ .d_weak_revalidate = aufs_d_revalidate, ++ .d_release = aufs_d_release ++}; ++ ++/* aufs_dop without d_revalidate */ ++const struct dentry_operations aufs_dop_noreval = { ++ .d_release = aufs_d_release ++}; +diff -Nurp linux-5.4/fs/aufs/dentry.h linux-5.4-aufs/fs/aufs/dentry.h +--- linux-5.4/fs/aufs/dentry.h 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/dentry.h 2019-11-28 01:25:59.063925618 +0200 +@@ -0,0 +1,255 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * lookup and dentry operations ++ */ ++ ++#ifndef __AUFS_DENTRY_H__ ++#define __AUFS_DENTRY_H__ ++ ++#ifdef __KERNEL__ ++ ++#include ++#include "dirren.h" ++#include "rwsem.h" ++ ++struct au_hdentry { ++ struct dentry *hd_dentry; ++ aufs_bindex_t hd_id; ++}; ++ ++struct au_dinfo { ++ atomic_t di_generation; ++ ++ struct au_rwsem di_rwsem; ++ aufs_bindex_t di_btop, di_bbot, di_bwh, di_bdiropq; ++ unsigned char di_tmpfile; /* to allow the different name */ ++ struct au_hdentry *di_hdentry; ++ struct rcu_head rcu; ++} ____cacheline_aligned_in_smp; ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* flags for au_lkup_dentry() */ ++#define AuLkup_ALLOW_NEG 1 ++#define AuLkup_IGNORE_PERM (1 << 1) ++#define AuLkup_DIRREN (1 << 2) ++#define au_ftest_lkup(flags, name) ((flags) & AuLkup_##name) ++#define au_fset_lkup(flags, name) \ ++ do { (flags) |= AuLkup_##name; } while (0) ++#define au_fclr_lkup(flags, name) \ ++ do { (flags) &= ~AuLkup_##name; } while (0) ++ ++#ifndef CONFIG_AUFS_DIRREN ++#undef AuLkup_DIRREN ++#define AuLkup_DIRREN 0 ++#endif ++ ++struct au_do_lookup_args { ++ unsigned int flags; ++ mode_t type; ++ struct qstr whname, *name; ++ struct au_dr_lookup dirren; ++}; ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* dentry.c */ ++extern const struct dentry_operations aufs_dop, aufs_dop_noreval; ++struct au_branch; ++struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent); ++int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir, ++ struct dentry *h_parent, struct au_branch *br); ++ ++int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t btop, ++ unsigned int flags); ++int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex, int wh); ++int au_refresh_dentry(struct dentry *dentry, struct dentry *parent); ++int au_reval_dpath(struct dentry *dentry, unsigned int sigen); ++void au_refresh_dop(struct dentry *dentry, int force_reval); ++ ++/* dinfo.c */ ++void au_di_init_once(void *_di); ++struct au_dinfo *au_di_alloc(struct super_block *sb, unsigned int lsc); ++void au_di_free(struct au_dinfo *dinfo); ++void au_di_swap(struct au_dinfo *a, struct au_dinfo *b); ++void au_di_cp(struct au_dinfo *dst, struct au_dinfo *src); ++int au_di_init(struct dentry *dentry); ++void au_di_fin(struct dentry *dentry); ++int au_di_realloc(struct au_dinfo *dinfo, int nbr, int may_shrink); ++ ++void di_read_lock(struct dentry *d, int flags, unsigned int lsc); ++void di_read_unlock(struct dentry *d, int flags); ++void di_downgrade_lock(struct dentry *d, int flags); ++void di_write_lock(struct dentry *d, unsigned int lsc); ++void di_write_unlock(struct dentry *d); ++void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir); ++void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir); ++void di_write_unlock2(struct dentry *d1, struct dentry *d2); ++ ++struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex); ++struct dentry *au_h_d_alias(struct dentry *dentry, aufs_bindex_t bindex); ++aufs_bindex_t au_dbtail(struct dentry *dentry); ++aufs_bindex_t au_dbtaildir(struct dentry *dentry); ++ ++void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex, ++ struct dentry *h_dentry); ++int au_digen_test(struct dentry *dentry, unsigned int sigen); ++int au_dbrange_test(struct dentry *dentry); ++void au_update_digen(struct dentry *dentry); ++void au_update_dbrange(struct dentry *dentry, int do_put_zero); ++void au_update_dbtop(struct dentry *dentry); ++void au_update_dbbot(struct dentry *dentry); ++int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry); ++ ++/* ---------------------------------------------------------------------- */ ++ ++static inline struct au_dinfo *au_di(struct dentry *dentry) ++{ ++ return dentry->d_fsdata; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* lock subclass for dinfo */ ++enum { ++ AuLsc_DI_CHILD, /* child first */ ++ AuLsc_DI_CHILD2, /* rename(2), link(2), and cpup at hnotify */ ++ AuLsc_DI_CHILD3, /* copyup dirs */ ++ AuLsc_DI_PARENT, ++ AuLsc_DI_PARENT2, ++ AuLsc_DI_PARENT3, ++ AuLsc_DI_TMP /* temp for replacing dinfo */ ++}; ++ ++/* ++ * di_read_lock_child, di_write_lock_child, ++ * di_read_lock_child2, di_write_lock_child2, ++ * di_read_lock_child3, di_write_lock_child3, ++ * di_read_lock_parent, di_write_lock_parent, ++ * di_read_lock_parent2, di_write_lock_parent2, ++ * di_read_lock_parent3, di_write_lock_parent3, ++ */ ++#define AuReadLockFunc(name, lsc) \ ++static inline void di_read_lock_##name(struct dentry *d, int flags) \ ++{ di_read_lock(d, flags, AuLsc_DI_##lsc); } ++ ++#define AuWriteLockFunc(name, lsc) \ ++static inline void di_write_lock_##name(struct dentry *d) \ ++{ di_write_lock(d, AuLsc_DI_##lsc); } ++ ++#define AuRWLockFuncs(name, lsc) \ ++ AuReadLockFunc(name, lsc) \ ++ AuWriteLockFunc(name, lsc) ++ ++AuRWLockFuncs(child, CHILD); ++AuRWLockFuncs(child2, CHILD2); ++AuRWLockFuncs(child3, CHILD3); ++AuRWLockFuncs(parent, PARENT); ++AuRWLockFuncs(parent2, PARENT2); ++AuRWLockFuncs(parent3, PARENT3); ++ ++#undef AuReadLockFunc ++#undef AuWriteLockFunc ++#undef AuRWLockFuncs ++ ++#define DiMustNoWaiters(d) AuRwMustNoWaiters(&au_di(d)->di_rwsem) ++#define DiMustAnyLock(d) AuRwMustAnyLock(&au_di(d)->di_rwsem) ++#define DiMustWriteLock(d) AuRwMustWriteLock(&au_di(d)->di_rwsem) ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* todo: memory barrier? */ ++static inline unsigned int au_digen(struct dentry *d) ++{ ++ return atomic_read(&au_di(d)->di_generation); ++} ++ ++static inline void au_h_dentry_init(struct au_hdentry *hdentry) ++{ ++ hdentry->hd_dentry = NULL; ++} ++ ++static inline struct au_hdentry *au_hdentry(struct au_dinfo *di, ++ aufs_bindex_t bindex) ++{ ++ return di->di_hdentry + bindex; ++} ++ ++static inline void au_hdput(struct au_hdentry *hd) ++{ ++ if (hd) ++ dput(hd->hd_dentry); ++} ++ ++static inline aufs_bindex_t au_dbtop(struct dentry *dentry) ++{ ++ DiMustAnyLock(dentry); ++ return au_di(dentry)->di_btop; ++} ++ ++static inline aufs_bindex_t au_dbbot(struct dentry *dentry) ++{ ++ DiMustAnyLock(dentry); ++ return au_di(dentry)->di_bbot; ++} ++ ++static inline aufs_bindex_t au_dbwh(struct dentry *dentry) ++{ ++ DiMustAnyLock(dentry); ++ return au_di(dentry)->di_bwh; ++} ++ ++static inline aufs_bindex_t au_dbdiropq(struct dentry *dentry) ++{ ++ DiMustAnyLock(dentry); ++ return au_di(dentry)->di_bdiropq; ++} ++ ++/* todo: hard/soft set? */ ++static inline void au_set_dbtop(struct dentry *dentry, aufs_bindex_t bindex) ++{ ++ DiMustWriteLock(dentry); ++ au_di(dentry)->di_btop = bindex; ++} ++ ++static inline void au_set_dbbot(struct dentry *dentry, aufs_bindex_t bindex) ++{ ++ DiMustWriteLock(dentry); ++ au_di(dentry)->di_bbot = bindex; ++} ++ ++static inline void au_set_dbwh(struct dentry *dentry, aufs_bindex_t bindex) ++{ ++ DiMustWriteLock(dentry); ++ /* dbwh can be outside of btop - bbot range */ ++ au_di(dentry)->di_bwh = bindex; ++} ++ ++static inline void au_set_dbdiropq(struct dentry *dentry, aufs_bindex_t bindex) ++{ ++ DiMustWriteLock(dentry); ++ au_di(dentry)->di_bdiropq = bindex; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++#ifdef CONFIG_AUFS_HNOTIFY ++static inline void au_digen_dec(struct dentry *d) ++{ ++ atomic_dec(&au_di(d)->di_generation); ++} ++ ++static inline void au_hn_di_reinit(struct dentry *dentry) ++{ ++ dentry->d_fsdata = NULL; ++} ++#else ++AuStubVoid(au_hn_di_reinit, struct dentry *dentry __maybe_unused) ++#endif /* CONFIG_AUFS_HNOTIFY */ ++ ++#endif /* __KERNEL__ */ ++#endif /* __AUFS_DENTRY_H__ */ +diff -Nurp linux-5.4/fs/aufs/dinfo.c linux-5.4-aufs/fs/aufs/dinfo.c +--- linux-5.4/fs/aufs/dinfo.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/dinfo.c 2019-11-28 01:25:59.063925618 +0200 +@@ -0,0 +1,541 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * dentry private data ++ */ ++ ++#include "aufs.h" ++ ++void au_di_init_once(void *_dinfo) ++{ ++ struct au_dinfo *dinfo = _dinfo; ++ ++ au_rw_init(&dinfo->di_rwsem); ++} ++ ++struct au_dinfo *au_di_alloc(struct super_block *sb, unsigned int lsc) ++{ ++ struct au_dinfo *dinfo; ++ int nbr, i; ++ ++ dinfo = au_cache_alloc_dinfo(); ++ if (unlikely(!dinfo)) ++ goto out; ++ ++ nbr = au_sbbot(sb) + 1; ++ if (nbr <= 0) ++ nbr = 1; ++ dinfo->di_hdentry = kcalloc(nbr, sizeof(*dinfo->di_hdentry), GFP_NOFS); ++ if (dinfo->di_hdentry) { ++ au_rw_write_lock_nested(&dinfo->di_rwsem, lsc); ++ dinfo->di_btop = -1; ++ dinfo->di_bbot = -1; ++ dinfo->di_bwh = -1; ++ dinfo->di_bdiropq = -1; ++ dinfo->di_tmpfile = 0; ++ for (i = 0; i < nbr; i++) ++ dinfo->di_hdentry[i].hd_id = -1; ++ goto out; ++ } ++ ++ au_cache_free_dinfo(dinfo); ++ dinfo = NULL; ++ ++out: ++ return dinfo; ++} ++ ++void au_di_free(struct au_dinfo *dinfo) ++{ ++ struct au_hdentry *p; ++ aufs_bindex_t bbot, bindex; ++ ++ /* dentry may not be revalidated */ ++ bindex = dinfo->di_btop; ++ if (bindex >= 0) { ++ bbot = dinfo->di_bbot; ++ p = au_hdentry(dinfo, bindex); ++ while (bindex++ <= bbot) ++ au_hdput(p++); ++ } ++ au_kfree_try_rcu(dinfo->di_hdentry); ++ au_cache_free_dinfo(dinfo); ++} ++ ++void au_di_swap(struct au_dinfo *a, struct au_dinfo *b) ++{ ++ struct au_hdentry *p; ++ aufs_bindex_t bi; ++ ++ AuRwMustWriteLock(&a->di_rwsem); ++ AuRwMustWriteLock(&b->di_rwsem); ++ ++#define DiSwap(v, name) \ ++ do { \ ++ v = a->di_##name; \ ++ a->di_##name = b->di_##name; \ ++ b->di_##name = v; \ ++ } while (0) ++ ++ DiSwap(p, hdentry); ++ DiSwap(bi, btop); ++ DiSwap(bi, bbot); ++ DiSwap(bi, bwh); ++ DiSwap(bi, bdiropq); ++ /* smp_mb(); */ ++ ++#undef DiSwap ++} ++ ++void au_di_cp(struct au_dinfo *dst, struct au_dinfo *src) ++{ ++ AuRwMustWriteLock(&dst->di_rwsem); ++ AuRwMustWriteLock(&src->di_rwsem); ++ ++ dst->di_btop = src->di_btop; ++ dst->di_bbot = src->di_bbot; ++ dst->di_bwh = src->di_bwh; ++ dst->di_bdiropq = src->di_bdiropq; ++ /* smp_mb(); */ ++} ++ ++int au_di_init(struct dentry *dentry) ++{ ++ int err; ++ struct super_block *sb; ++ struct au_dinfo *dinfo; ++ ++ err = 0; ++ sb = dentry->d_sb; ++ dinfo = au_di_alloc(sb, AuLsc_DI_CHILD); ++ if (dinfo) { ++ atomic_set(&dinfo->di_generation, au_sigen(sb)); ++ /* smp_mb(); */ /* atomic_set */ ++ dentry->d_fsdata = dinfo; ++ } else ++ err = -ENOMEM; ++ ++ return err; ++} ++ ++void au_di_fin(struct dentry *dentry) ++{ ++ struct au_dinfo *dinfo; ++ ++ dinfo = au_di(dentry); ++ AuRwDestroy(&dinfo->di_rwsem); ++ au_di_free(dinfo); ++} ++ ++int au_di_realloc(struct au_dinfo *dinfo, int nbr, int may_shrink) ++{ ++ int err, sz; ++ struct au_hdentry *hdp; ++ ++ AuRwMustWriteLock(&dinfo->di_rwsem); ++ ++ err = -ENOMEM; ++ sz = sizeof(*hdp) * (dinfo->di_bbot + 1); ++ if (!sz) ++ sz = sizeof(*hdp); ++ hdp = au_kzrealloc(dinfo->di_hdentry, sz, sizeof(*hdp) * nbr, GFP_NOFS, ++ may_shrink); ++ if (hdp) { ++ dinfo->di_hdentry = hdp; ++ err = 0; ++ } ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static void do_ii_write_lock(struct inode *inode, unsigned int lsc) ++{ ++ switch (lsc) { ++ case AuLsc_DI_CHILD: ++ ii_write_lock_child(inode); ++ break; ++ case AuLsc_DI_CHILD2: ++ ii_write_lock_child2(inode); ++ break; ++ case AuLsc_DI_CHILD3: ++ ii_write_lock_child3(inode); ++ break; ++ case AuLsc_DI_PARENT: ++ ii_write_lock_parent(inode); ++ break; ++ case AuLsc_DI_PARENT2: ++ ii_write_lock_parent2(inode); ++ break; ++ case AuLsc_DI_PARENT3: ++ ii_write_lock_parent3(inode); ++ break; ++ default: ++ BUG(); ++ } ++} ++ ++static void do_ii_read_lock(struct inode *inode, unsigned int lsc) ++{ ++ switch (lsc) { ++ case AuLsc_DI_CHILD: ++ ii_read_lock_child(inode); ++ break; ++ case AuLsc_DI_CHILD2: ++ ii_read_lock_child2(inode); ++ break; ++ case AuLsc_DI_CHILD3: ++ ii_read_lock_child3(inode); ++ break; ++ case AuLsc_DI_PARENT: ++ ii_read_lock_parent(inode); ++ break; ++ case AuLsc_DI_PARENT2: ++ ii_read_lock_parent2(inode); ++ break; ++ case AuLsc_DI_PARENT3: ++ ii_read_lock_parent3(inode); ++ break; ++ default: ++ BUG(); ++ } ++} ++ ++void di_read_lock(struct dentry *d, int flags, unsigned int lsc) ++{ ++ struct inode *inode; ++ ++ au_rw_read_lock_nested(&au_di(d)->di_rwsem, lsc); ++ if (d_really_is_positive(d)) { ++ inode = d_inode(d); ++ if (au_ftest_lock(flags, IW)) ++ do_ii_write_lock(inode, lsc); ++ else if (au_ftest_lock(flags, IR)) ++ do_ii_read_lock(inode, lsc); ++ } ++} ++ ++void di_read_unlock(struct dentry *d, int flags) ++{ ++ struct inode *inode; ++ ++ if (d_really_is_positive(d)) { ++ inode = d_inode(d); ++ if (au_ftest_lock(flags, IW)) { ++ au_dbg_verify_dinode(d); ++ ii_write_unlock(inode); ++ } else if (au_ftest_lock(flags, IR)) { ++ au_dbg_verify_dinode(d); ++ ii_read_unlock(inode); ++ } ++ } ++ au_rw_read_unlock(&au_di(d)->di_rwsem); ++} ++ ++void di_downgrade_lock(struct dentry *d, int flags) ++{ ++ if (d_really_is_positive(d) && au_ftest_lock(flags, IR)) ++ ii_downgrade_lock(d_inode(d)); ++ au_rw_dgrade_lock(&au_di(d)->di_rwsem); ++} ++ ++void di_write_lock(struct dentry *d, unsigned int lsc) ++{ ++ au_rw_write_lock_nested(&au_di(d)->di_rwsem, lsc); ++ if (d_really_is_positive(d)) ++ do_ii_write_lock(d_inode(d), lsc); ++} ++ ++void di_write_unlock(struct dentry *d) ++{ ++ au_dbg_verify_dinode(d); ++ if (d_really_is_positive(d)) ++ ii_write_unlock(d_inode(d)); ++ au_rw_write_unlock(&au_di(d)->di_rwsem); ++} ++ ++void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir) ++{ ++ AuDebugOn(d1 == d2 ++ || d_inode(d1) == d_inode(d2) ++ || d1->d_sb != d2->d_sb); ++ ++ if ((isdir && au_test_subdir(d1, d2)) ++ || d1 < d2) { ++ di_write_lock_child(d1); ++ di_write_lock_child2(d2); ++ } else { ++ di_write_lock_child(d2); ++ di_write_lock_child2(d1); ++ } ++} ++ ++void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir) ++{ ++ AuDebugOn(d1 == d2 ++ || d_inode(d1) == d_inode(d2) ++ || d1->d_sb != d2->d_sb); ++ ++ if ((isdir && au_test_subdir(d1, d2)) ++ || d1 < d2) { ++ di_write_lock_parent(d1); ++ di_write_lock_parent2(d2); ++ } else { ++ di_write_lock_parent(d2); ++ di_write_lock_parent2(d1); ++ } ++} ++ ++void di_write_unlock2(struct dentry *d1, struct dentry *d2) ++{ ++ di_write_unlock(d1); ++ if (d_inode(d1) == d_inode(d2)) ++ au_rw_write_unlock(&au_di(d2)->di_rwsem); ++ else ++ di_write_unlock(d2); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex) ++{ ++ struct dentry *d; ++ ++ DiMustAnyLock(dentry); ++ ++ if (au_dbtop(dentry) < 0 || bindex < au_dbtop(dentry)) ++ return NULL; ++ AuDebugOn(bindex < 0); ++ d = au_hdentry(au_di(dentry), bindex)->hd_dentry; ++ AuDebugOn(d && au_dcount(d) <= 0); ++ return d; ++} ++ ++/* ++ * extended version of au_h_dptr(). ++ * returns a hashed and positive (or linkable) h_dentry in bindex, NULL, or ++ * error. ++ */ ++struct dentry *au_h_d_alias(struct dentry *dentry, aufs_bindex_t bindex) ++{ ++ struct dentry *h_dentry; ++ struct inode *inode, *h_inode; ++ ++ AuDebugOn(d_really_is_negative(dentry)); ++ ++ h_dentry = NULL; ++ if (au_dbtop(dentry) <= bindex ++ && bindex <= au_dbbot(dentry)) ++ h_dentry = au_h_dptr(dentry, bindex); ++ if (h_dentry && !au_d_linkable(h_dentry)) { ++ dget(h_dentry); ++ goto out; /* success */ ++ } ++ ++ inode = d_inode(dentry); ++ AuDebugOn(bindex < au_ibtop(inode)); ++ AuDebugOn(au_ibbot(inode) < bindex); ++ h_inode = au_h_iptr(inode, bindex); ++ h_dentry = d_find_alias(h_inode); ++ if (h_dentry) { ++ if (!IS_ERR(h_dentry)) { ++ if (!au_d_linkable(h_dentry)) ++ goto out; /* success */ ++ dput(h_dentry); ++ } else ++ goto out; ++ } ++ ++ if (au_opt_test(au_mntflags(dentry->d_sb), PLINK)) { ++ h_dentry = au_plink_lkup(inode, bindex); ++ AuDebugOn(!h_dentry); ++ if (!IS_ERR(h_dentry)) { ++ if (!au_d_hashed_positive(h_dentry)) ++ goto out; /* success */ ++ dput(h_dentry); ++ h_dentry = NULL; ++ } ++ } ++ ++out: ++ AuDbgDentry(h_dentry); ++ return h_dentry; ++} ++ ++aufs_bindex_t au_dbtail(struct dentry *dentry) ++{ ++ aufs_bindex_t bbot, bwh; ++ ++ bbot = au_dbbot(dentry); ++ if (0 <= bbot) { ++ bwh = au_dbwh(dentry); ++ if (!bwh) ++ return bwh; ++ if (0 < bwh && bwh < bbot) ++ return bwh - 1; ++ } ++ return bbot; ++} ++ ++aufs_bindex_t au_dbtaildir(struct dentry *dentry) ++{ ++ aufs_bindex_t bbot, bopq; ++ ++ bbot = au_dbtail(dentry); ++ if (0 <= bbot) { ++ bopq = au_dbdiropq(dentry); ++ if (0 <= bopq && bopq < bbot) ++ bbot = bopq; ++ } ++ return bbot; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex, ++ struct dentry *h_dentry) ++{ ++ struct au_dinfo *dinfo; ++ struct au_hdentry *hd; ++ struct au_branch *br; ++ ++ DiMustWriteLock(dentry); ++ ++ dinfo = au_di(dentry); ++ hd = au_hdentry(dinfo, bindex); ++ au_hdput(hd); ++ hd->hd_dentry = h_dentry; ++ if (h_dentry) { ++ br = au_sbr(dentry->d_sb, bindex); ++ hd->hd_id = br->br_id; ++ } ++} ++ ++int au_dbrange_test(struct dentry *dentry) ++{ ++ int err; ++ aufs_bindex_t btop, bbot; ++ ++ err = 0; ++ btop = au_dbtop(dentry); ++ bbot = au_dbbot(dentry); ++ if (btop >= 0) ++ AuDebugOn(bbot < 0 && btop > bbot); ++ else { ++ err = -EIO; ++ AuDebugOn(bbot >= 0); ++ } ++ ++ return err; ++} ++ ++int au_digen_test(struct dentry *dentry, unsigned int sigen) ++{ ++ int err; ++ ++ err = 0; ++ if (unlikely(au_digen(dentry) != sigen ++ || au_iigen_test(d_inode(dentry), sigen))) ++ err = -EIO; ++ ++ return err; ++} ++ ++void au_update_digen(struct dentry *dentry) ++{ ++ atomic_set(&au_di(dentry)->di_generation, au_sigen(dentry->d_sb)); ++ /* smp_mb(); */ /* atomic_set */ ++} ++ ++void au_update_dbrange(struct dentry *dentry, int do_put_zero) ++{ ++ struct au_dinfo *dinfo; ++ struct dentry *h_d; ++ struct au_hdentry *hdp; ++ aufs_bindex_t bindex, bbot; ++ ++ DiMustWriteLock(dentry); ++ ++ dinfo = au_di(dentry); ++ if (!dinfo || dinfo->di_btop < 0) ++ return; ++ ++ if (do_put_zero) { ++ bbot = dinfo->di_bbot; ++ bindex = dinfo->di_btop; ++ hdp = au_hdentry(dinfo, bindex); ++ for (; bindex <= bbot; bindex++, hdp++) { ++ h_d = hdp->hd_dentry; ++ if (h_d && d_is_negative(h_d)) ++ au_set_h_dptr(dentry, bindex, NULL); ++ } ++ } ++ ++ dinfo->di_btop = 0; ++ hdp = au_hdentry(dinfo, dinfo->di_btop); ++ for (; dinfo->di_btop <= dinfo->di_bbot; dinfo->di_btop++, hdp++) ++ if (hdp->hd_dentry) ++ break; ++ if (dinfo->di_btop > dinfo->di_bbot) { ++ dinfo->di_btop = -1; ++ dinfo->di_bbot = -1; ++ return; ++ } ++ ++ hdp = au_hdentry(dinfo, dinfo->di_bbot); ++ for (; dinfo->di_bbot >= 0; dinfo->di_bbot--, hdp--) ++ if (hdp->hd_dentry) ++ break; ++ AuDebugOn(dinfo->di_btop > dinfo->di_bbot || dinfo->di_bbot < 0); ++} ++ ++void au_update_dbtop(struct dentry *dentry) ++{ ++ aufs_bindex_t bindex, bbot; ++ struct dentry *h_dentry; ++ ++ bbot = au_dbbot(dentry); ++ for (bindex = au_dbtop(dentry); bindex <= bbot; bindex++) { ++ h_dentry = au_h_dptr(dentry, bindex); ++ if (!h_dentry) ++ continue; ++ if (d_is_positive(h_dentry)) { ++ au_set_dbtop(dentry, bindex); ++ return; ++ } ++ au_set_h_dptr(dentry, bindex, NULL); ++ } ++} ++ ++void au_update_dbbot(struct dentry *dentry) ++{ ++ aufs_bindex_t bindex, btop; ++ struct dentry *h_dentry; ++ ++ btop = au_dbtop(dentry); ++ for (bindex = au_dbbot(dentry); bindex >= btop; bindex--) { ++ h_dentry = au_h_dptr(dentry, bindex); ++ if (!h_dentry) ++ continue; ++ if (d_is_positive(h_dentry)) { ++ au_set_dbbot(dentry, bindex); ++ return; ++ } ++ au_set_h_dptr(dentry, bindex, NULL); ++ } ++} ++ ++int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry) ++{ ++ aufs_bindex_t bindex, bbot; ++ ++ bbot = au_dbbot(dentry); ++ for (bindex = au_dbtop(dentry); bindex <= bbot; bindex++) ++ if (au_h_dptr(dentry, bindex) == h_dentry) ++ return bindex; ++ return -1; ++} +diff -Nurp linux-5.4/fs/aufs/dir.c linux-5.4-aufs/fs/aufs/dir.c +--- linux-5.4/fs/aufs/dir.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/dir.c 2019-11-28 01:25:59.064925618 +0200 +@@ -0,0 +1,750 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * directory operations ++ */ ++ ++#include ++#include ++#include "aufs.h" ++ ++void au_add_nlink(struct inode *dir, struct inode *h_dir) ++{ ++ unsigned int nlink; ++ ++ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode)); ++ ++ nlink = dir->i_nlink; ++ nlink += h_dir->i_nlink - 2; ++ if (h_dir->i_nlink < 2) ++ nlink += 2; ++ smp_mb(); /* for i_nlink */ ++ /* 0 can happen in revaliding */ ++ set_nlink(dir, nlink); ++} ++ ++void au_sub_nlink(struct inode *dir, struct inode *h_dir) ++{ ++ unsigned int nlink; ++ ++ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode)); ++ ++ nlink = dir->i_nlink; ++ nlink -= h_dir->i_nlink - 2; ++ if (h_dir->i_nlink < 2) ++ nlink -= 2; ++ smp_mb(); /* for i_nlink */ ++ /* nlink == 0 means the branch-fs is broken */ ++ set_nlink(dir, nlink); ++} ++ ++loff_t au_dir_size(struct file *file, struct dentry *dentry) ++{ ++ loff_t sz; ++ aufs_bindex_t bindex, bbot; ++ struct file *h_file; ++ struct dentry *h_dentry; ++ ++ sz = 0; ++ if (file) { ++ AuDebugOn(!d_is_dir(file->f_path.dentry)); ++ ++ bbot = au_fbbot_dir(file); ++ for (bindex = au_fbtop(file); ++ bindex <= bbot && sz < KMALLOC_MAX_SIZE; ++ bindex++) { ++ h_file = au_hf_dir(file, bindex); ++ if (h_file && file_inode(h_file)) ++ sz += vfsub_f_size_read(h_file); ++ } ++ } else { ++ AuDebugOn(!dentry); ++ AuDebugOn(!d_is_dir(dentry)); ++ ++ bbot = au_dbtaildir(dentry); ++ for (bindex = au_dbtop(dentry); ++ bindex <= bbot && sz < KMALLOC_MAX_SIZE; ++ bindex++) { ++ h_dentry = au_h_dptr(dentry, bindex); ++ if (h_dentry && d_is_positive(h_dentry)) ++ sz += i_size_read(d_inode(h_dentry)); ++ } ++ } ++ if (sz < KMALLOC_MAX_SIZE) ++ sz = roundup_pow_of_two(sz); ++ if (sz > KMALLOC_MAX_SIZE) ++ sz = KMALLOC_MAX_SIZE; ++ else if (sz < NAME_MAX) { ++ BUILD_BUG_ON(AUFS_RDBLK_DEF < NAME_MAX); ++ sz = AUFS_RDBLK_DEF; ++ } ++ return sz; ++} ++ ++struct au_dir_ts_arg { ++ struct dentry *dentry; ++ aufs_bindex_t brid; ++}; ++ ++static void au_do_dir_ts(void *arg) ++{ ++ struct au_dir_ts_arg *a = arg; ++ struct au_dtime dt; ++ struct path h_path; ++ struct inode *dir, *h_dir; ++ struct super_block *sb; ++ struct au_branch *br; ++ struct au_hinode *hdir; ++ int err; ++ aufs_bindex_t btop, bindex; ++ ++ sb = a->dentry->d_sb; ++ if (d_really_is_negative(a->dentry)) ++ goto out; ++ /* no dir->i_mutex lock */ ++ aufs_read_lock(a->dentry, AuLock_DW); /* noflush */ ++ ++ dir = d_inode(a->dentry); ++ btop = au_ibtop(dir); ++ bindex = au_br_index(sb, a->brid); ++ if (bindex < btop) ++ goto out_unlock; ++ ++ br = au_sbr(sb, bindex); ++ h_path.dentry = au_h_dptr(a->dentry, bindex); ++ if (!h_path.dentry) ++ goto out_unlock; ++ h_path.mnt = au_br_mnt(br); ++ au_dtime_store(&dt, a->dentry, &h_path); ++ ++ br = au_sbr(sb, btop); ++ if (!au_br_writable(br->br_perm)) ++ goto out_unlock; ++ h_path.dentry = au_h_dptr(a->dentry, btop); ++ h_path.mnt = au_br_mnt(br); ++ err = vfsub_mnt_want_write(h_path.mnt); ++ if (err) ++ goto out_unlock; ++ hdir = au_hi(dir, btop); ++ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT); ++ h_dir = au_h_iptr(dir, btop); ++ if (h_dir->i_nlink ++ && timespec64_compare(&h_dir->i_mtime, &dt.dt_mtime) < 0) { ++ dt.dt_h_path = h_path; ++ au_dtime_revert(&dt); ++ } ++ au_hn_inode_unlock(hdir); ++ vfsub_mnt_drop_write(h_path.mnt); ++ au_cpup_attr_timesizes(dir); ++ ++out_unlock: ++ aufs_read_unlock(a->dentry, AuLock_DW); ++out: ++ dput(a->dentry); ++ au_nwt_done(&au_sbi(sb)->si_nowait); ++ au_kfree_try_rcu(arg); ++} ++ ++void au_dir_ts(struct inode *dir, aufs_bindex_t bindex) ++{ ++ int perm, wkq_err; ++ aufs_bindex_t btop; ++ struct au_dir_ts_arg *arg; ++ struct dentry *dentry; ++ struct super_block *sb; ++ ++ IMustLock(dir); ++ ++ dentry = d_find_any_alias(dir); ++ AuDebugOn(!dentry); ++ sb = dentry->d_sb; ++ btop = au_ibtop(dir); ++ if (btop == bindex) { ++ au_cpup_attr_timesizes(dir); ++ goto out; ++ } ++ ++ perm = au_sbr_perm(sb, btop); ++ if (!au_br_writable(perm)) ++ goto out; ++ ++ arg = kmalloc(sizeof(*arg), GFP_NOFS); ++ if (!arg) ++ goto out; ++ ++ arg->dentry = dget(dentry); /* will be dput-ted by au_do_dir_ts() */ ++ arg->brid = au_sbr_id(sb, bindex); ++ wkq_err = au_wkq_nowait(au_do_dir_ts, arg, sb, /*flags*/0); ++ if (unlikely(wkq_err)) { ++ pr_err("wkq %d\n", wkq_err); ++ dput(dentry); ++ au_kfree_try_rcu(arg); ++ } ++ ++out: ++ dput(dentry); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int reopen_dir(struct file *file) ++{ ++ int err; ++ unsigned int flags; ++ aufs_bindex_t bindex, btail, btop; ++ struct dentry *dentry, *h_dentry; ++ struct file *h_file; ++ ++ /* open all lower dirs */ ++ dentry = file->f_path.dentry; ++ btop = au_dbtop(dentry); ++ for (bindex = au_fbtop(file); bindex < btop; bindex++) ++ au_set_h_fptr(file, bindex, NULL); ++ au_set_fbtop(file, btop); ++ ++ btail = au_dbtaildir(dentry); ++ for (bindex = au_fbbot_dir(file); btail < bindex; bindex--) ++ au_set_h_fptr(file, bindex, NULL); ++ au_set_fbbot_dir(file, btail); ++ ++ flags = vfsub_file_flags(file); ++ for (bindex = btop; bindex <= btail; bindex++) { ++ h_dentry = au_h_dptr(dentry, bindex); ++ if (!h_dentry) ++ continue; ++ h_file = au_hf_dir(file, bindex); ++ if (h_file) ++ continue; ++ ++ h_file = au_h_open(dentry, bindex, flags, file, /*force_wr*/0); ++ err = PTR_ERR(h_file); ++ if (IS_ERR(h_file)) ++ goto out; /* close all? */ ++ au_set_h_fptr(file, bindex, h_file); ++ } ++ au_update_figen(file); ++ /* todo: necessary? */ ++ /* file->f_ra = h_file->f_ra; */ ++ err = 0; ++ ++out: ++ return err; ++} ++ ++static int do_open_dir(struct file *file, int flags, struct file *h_file) ++{ ++ int err; ++ aufs_bindex_t bindex, btail; ++ struct dentry *dentry, *h_dentry; ++ struct vfsmount *mnt; ++ ++ FiMustWriteLock(file); ++ AuDebugOn(h_file); ++ ++ err = 0; ++ mnt = file->f_path.mnt; ++ dentry = file->f_path.dentry; ++ file->f_version = inode_query_iversion(d_inode(dentry)); ++ bindex = au_dbtop(dentry); ++ au_set_fbtop(file, bindex); ++ btail = au_dbtaildir(dentry); ++ au_set_fbbot_dir(file, btail); ++ for (; !err && bindex <= btail; bindex++) { ++ h_dentry = au_h_dptr(dentry, bindex); ++ if (!h_dentry) ++ continue; ++ ++ err = vfsub_test_mntns(mnt, h_dentry->d_sb); ++ if (unlikely(err)) ++ break; ++ h_file = au_h_open(dentry, bindex, flags, file, /*force_wr*/0); ++ if (IS_ERR(h_file)) { ++ err = PTR_ERR(h_file); ++ break; ++ } ++ au_set_h_fptr(file, bindex, h_file); ++ } ++ au_update_figen(file); ++ /* todo: necessary? */ ++ /* file->f_ra = h_file->f_ra; */ ++ if (!err) ++ return 0; /* success */ ++ ++ /* close all */ ++ for (bindex = au_fbtop(file); bindex <= btail; bindex++) ++ au_set_h_fptr(file, bindex, NULL); ++ au_set_fbtop(file, -1); ++ au_set_fbbot_dir(file, -1); ++ ++ return err; ++} ++ ++static int aufs_open_dir(struct inode *inode __maybe_unused, ++ struct file *file) ++{ ++ int err; ++ struct super_block *sb; ++ struct au_fidir *fidir; ++ ++ err = -ENOMEM; ++ sb = file->f_path.dentry->d_sb; ++ si_read_lock(sb, AuLock_FLUSH); ++ fidir = au_fidir_alloc(sb); ++ if (fidir) { ++ struct au_do_open_args args = { ++ .open = do_open_dir, ++ .fidir = fidir ++ }; ++ err = au_do_open(file, &args); ++ if (unlikely(err)) ++ au_kfree_rcu(fidir); ++ } ++ si_read_unlock(sb); ++ return err; ++} ++ ++static int aufs_release_dir(struct inode *inode __maybe_unused, ++ struct file *file) ++{ ++ struct au_vdir *vdir_cache; ++ struct au_finfo *finfo; ++ struct au_fidir *fidir; ++ struct au_hfile *hf; ++ aufs_bindex_t bindex, bbot; ++ ++ finfo = au_fi(file); ++ fidir = finfo->fi_hdir; ++ if (fidir) { ++ au_hbl_del(&finfo->fi_hlist, ++ &au_sbi(file->f_path.dentry->d_sb)->si_files); ++ vdir_cache = fidir->fd_vdir_cache; /* lock-free */ ++ if (vdir_cache) ++ au_vdir_free(vdir_cache); ++ ++ bindex = finfo->fi_btop; ++ if (bindex >= 0) { ++ hf = fidir->fd_hfile + bindex; ++ /* ++ * calls fput() instead of filp_close(), ++ * since no dnotify or lock for the lower file. ++ */ ++ bbot = fidir->fd_bbot; ++ for (; bindex <= bbot; bindex++, hf++) ++ if (hf->hf_file) ++ au_hfput(hf, /*execed*/0); ++ } ++ au_kfree_rcu(fidir); ++ finfo->fi_hdir = NULL; ++ } ++ au_finfo_fin(file); ++ return 0; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int au_do_flush_dir(struct file *file, fl_owner_t id) ++{ ++ int err; ++ aufs_bindex_t bindex, bbot; ++ struct file *h_file; ++ ++ err = 0; ++ bbot = au_fbbot_dir(file); ++ for (bindex = au_fbtop(file); !err && bindex <= bbot; bindex++) { ++ h_file = au_hf_dir(file, bindex); ++ if (h_file) ++ err = vfsub_flush(h_file, id); ++ } ++ return err; ++} ++ ++static int aufs_flush_dir(struct file *file, fl_owner_t id) ++{ ++ return au_do_flush(file, id, au_do_flush_dir); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int au_do_fsync_dir_no_file(struct dentry *dentry, int datasync) ++{ ++ int err; ++ aufs_bindex_t bbot, bindex; ++ struct inode *inode; ++ struct super_block *sb; ++ ++ err = 0; ++ sb = dentry->d_sb; ++ inode = d_inode(dentry); ++ IMustLock(inode); ++ bbot = au_dbbot(dentry); ++ for (bindex = au_dbtop(dentry); !err && bindex <= bbot; bindex++) { ++ struct path h_path; ++ ++ if (au_test_ro(sb, bindex, inode)) ++ continue; ++ h_path.dentry = au_h_dptr(dentry, bindex); ++ if (!h_path.dentry) ++ continue; ++ ++ h_path.mnt = au_sbr_mnt(sb, bindex); ++ err = vfsub_fsync(NULL, &h_path, datasync); ++ } ++ ++ return err; ++} ++ ++static int au_do_fsync_dir(struct file *file, int datasync) ++{ ++ int err; ++ aufs_bindex_t bbot, bindex; ++ struct file *h_file; ++ struct super_block *sb; ++ struct inode *inode; ++ ++ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1, /*fi_lsc*/0); ++ if (unlikely(err)) ++ goto out; ++ ++ inode = file_inode(file); ++ sb = inode->i_sb; ++ bbot = au_fbbot_dir(file); ++ for (bindex = au_fbtop(file); !err && bindex <= bbot; bindex++) { ++ h_file = au_hf_dir(file, bindex); ++ if (!h_file || au_test_ro(sb, bindex, inode)) ++ continue; ++ ++ err = vfsub_fsync(h_file, &h_file->f_path, datasync); ++ } ++ ++out: ++ return err; ++} ++ ++/* ++ * @file may be NULL ++ */ ++static int aufs_fsync_dir(struct file *file, loff_t start, loff_t end, ++ int datasync) ++{ ++ int err; ++ struct dentry *dentry; ++ struct inode *inode; ++ struct super_block *sb; ++ ++ err = 0; ++ dentry = file->f_path.dentry; ++ inode = d_inode(dentry); ++ inode_lock(inode); ++ sb = dentry->d_sb; ++ si_noflush_read_lock(sb); ++ if (file) ++ err = au_do_fsync_dir(file, datasync); ++ else { ++ di_write_lock_child(dentry); ++ err = au_do_fsync_dir_no_file(dentry, datasync); ++ } ++ au_cpup_attr_timesizes(inode); ++ di_write_unlock(dentry); ++ if (file) ++ fi_write_unlock(file); ++ ++ si_read_unlock(sb); ++ inode_unlock(inode); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int aufs_iterate_shared(struct file *file, struct dir_context *ctx) ++{ ++ int err; ++ struct dentry *dentry; ++ struct inode *inode, *h_inode; ++ struct super_block *sb; ++ ++ AuDbg("%pD, ctx{%ps, %llu}\n", file, ctx->actor, ctx->pos); ++ ++ dentry = file->f_path.dentry; ++ inode = d_inode(dentry); ++ IMustLock(inode); ++ ++ sb = dentry->d_sb; ++ si_read_lock(sb, AuLock_FLUSH); ++ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1, /*fi_lsc*/0); ++ if (unlikely(err)) ++ goto out; ++ err = au_alive_dir(dentry); ++ if (!err) ++ err = au_vdir_init(file); ++ di_downgrade_lock(dentry, AuLock_IR); ++ if (unlikely(err)) ++ goto out_unlock; ++ ++ h_inode = au_h_iptr(inode, au_ibtop(inode)); ++ if (!au_test_nfsd()) { ++ err = au_vdir_fill_de(file, ctx); ++ fsstack_copy_attr_atime(inode, h_inode); ++ } else { ++ /* ++ * nfsd filldir may call lookup_one_len(), vfs_getattr(), ++ * encode_fh() and others. ++ */ ++ atomic_inc(&h_inode->i_count); ++ di_read_unlock(dentry, AuLock_IR); ++ si_read_unlock(sb); ++ err = au_vdir_fill_de(file, ctx); ++ fsstack_copy_attr_atime(inode, h_inode); ++ fi_write_unlock(file); ++ iput(h_inode); ++ ++ AuTraceErr(err); ++ return err; ++ } ++ ++out_unlock: ++ di_read_unlock(dentry, AuLock_IR); ++ fi_write_unlock(file); ++out: ++ si_read_unlock(sb); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++#define AuTestEmpty_WHONLY 1 ++#define AuTestEmpty_CALLED (1 << 1) ++#define AuTestEmpty_SHWH (1 << 2) ++#define au_ftest_testempty(flags, name) ((flags) & AuTestEmpty_##name) ++#define au_fset_testempty(flags, name) \ ++ do { (flags) |= AuTestEmpty_##name; } while (0) ++#define au_fclr_testempty(flags, name) \ ++ do { (flags) &= ~AuTestEmpty_##name; } while (0) ++ ++#ifndef CONFIG_AUFS_SHWH ++#undef AuTestEmpty_SHWH ++#define AuTestEmpty_SHWH 0 ++#endif ++ ++struct test_empty_arg { ++ struct dir_context ctx; ++ struct au_nhash *whlist; ++ unsigned int flags; ++ int err; ++ aufs_bindex_t bindex; ++}; ++ ++static int test_empty_cb(struct dir_context *ctx, const char *__name, ++ int namelen, loff_t offset __maybe_unused, u64 ino, ++ unsigned int d_type) ++{ ++ struct test_empty_arg *arg = container_of(ctx, struct test_empty_arg, ++ ctx); ++ char *name = (void *)__name; ++ ++ arg->err = 0; ++ au_fset_testempty(arg->flags, CALLED); ++ /* smp_mb(); */ ++ if (name[0] == '.' ++ && (namelen == 1 || (name[1] == '.' && namelen == 2))) ++ goto out; /* success */ ++ ++ if (namelen <= AUFS_WH_PFX_LEN ++ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) { ++ if (au_ftest_testempty(arg->flags, WHONLY) ++ && !au_nhash_test_known_wh(arg->whlist, name, namelen)) ++ arg->err = -ENOTEMPTY; ++ goto out; ++ } ++ ++ name += AUFS_WH_PFX_LEN; ++ namelen -= AUFS_WH_PFX_LEN; ++ if (!au_nhash_test_known_wh(arg->whlist, name, namelen)) ++ arg->err = au_nhash_append_wh ++ (arg->whlist, name, namelen, ino, d_type, arg->bindex, ++ au_ftest_testempty(arg->flags, SHWH)); ++ ++out: ++ /* smp_mb(); */ ++ AuTraceErr(arg->err); ++ return arg->err; ++} ++ ++static int do_test_empty(struct dentry *dentry, struct test_empty_arg *arg) ++{ ++ int err; ++ struct file *h_file; ++ struct au_branch *br; ++ ++ h_file = au_h_open(dentry, arg->bindex, ++ O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_LARGEFILE, ++ /*file*/NULL, /*force_wr*/0); ++ err = PTR_ERR(h_file); ++ if (IS_ERR(h_file)) ++ goto out; ++ ++ err = 0; ++ if (!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE) ++ && !file_inode(h_file)->i_nlink) ++ goto out_put; ++ ++ do { ++ arg->err = 0; ++ au_fclr_testempty(arg->flags, CALLED); ++ /* smp_mb(); */ ++ err = vfsub_iterate_dir(h_file, &arg->ctx); ++ if (err >= 0) ++ err = arg->err; ++ } while (!err && au_ftest_testempty(arg->flags, CALLED)); ++ ++out_put: ++ fput(h_file); ++ br = au_sbr(dentry->d_sb, arg->bindex); ++ au_lcnt_dec(&br->br_nfiles); ++out: ++ return err; ++} ++ ++struct do_test_empty_args { ++ int *errp; ++ struct dentry *dentry; ++ struct test_empty_arg *arg; ++}; ++ ++static void call_do_test_empty(void *args) ++{ ++ struct do_test_empty_args *a = args; ++ *a->errp = do_test_empty(a->dentry, a->arg); ++} ++ ++static int sio_test_empty(struct dentry *dentry, struct test_empty_arg *arg) ++{ ++ int err, wkq_err; ++ struct dentry *h_dentry; ++ struct inode *h_inode; ++ ++ h_dentry = au_h_dptr(dentry, arg->bindex); ++ h_inode = d_inode(h_dentry); ++ /* todo: i_mode changes anytime? */ ++ inode_lock_shared_nested(h_inode, AuLsc_I_CHILD); ++ err = au_test_h_perm_sio(h_inode, MAY_EXEC | MAY_READ); ++ inode_unlock_shared(h_inode); ++ if (!err) ++ err = do_test_empty(dentry, arg); ++ else { ++ struct do_test_empty_args args = { ++ .errp = &err, ++ .dentry = dentry, ++ .arg = arg ++ }; ++ unsigned int flags = arg->flags; ++ ++ wkq_err = au_wkq_wait(call_do_test_empty, &args); ++ if (unlikely(wkq_err)) ++ err = wkq_err; ++ arg->flags = flags; ++ } ++ ++ return err; ++} ++ ++int au_test_empty_lower(struct dentry *dentry) ++{ ++ int err; ++ unsigned int rdhash; ++ aufs_bindex_t bindex, btop, btail; ++ struct au_nhash whlist; ++ struct test_empty_arg arg = { ++ .ctx = { ++ .actor = test_empty_cb ++ } ++ }; ++ int (*test_empty)(struct dentry *dentry, struct test_empty_arg *arg); ++ ++ SiMustAnyLock(dentry->d_sb); ++ ++ rdhash = au_sbi(dentry->d_sb)->si_rdhash; ++ if (!rdhash) ++ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, dentry)); ++ err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS); ++ if (unlikely(err)) ++ goto out; ++ ++ arg.flags = 0; ++ arg.whlist = &whlist; ++ btop = au_dbtop(dentry); ++ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH)) ++ au_fset_testempty(arg.flags, SHWH); ++ test_empty = do_test_empty; ++ if (au_opt_test(au_mntflags(dentry->d_sb), DIRPERM1)) ++ test_empty = sio_test_empty; ++ arg.bindex = btop; ++ err = test_empty(dentry, &arg); ++ if (unlikely(err)) ++ goto out_whlist; ++ ++ au_fset_testempty(arg.flags, WHONLY); ++ btail = au_dbtaildir(dentry); ++ for (bindex = btop + 1; !err && bindex <= btail; bindex++) { ++ struct dentry *h_dentry; ++ ++ h_dentry = au_h_dptr(dentry, bindex); ++ if (h_dentry && d_is_positive(h_dentry)) { ++ arg.bindex = bindex; ++ err = test_empty(dentry, &arg); ++ } ++ } ++ ++out_whlist: ++ au_nhash_wh_free(&whlist); ++out: ++ return err; ++} ++ ++int au_test_empty(struct dentry *dentry, struct au_nhash *whlist) ++{ ++ int err; ++ struct test_empty_arg arg = { ++ .ctx = { ++ .actor = test_empty_cb ++ } ++ }; ++ aufs_bindex_t bindex, btail; ++ ++ err = 0; ++ arg.whlist = whlist; ++ arg.flags = AuTestEmpty_WHONLY; ++ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH)) ++ au_fset_testempty(arg.flags, SHWH); ++ btail = au_dbtaildir(dentry); ++ for (bindex = au_dbtop(dentry); !err && bindex <= btail; bindex++) { ++ struct dentry *h_dentry; ++ ++ h_dentry = au_h_dptr(dentry, bindex); ++ if (h_dentry && d_is_positive(h_dentry)) { ++ arg.bindex = bindex; ++ err = sio_test_empty(dentry, &arg); ++ } ++ } ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++const struct file_operations aufs_dir_fop = { ++ .owner = THIS_MODULE, ++ .llseek = default_llseek, ++ .read = generic_read_dir, ++ .iterate_shared = aufs_iterate_shared, ++ .unlocked_ioctl = aufs_ioctl_dir, ++#ifdef CONFIG_COMPAT ++ .compat_ioctl = aufs_compat_ioctl_dir, ++#endif ++ .open = aufs_open_dir, ++ .release = aufs_release_dir, ++ .flush = aufs_flush_dir, ++ .fsync = aufs_fsync_dir ++}; +diff -Nurp linux-5.4/fs/aufs/dir.h linux-5.4-aufs/fs/aufs/dir.h +--- linux-5.4/fs/aufs/dir.h 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/dir.h 2019-11-28 01:25:59.064925618 +0200 +@@ -0,0 +1,121 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * directory operations ++ */ ++ ++#ifndef __AUFS_DIR_H__ ++#define __AUFS_DIR_H__ ++ ++#ifdef __KERNEL__ ++ ++#include ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* need to be faster and smaller */ ++ ++struct au_nhash { ++ unsigned int nh_num; ++ struct hlist_head *nh_head; ++}; ++ ++struct au_vdir_destr { ++ unsigned char len; ++ unsigned char name[0]; ++} __packed; ++ ++struct au_vdir_dehstr { ++ struct hlist_node hash; ++ struct au_vdir_destr *str; ++ struct rcu_head rcu; ++} ____cacheline_aligned_in_smp; ++ ++struct au_vdir_de { ++ ino_t de_ino; ++ unsigned char de_type; ++ /* caution: packed */ ++ struct au_vdir_destr de_str; ++} __packed; ++ ++struct au_vdir_wh { ++ struct hlist_node wh_hash; ++#ifdef CONFIG_AUFS_SHWH ++ ino_t wh_ino; ++ aufs_bindex_t wh_bindex; ++ unsigned char wh_type; ++#else ++ aufs_bindex_t wh_bindex; ++#endif ++ /* caution: packed */ ++ struct au_vdir_destr wh_str; ++} __packed; ++ ++union au_vdir_deblk_p { ++ unsigned char *deblk; ++ struct au_vdir_de *de; ++}; ++ ++struct au_vdir { ++ unsigned char **vd_deblk; ++ unsigned long vd_nblk; ++ struct { ++ unsigned long ul; ++ union au_vdir_deblk_p p; ++ } vd_last; ++ ++ u64 vd_version; ++ unsigned int vd_deblk_sz; ++ unsigned long vd_jiffy; ++ struct rcu_head rcu; ++} ____cacheline_aligned_in_smp; ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* dir.c */ ++extern const struct file_operations aufs_dir_fop; ++void au_add_nlink(struct inode *dir, struct inode *h_dir); ++void au_sub_nlink(struct inode *dir, struct inode *h_dir); ++loff_t au_dir_size(struct file *file, struct dentry *dentry); ++void au_dir_ts(struct inode *dir, aufs_bindex_t bsrc); ++int au_test_empty_lower(struct dentry *dentry); ++int au_test_empty(struct dentry *dentry, struct au_nhash *whlist); ++ ++/* vdir.c */ ++unsigned int au_rdhash_est(loff_t sz); ++int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp); ++void au_nhash_wh_free(struct au_nhash *whlist); ++int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt, ++ int limit); ++int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen); ++int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino, ++ unsigned int d_type, aufs_bindex_t bindex, ++ unsigned char shwh); ++void au_vdir_free(struct au_vdir *vdir); ++int au_vdir_init(struct file *file); ++int au_vdir_fill_de(struct file *file, struct dir_context *ctx); ++ ++/* ioctl.c */ ++long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg); ++ ++#ifdef CONFIG_AUFS_RDU ++/* rdu.c */ ++long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg); ++#ifdef CONFIG_COMPAT ++long au_rdu_compat_ioctl(struct file *file, unsigned int cmd, ++ unsigned long arg); ++#endif ++#else ++AuStub(long, au_rdu_ioctl, return -EINVAL, struct file *file, ++ unsigned int cmd, unsigned long arg) ++#ifdef CONFIG_COMPAT ++AuStub(long, au_rdu_compat_ioctl, return -EINVAL, struct file *file, ++ unsigned int cmd, unsigned long arg) ++#endif ++#endif ++ ++#endif /* __KERNEL__ */ ++#endif /* __AUFS_DIR_H__ */ +diff -Nurp linux-5.4/fs/aufs/dirren.c linux-5.4-aufs/fs/aufs/dirren.c +--- linux-5.4/fs/aufs/dirren.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/dirren.c 2019-11-28 01:25:59.064925618 +0200 +@@ -0,0 +1,1303 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2017-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * special handling in renaming a directory ++ * in order to support looking-up the before-renamed name on the lower readonly ++ * branches ++ */ ++ ++#include ++#include "aufs.h" ++ ++static void au_dr_hino_del(struct au_dr_br *dr, struct au_dr_hino *ent) ++{ ++ int idx; ++ ++ idx = au_dr_ihash(ent->dr_h_ino); ++ au_hbl_del(&ent->dr_hnode, dr->dr_h_ino + idx); ++} ++ ++static int au_dr_hino_test_empty(struct au_dr_br *dr) ++{ ++ int ret, i; ++ struct hlist_bl_head *hbl; ++ ++ ret = 1; ++ for (i = 0; ret && i < AuDirren_NHASH; i++) { ++ hbl = dr->dr_h_ino + i; ++ hlist_bl_lock(hbl); ++ ret &= hlist_bl_empty(hbl); ++ hlist_bl_unlock(hbl); ++ } ++ ++ return ret; ++} ++ ++static struct au_dr_hino *au_dr_hino_find(struct au_dr_br *dr, ino_t ino) ++{ ++ struct au_dr_hino *found, *ent; ++ struct hlist_bl_head *hbl; ++ struct hlist_bl_node *pos; ++ int idx; ++ ++ found = NULL; ++ idx = au_dr_ihash(ino); ++ hbl = dr->dr_h_ino + idx; ++ hlist_bl_lock(hbl); ++ hlist_bl_for_each_entry(ent, pos, hbl, dr_hnode) ++ if (ent->dr_h_ino == ino) { ++ found = ent; ++ break; ++ } ++ hlist_bl_unlock(hbl); ++ ++ return found; ++} ++ ++int au_dr_hino_test_add(struct au_dr_br *dr, ino_t ino, ++ struct au_dr_hino *add_ent) ++{ ++ int found, idx; ++ struct hlist_bl_head *hbl; ++ struct hlist_bl_node *pos; ++ struct au_dr_hino *ent; ++ ++ found = 0; ++ idx = au_dr_ihash(ino); ++ hbl = dr->dr_h_ino + idx; ++#if 0 ++ { ++ struct hlist_bl_node *tmp; ++ ++ hlist_bl_for_each_entry_safe(ent, pos, tmp, hbl, dr_hnode) ++ AuDbg("hi%llu\n", (unsigned long long)ent->dr_h_ino); ++ } ++#endif ++ hlist_bl_lock(hbl); ++ hlist_bl_for_each_entry(ent, pos, hbl, dr_hnode) ++ if (ent->dr_h_ino == ino) { ++ found = 1; ++ break; ++ } ++ if (!found && add_ent) ++ hlist_bl_add_head(&add_ent->dr_hnode, hbl); ++ hlist_bl_unlock(hbl); ++ ++ if (!found && add_ent) ++ AuDbg("i%llu added\n", (unsigned long long)add_ent->dr_h_ino); ++ ++ return found; ++} ++ ++void au_dr_hino_free(struct au_dr_br *dr) ++{ ++ int i; ++ struct hlist_bl_head *hbl; ++ struct hlist_bl_node *pos, *tmp; ++ struct au_dr_hino *ent; ++ ++ /* SiMustWriteLock(sb); */ ++ ++ for (i = 0; i < AuDirren_NHASH; i++) { ++ hbl = dr->dr_h_ino + i; ++ /* no spinlock since sbinfo must be write-locked */ ++ hlist_bl_for_each_entry_safe(ent, pos, tmp, hbl, dr_hnode) ++ au_kfree_rcu(ent); ++ INIT_HLIST_BL_HEAD(hbl); ++ } ++} ++ ++/* returns the number of inodes or an error */ ++static int au_dr_hino_store(struct super_block *sb, struct au_branch *br, ++ struct file *hinofile) ++{ ++ int err, i; ++ ssize_t ssz; ++ loff_t pos, oldsize; ++ __be64 u64; ++ struct inode *hinoinode; ++ struct hlist_bl_head *hbl; ++ struct hlist_bl_node *n1, *n2; ++ struct au_dr_hino *ent; ++ ++ SiMustWriteLock(sb); ++ AuDebugOn(!au_br_writable(br->br_perm)); ++ ++ hinoinode = file_inode(hinofile); ++ oldsize = i_size_read(hinoinode); ++ ++ err = 0; ++ pos = 0; ++ hbl = br->br_dirren.dr_h_ino; ++ for (i = 0; !err && i < AuDirren_NHASH; i++, hbl++) { ++ /* no bit-lock since sbinfo must be write-locked */ ++ hlist_bl_for_each_entry_safe(ent, n1, n2, hbl, dr_hnode) { ++ AuDbg("hi%llu, %pD2\n", ++ (unsigned long long)ent->dr_h_ino, hinofile); ++ u64 = cpu_to_be64(ent->dr_h_ino); ++ ssz = vfsub_write_k(hinofile, &u64, sizeof(u64), &pos); ++ if (ssz == sizeof(u64)) ++ continue; ++ ++ /* write error */ ++ pr_err("ssz %zd, %pD2\n", ssz, hinofile); ++ err = -ENOSPC; ++ if (ssz < 0) ++ err = ssz; ++ break; ++ } ++ } ++ /* regardless the error */ ++ if (pos < oldsize) { ++ err = vfsub_trunc(&hinofile->f_path, pos, /*attr*/0, hinofile); ++ AuTraceErr(err); ++ } ++ ++ AuTraceErr(err); ++ return err; ++} ++ ++static int au_dr_hino_load(struct au_dr_br *dr, struct file *hinofile) ++{ ++ int err, hidx; ++ ssize_t ssz; ++ size_t sz, n; ++ loff_t pos; ++ uint64_t u64; ++ struct au_dr_hino *ent; ++ struct inode *hinoinode; ++ struct hlist_bl_head *hbl; ++ ++ err = 0; ++ pos = 0; ++ hbl = dr->dr_h_ino; ++ hinoinode = file_inode(hinofile); ++ sz = i_size_read(hinoinode); ++ AuDebugOn(sz % sizeof(u64)); ++ n = sz / sizeof(u64); ++ while (n--) { ++ ssz = vfsub_read_k(hinofile, &u64, sizeof(u64), &pos); ++ if (unlikely(ssz != sizeof(u64))) { ++ pr_err("ssz %zd, %pD2\n", ssz, hinofile); ++ err = -EINVAL; ++ if (ssz < 0) ++ err = ssz; ++ goto out_free; ++ } ++ ++ ent = kmalloc(sizeof(*ent), GFP_NOFS); ++ if (!ent) { ++ err = -ENOMEM; ++ AuTraceErr(err); ++ goto out_free; ++ } ++ ent->dr_h_ino = be64_to_cpu((__force __be64)u64); ++ AuDbg("hi%llu, %pD2\n", ++ (unsigned long long)ent->dr_h_ino, hinofile); ++ hidx = au_dr_ihash(ent->dr_h_ino); ++ au_hbl_add(&ent->dr_hnode, hbl + hidx); ++ } ++ goto out; /* success */ ++ ++out_free: ++ au_dr_hino_free(dr); ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++/* ++ * @bindex/@br is a switch to distinguish whether suspending hnotify or not. ++ * @path is a switch to distinguish load and store. ++ */ ++static int au_dr_hino(struct super_block *sb, aufs_bindex_t bindex, ++ struct au_branch *br, const struct path *path) ++{ ++ int err, flags; ++ unsigned char load, suspend; ++ struct file *hinofile; ++ struct au_hinode *hdir; ++ struct inode *dir, *delegated; ++ struct path hinopath; ++ struct qstr hinoname = QSTR_INIT(AUFS_WH_DR_BRHINO, ++ sizeof(AUFS_WH_DR_BRHINO) - 1); ++ ++ AuDebugOn(bindex < 0 && !br); ++ AuDebugOn(bindex >= 0 && br); ++ ++ err = -EINVAL; ++ suspend = !br; ++ if (suspend) ++ br = au_sbr(sb, bindex); ++ load = !!path; ++ if (!load) { ++ path = &br->br_path; ++ AuDebugOn(!au_br_writable(br->br_perm)); ++ if (unlikely(!au_br_writable(br->br_perm))) ++ goto out; ++ } ++ ++ hdir = NULL; ++ if (suspend) { ++ dir = d_inode(sb->s_root); ++ hdir = au_hinode(au_ii(dir), bindex); ++ dir = hdir->hi_inode; ++ au_hn_inode_lock_nested(hdir, AuLsc_I_CHILD); ++ } else { ++ dir = d_inode(path->dentry); ++ inode_lock_nested(dir, AuLsc_I_CHILD); ++ } ++ hinopath.dentry = vfsub_lkup_one(&hinoname, path->dentry); ++ err = PTR_ERR(hinopath.dentry); ++ if (IS_ERR(hinopath.dentry)) ++ goto out_unlock; ++ ++ err = 0; ++ flags = O_RDONLY; ++ if (load) { ++ if (d_is_negative(hinopath.dentry)) ++ goto out_dput; /* success */ ++ } else { ++ if (au_dr_hino_test_empty(&br->br_dirren)) { ++ if (d_is_positive(hinopath.dentry)) { ++ delegated = NULL; ++ err = vfsub_unlink(dir, &hinopath, &delegated, ++ /*force*/0); ++ AuTraceErr(err); ++ if (unlikely(err)) ++ pr_err("ignored err %d, %pd2\n", ++ err, hinopath.dentry); ++ if (unlikely(err == -EWOULDBLOCK)) ++ iput(delegated); ++ err = 0; ++ } ++ goto out_dput; ++ } else if (!d_is_positive(hinopath.dentry)) { ++ err = vfsub_create(dir, &hinopath, 0600, ++ /*want_excl*/false); ++ AuTraceErr(err); ++ if (unlikely(err)) ++ goto out_dput; ++ } ++ flags = O_WRONLY; ++ } ++ hinopath.mnt = path->mnt; ++ hinofile = vfsub_dentry_open(&hinopath, flags); ++ if (suspend) ++ au_hn_inode_unlock(hdir); ++ else ++ inode_unlock(dir); ++ dput(hinopath.dentry); ++ AuTraceErrPtr(hinofile); ++ if (IS_ERR(hinofile)) { ++ err = PTR_ERR(hinofile); ++ goto out; ++ } ++ ++ if (load) ++ err = au_dr_hino_load(&br->br_dirren, hinofile); ++ else ++ err = au_dr_hino_store(sb, br, hinofile); ++ fput(hinofile); ++ goto out; ++ ++out_dput: ++ dput(hinopath.dentry); ++out_unlock: ++ if (suspend) ++ au_hn_inode_unlock(hdir); ++ else ++ inode_unlock(dir); ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int au_dr_brid_init(struct au_dr_brid *brid, const struct path *path) ++{ ++ int err; ++ struct kstatfs kstfs; ++ dev_t dev; ++ struct dentry *dentry; ++ struct super_block *sb; ++ ++ err = vfs_statfs((void *)path, &kstfs); ++ AuTraceErr(err); ++ if (unlikely(err)) ++ goto out; ++ ++ /* todo: support for UUID */ ++ ++ if (kstfs.f_fsid.val[0] || kstfs.f_fsid.val[1]) { ++ brid->type = AuBrid_FSID; ++ brid->fsid = kstfs.f_fsid; ++ } else { ++ dentry = path->dentry; ++ sb = dentry->d_sb; ++ dev = sb->s_dev; ++ if (dev) { ++ brid->type = AuBrid_DEV; ++ brid->dev = dev; ++ } ++ } ++ ++out: ++ return err; ++} ++ ++int au_dr_br_init(struct super_block *sb, struct au_branch *br, ++ const struct path *path) ++{ ++ int err, i; ++ struct au_dr_br *dr; ++ struct hlist_bl_head *hbl; ++ ++ dr = &br->br_dirren; ++ hbl = dr->dr_h_ino; ++ for (i = 0; i < AuDirren_NHASH; i++, hbl++) ++ INIT_HLIST_BL_HEAD(hbl); ++ ++ err = au_dr_brid_init(&dr->dr_brid, path); ++ if (unlikely(err)) ++ goto out; ++ ++ if (au_opt_test(au_mntflags(sb), DIRREN)) ++ err = au_dr_hino(sb, /*bindex*/-1, br, path); ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++int au_dr_br_fin(struct super_block *sb, struct au_branch *br) ++{ ++ int err; ++ ++ err = 0; ++ if (au_br_writable(br->br_perm)) ++ err = au_dr_hino(sb, /*bindex*/-1, br, /*path*/NULL); ++ if (!err) ++ au_dr_hino_free(&br->br_dirren); ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int au_brid_str(struct au_dr_brid *brid, struct inode *h_inode, ++ char *buf, size_t sz) ++{ ++ int err; ++ unsigned int major, minor; ++ char *p; ++ ++ p = buf; ++ err = snprintf(p, sz, "%d_", brid->type); ++ AuDebugOn(err > sz); ++ p += err; ++ sz -= err; ++ switch (brid->type) { ++ case AuBrid_Unset: ++ return -EINVAL; ++ case AuBrid_UUID: ++ err = snprintf(p, sz, "%pU", brid->uuid.b); ++ break; ++ case AuBrid_FSID: ++ err = snprintf(p, sz, "%08x-%08x", ++ brid->fsid.val[0], brid->fsid.val[1]); ++ break; ++ case AuBrid_DEV: ++ major = MAJOR(brid->dev); ++ minor = MINOR(brid->dev); ++ if (major <= 0xff && minor <= 0xff) ++ err = snprintf(p, sz, "%02x%02x", major, minor); ++ else ++ err = snprintf(p, sz, "%03x:%05x", major, minor); ++ break; ++ } ++ AuDebugOn(err > sz); ++ p += err; ++ sz -= err; ++ err = snprintf(p, sz, "_%llu", (unsigned long long)h_inode->i_ino); ++ AuDebugOn(err > sz); ++ p += err; ++ sz -= err; ++ ++ return p - buf; ++} ++ ++static int au_drinfo_name(struct au_branch *br, char *name, int len) ++{ ++ int rlen; ++ struct dentry *br_dentry; ++ struct inode *br_inode; ++ ++ br_dentry = au_br_dentry(br); ++ br_inode = d_inode(br_dentry); ++ rlen = au_brid_str(&br->br_dirren.dr_brid, br_inode, name, len); ++ AuDebugOn(rlen >= AUFS_DIRREN_ENV_VAL_SZ); ++ AuDebugOn(rlen > len); ++ ++ return rlen; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * from the given @h_dentry, construct drinfo at @*fdata. ++ * when the size of @*fdata is not enough, reallocate and return new @fdata and ++ * @allocated. ++ */ ++static int au_drinfo_construct(struct au_drinfo_fdata **fdata, ++ struct dentry *h_dentry, ++ unsigned char *allocated) ++{ ++ int err, v; ++ struct au_drinfo_fdata *f, *p; ++ struct au_drinfo *drinfo; ++ struct inode *h_inode; ++ struct qstr *qname; ++ ++ err = 0; ++ f = *fdata; ++ h_inode = d_inode(h_dentry); ++ qname = &h_dentry->d_name; ++ drinfo = &f->drinfo; ++ drinfo->ino = (__force uint64_t)cpu_to_be64(h_inode->i_ino); ++ drinfo->oldnamelen = qname->len; ++ if (*allocated < sizeof(*f) + qname->len) { ++ v = roundup_pow_of_two(*allocated + qname->len); ++ p = au_krealloc(f, v, GFP_NOFS, /*may_shrink*/0); ++ if (unlikely(!p)) { ++ err = -ENOMEM; ++ AuTraceErr(err); ++ goto out; ++ } ++ f = p; ++ *fdata = f; ++ *allocated = v; ++ drinfo = &f->drinfo; ++ } ++ memcpy(drinfo->oldname, qname->name, qname->len); ++ AuDbg("i%llu, %.*s\n", ++ be64_to_cpu((__force __be64)drinfo->ino), drinfo->oldnamelen, ++ drinfo->oldname); ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++/* callers have to free the return value */ ++static struct au_drinfo *au_drinfo_read_k(struct file *file, ino_t h_ino) ++{ ++ struct au_drinfo *ret, *drinfo; ++ struct au_drinfo_fdata fdata; ++ int len; ++ loff_t pos; ++ ssize_t ssz; ++ ++ ret = ERR_PTR(-EIO); ++ pos = 0; ++ ssz = vfsub_read_k(file, &fdata, sizeof(fdata), &pos); ++ if (unlikely(ssz != sizeof(fdata))) { ++ AuIOErr("ssz %zd, %u, %pD2\n", ++ ssz, (unsigned int)sizeof(fdata), file); ++ goto out; ++ } ++ ++ fdata.magic = ntohl((__force __be32)fdata.magic); ++ switch (fdata.magic) { ++ case AUFS_DRINFO_MAGIC_V1: ++ break; ++ default: ++ AuIOErr("magic-num 0x%x, 0x%x, %pD2\n", ++ fdata.magic, AUFS_DRINFO_MAGIC_V1, file); ++ goto out; ++ } ++ ++ drinfo = &fdata.drinfo; ++ len = drinfo->oldnamelen; ++ if (!len) { ++ AuIOErr("broken drinfo %pD2\n", file); ++ goto out; ++ } ++ ++ ret = NULL; ++ drinfo->ino = be64_to_cpu((__force __be64)drinfo->ino); ++ if (unlikely(h_ino && drinfo->ino != h_ino)) { ++ AuDbg("ignored i%llu, i%llu, %pD2\n", ++ (unsigned long long)drinfo->ino, ++ (unsigned long long)h_ino, file); ++ goto out; /* success */ ++ } ++ ++ ret = kmalloc(sizeof(*ret) + len, GFP_NOFS); ++ if (unlikely(!ret)) { ++ ret = ERR_PTR(-ENOMEM); ++ AuTraceErrPtr(ret); ++ goto out; ++ } ++ ++ *ret = *drinfo; ++ ssz = vfsub_read_k(file, (void *)ret->oldname, len, &pos); ++ if (unlikely(ssz != len)) { ++ au_kfree_rcu(ret); ++ ret = ERR_PTR(-EIO); ++ AuIOErr("ssz %zd, %u, %pD2\n", ssz, len, file); ++ goto out; ++ } ++ ++ AuDbg("oldname %.*s\n", ret->oldnamelen, ret->oldname); ++ ++out: ++ return ret; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* in order to be revertible */ ++struct au_drinfo_rev_elm { ++ int created; ++ struct dentry *info_dentry; ++ struct au_drinfo *info_last; ++}; ++ ++struct au_drinfo_rev { ++ unsigned char already; ++ aufs_bindex_t nelm; ++ struct au_drinfo_rev_elm elm[0]; ++}; ++ ++/* todo: isn't it too large? */ ++struct au_drinfo_store { ++ struct path h_ppath; ++ struct dentry *h_dentry; ++ struct au_drinfo_fdata *fdata; ++ char *infoname; /* inside of whname, just after PFX */ ++ char whname[sizeof(AUFS_WH_DR_INFO_PFX) + AUFS_DIRREN_ENV_VAL_SZ]; ++ aufs_bindex_t btgt, btail; ++ unsigned char no_sio, ++ allocated, /* current size of *fdata */ ++ infonamelen, /* room size for p */ ++ whnamelen, /* length of the generated name */ ++ renameback; /* renamed back */ ++}; ++ ++/* on rename(2) error, the caller should revert it using @elm */ ++static int au_drinfo_do_store(struct au_drinfo_store *w, ++ struct au_drinfo_rev_elm *elm) ++{ ++ int err, len; ++ ssize_t ssz; ++ loff_t pos; ++ struct path infopath = { ++ .mnt = w->h_ppath.mnt ++ }; ++ struct inode *h_dir, *h_inode, *delegated; ++ struct file *infofile; ++ struct qstr *qname; ++ ++ AuDebugOn(elm ++ && memcmp(elm, page_address(ZERO_PAGE(0)), sizeof(*elm))); ++ ++ infopath.dentry = vfsub_lookup_one_len(w->whname, w->h_ppath.dentry, ++ w->whnamelen); ++ AuTraceErrPtr(infopath.dentry); ++ if (IS_ERR(infopath.dentry)) { ++ err = PTR_ERR(infopath.dentry); ++ goto out; ++ } ++ ++ err = 0; ++ h_dir = d_inode(w->h_ppath.dentry); ++ if (elm && d_is_negative(infopath.dentry)) { ++ err = vfsub_create(h_dir, &infopath, 0600, /*want_excl*/true); ++ AuTraceErr(err); ++ if (unlikely(err)) ++ goto out_dput; ++ elm->created = 1; ++ elm->info_dentry = dget(infopath.dentry); ++ } ++ ++ infofile = vfsub_dentry_open(&infopath, O_RDWR); ++ AuTraceErrPtr(infofile); ++ if (IS_ERR(infofile)) { ++ err = PTR_ERR(infofile); ++ goto out_dput; ++ } ++ ++ h_inode = d_inode(infopath.dentry); ++ if (elm && i_size_read(h_inode)) { ++ h_inode = d_inode(w->h_dentry); ++ elm->info_last = au_drinfo_read_k(infofile, h_inode->i_ino); ++ AuTraceErrPtr(elm->info_last); ++ if (IS_ERR(elm->info_last)) { ++ err = PTR_ERR(elm->info_last); ++ elm->info_last = NULL; ++ AuDebugOn(elm->info_dentry); ++ goto out_fput; ++ } ++ } ++ ++ if (elm && w->renameback) { ++ delegated = NULL; ++ err = vfsub_unlink(h_dir, &infopath, &delegated, /*force*/0); ++ AuTraceErr(err); ++ if (unlikely(err == -EWOULDBLOCK)) ++ iput(delegated); ++ goto out_fput; ++ } ++ ++ pos = 0; ++ qname = &w->h_dentry->d_name; ++ len = sizeof(*w->fdata) + qname->len; ++ if (!elm) ++ len = sizeof(*w->fdata) + w->fdata->drinfo.oldnamelen; ++ ssz = vfsub_write_k(infofile, w->fdata, len, &pos); ++ if (ssz == len) { ++ AuDbg("hi%llu, %.*s\n", w->fdata->drinfo.ino, ++ w->fdata->drinfo.oldnamelen, w->fdata->drinfo.oldname); ++ goto out_fput; /* success */ ++ } else { ++ err = -EIO; ++ if (ssz < 0) ++ err = ssz; ++ /* the caller should revert it using @elm */ ++ } ++ ++out_fput: ++ fput(infofile); ++out_dput: ++ dput(infopath.dentry); ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++struct au_call_drinfo_do_store_args { ++ int *errp; ++ struct au_drinfo_store *w; ++ struct au_drinfo_rev_elm *elm; ++}; ++ ++static void au_call_drinfo_do_store(void *args) ++{ ++ struct au_call_drinfo_do_store_args *a = args; ++ ++ *a->errp = au_drinfo_do_store(a->w, a->elm); ++} ++ ++static int au_drinfo_store_sio(struct au_drinfo_store *w, ++ struct au_drinfo_rev_elm *elm) ++{ ++ int err, wkq_err; ++ ++ if (w->no_sio) ++ err = au_drinfo_do_store(w, elm); ++ else { ++ struct au_call_drinfo_do_store_args a = { ++ .errp = &err, ++ .w = w, ++ .elm = elm ++ }; ++ wkq_err = au_wkq_wait(au_call_drinfo_do_store, &a); ++ if (unlikely(wkq_err)) ++ err = wkq_err; ++ } ++ AuTraceErr(err); ++ ++ return err; ++} ++ ++static int au_drinfo_store_work_init(struct au_drinfo_store *w, ++ aufs_bindex_t btgt) ++{ ++ int err; ++ ++ memset(w, 0, sizeof(*w)); ++ w->allocated = roundup_pow_of_two(sizeof(*w->fdata) + 40); ++ strcpy(w->whname, AUFS_WH_DR_INFO_PFX); ++ w->infoname = w->whname + sizeof(AUFS_WH_DR_INFO_PFX) - 1; ++ w->infonamelen = sizeof(w->whname) - sizeof(AUFS_WH_DR_INFO_PFX); ++ w->btgt = btgt; ++ w->no_sio = !!uid_eq(current_fsuid(), GLOBAL_ROOT_UID); ++ ++ err = -ENOMEM; ++ w->fdata = kcalloc(1, w->allocated, GFP_NOFS); ++ if (unlikely(!w->fdata)) { ++ AuTraceErr(err); ++ goto out; ++ } ++ w->fdata->magic = (__force uint32_t)htonl(AUFS_DRINFO_MAGIC_V1); ++ err = 0; ++ ++out: ++ return err; ++} ++ ++static void au_drinfo_store_work_fin(struct au_drinfo_store *w) ++{ ++ au_kfree_rcu(w->fdata); ++} ++ ++static void au_drinfo_store_rev(struct au_drinfo_rev *rev, ++ struct au_drinfo_store *w) ++{ ++ struct au_drinfo_rev_elm *elm; ++ struct inode *h_dir, *delegated; ++ int err, nelm; ++ struct path infopath = { ++ .mnt = w->h_ppath.mnt ++ }; ++ ++ h_dir = d_inode(w->h_ppath.dentry); ++ IMustLock(h_dir); ++ ++ err = 0; ++ elm = rev->elm; ++ for (nelm = rev->nelm; nelm > 0; nelm--, elm++) { ++ AuDebugOn(elm->created && elm->info_last); ++ if (elm->created) { ++ AuDbg("here\n"); ++ delegated = NULL; ++ infopath.dentry = elm->info_dentry; ++ err = vfsub_unlink(h_dir, &infopath, &delegated, ++ !w->no_sio); ++ AuTraceErr(err); ++ if (unlikely(err == -EWOULDBLOCK)) ++ iput(delegated); ++ dput(elm->info_dentry); ++ } else if (elm->info_last) { ++ AuDbg("here\n"); ++ w->fdata->drinfo = *elm->info_last; ++ memcpy(w->fdata->drinfo.oldname, ++ elm->info_last->oldname, ++ elm->info_last->oldnamelen); ++ err = au_drinfo_store_sio(w, /*elm*/NULL); ++ au_kfree_rcu(elm->info_last); ++ } ++ if (unlikely(err)) ++ AuIOErr("%d, %s\n", err, w->whname); ++ /* go on even if err */ ++ } ++} ++ ++/* caller has to call au_dr_rename_fin() later */ ++static int au_drinfo_store(struct dentry *dentry, aufs_bindex_t btgt, ++ struct qstr *dst_name, void *_rev) ++{ ++ int err, sz, nelm; ++ aufs_bindex_t bindex, btail; ++ struct au_drinfo_store work; ++ struct au_drinfo_rev *rev, **p; ++ struct au_drinfo_rev_elm *elm; ++ struct super_block *sb; ++ struct au_branch *br; ++ struct au_hinode *hdir; ++ ++ err = au_drinfo_store_work_init(&work, btgt); ++ AuTraceErr(err); ++ if (unlikely(err)) ++ goto out; ++ ++ err = -ENOMEM; ++ btail = au_dbtaildir(dentry); ++ nelm = btail - btgt; ++ sz = sizeof(*rev) + sizeof(*elm) * nelm; ++ rev = kcalloc(1, sz, GFP_NOFS); ++ if (unlikely(!rev)) { ++ AuTraceErr(err); ++ goto out_args; ++ } ++ rev->nelm = nelm; ++ elm = rev->elm; ++ p = _rev; ++ *p = rev; ++ ++ err = 0; ++ sb = dentry->d_sb; ++ work.h_ppath.dentry = au_h_dptr(dentry, btgt); ++ work.h_ppath.mnt = au_sbr_mnt(sb, btgt); ++ hdir = au_hi(d_inode(dentry), btgt); ++ au_hn_inode_lock_nested(hdir, AuLsc_I_CHILD); ++ for (bindex = btgt + 1; bindex <= btail; bindex++, elm++) { ++ work.h_dentry = au_h_dptr(dentry, bindex); ++ if (!work.h_dentry) ++ continue; ++ ++ err = au_drinfo_construct(&work.fdata, work.h_dentry, ++ &work.allocated); ++ AuTraceErr(err); ++ if (unlikely(err)) ++ break; ++ ++ work.renameback = au_qstreq(&work.h_dentry->d_name, dst_name); ++ br = au_sbr(sb, bindex); ++ work.whnamelen = sizeof(AUFS_WH_DR_INFO_PFX) - 1; ++ work.whnamelen += au_drinfo_name(br, work.infoname, ++ work.infonamelen); ++ AuDbg("whname %.*s, i%llu, %.*s\n", ++ work.whnamelen, work.whname, ++ be64_to_cpu((__force __be64)work.fdata->drinfo.ino), ++ work.fdata->drinfo.oldnamelen, ++ work.fdata->drinfo.oldname); ++ ++ err = au_drinfo_store_sio(&work, elm); ++ AuTraceErr(err); ++ if (unlikely(err)) ++ break; ++ } ++ if (unlikely(err)) { ++ /* revert all drinfo */ ++ au_drinfo_store_rev(rev, &work); ++ au_kfree_try_rcu(rev); ++ *p = NULL; ++ } ++ au_hn_inode_unlock(hdir); ++ ++out_args: ++ au_drinfo_store_work_fin(&work); ++out: ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++int au_dr_rename(struct dentry *src, aufs_bindex_t bindex, ++ struct qstr *dst_name, void *_rev) ++{ ++ int err, already; ++ ino_t ino; ++ struct super_block *sb; ++ struct au_branch *br; ++ struct au_dr_br *dr; ++ struct dentry *h_dentry; ++ struct inode *h_inode; ++ struct au_dr_hino *ent; ++ struct au_drinfo_rev *rev, **p; ++ ++ AuDbg("bindex %d\n", bindex); ++ ++ err = -ENOMEM; ++ ent = kmalloc(sizeof(*ent), GFP_NOFS); ++ if (unlikely(!ent)) ++ goto out; ++ ++ sb = src->d_sb; ++ br = au_sbr(sb, bindex); ++ dr = &br->br_dirren; ++ h_dentry = au_h_dptr(src, bindex); ++ h_inode = d_inode(h_dentry); ++ ino = h_inode->i_ino; ++ ent->dr_h_ino = ino; ++ already = au_dr_hino_test_add(dr, ino, ent); ++ AuDbg("b%d, hi%llu, already %d\n", ++ bindex, (unsigned long long)ino, already); ++ ++ err = au_drinfo_store(src, bindex, dst_name, _rev); ++ AuTraceErr(err); ++ if (!err) { ++ p = _rev; ++ rev = *p; ++ rev->already = already; ++ goto out; /* success */ ++ } ++ ++ /* revert */ ++ if (!already) ++ au_dr_hino_del(dr, ent); ++ au_kfree_rcu(ent); ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++void au_dr_rename_fin(struct dentry *src, aufs_bindex_t btgt, void *_rev) ++{ ++ struct au_drinfo_rev *rev; ++ struct au_drinfo_rev_elm *elm; ++ int nelm; ++ ++ rev = _rev; ++ elm = rev->elm; ++ for (nelm = rev->nelm; nelm > 0; nelm--, elm++) { ++ dput(elm->info_dentry); ++ au_kfree_rcu(elm->info_last); ++ } ++ au_kfree_try_rcu(rev); ++} ++ ++void au_dr_rename_rev(struct dentry *src, aufs_bindex_t btgt, void *_rev) ++{ ++ int err; ++ struct au_drinfo_store work; ++ struct au_drinfo_rev *rev = _rev; ++ struct super_block *sb; ++ struct au_branch *br; ++ struct inode *h_inode; ++ struct au_dr_br *dr; ++ struct au_dr_hino *ent; ++ ++ err = au_drinfo_store_work_init(&work, btgt); ++ if (unlikely(err)) ++ goto out; ++ ++ sb = src->d_sb; ++ br = au_sbr(sb, btgt); ++ work.h_ppath.dentry = au_h_dptr(src, btgt); ++ work.h_ppath.mnt = au_br_mnt(br); ++ au_drinfo_store_rev(rev, &work); ++ au_drinfo_store_work_fin(&work); ++ if (rev->already) ++ goto out; ++ ++ dr = &br->br_dirren; ++ h_inode = d_inode(work.h_ppath.dentry); ++ ent = au_dr_hino_find(dr, h_inode->i_ino); ++ BUG_ON(!ent); ++ au_dr_hino_del(dr, ent); ++ au_kfree_rcu(ent); ++ ++out: ++ au_kfree_try_rcu(rev); ++ if (unlikely(err)) ++ pr_err("failed to remove dirren info\n"); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static struct au_drinfo *au_drinfo_do_load(struct path *h_ppath, ++ char *whname, int whnamelen, ++ struct dentry **info_dentry) ++{ ++ struct au_drinfo *drinfo; ++ struct file *f; ++ struct inode *h_dir; ++ struct path infopath; ++ int unlocked; ++ ++ AuDbg("%pd/%.*s\n", h_ppath->dentry, whnamelen, whname); ++ ++ *info_dentry = NULL; ++ drinfo = NULL; ++ unlocked = 0; ++ h_dir = d_inode(h_ppath->dentry); ++ inode_lock_shared_nested(h_dir, AuLsc_I_PARENT); ++ infopath.dentry = vfsub_lookup_one_len(whname, h_ppath->dentry, ++ whnamelen); ++ if (IS_ERR(infopath.dentry)) { ++ drinfo = (void *)infopath.dentry; ++ goto out; ++ } ++ ++ if (d_is_negative(infopath.dentry)) ++ goto out_dput; /* success */ ++ ++ infopath.mnt = h_ppath->mnt; ++ f = vfsub_dentry_open(&infopath, O_RDONLY); ++ inode_unlock_shared(h_dir); ++ unlocked = 1; ++ if (IS_ERR(f)) { ++ drinfo = (void *)f; ++ goto out_dput; ++ } ++ ++ drinfo = au_drinfo_read_k(f, /*h_ino*/0); ++ if (IS_ERR_OR_NULL(drinfo)) ++ goto out_fput; ++ ++ AuDbg("oldname %.*s\n", drinfo->oldnamelen, drinfo->oldname); ++ *info_dentry = dget(infopath.dentry); /* keep it alive */ ++ ++out_fput: ++ fput(f); ++out_dput: ++ dput(infopath.dentry); ++out: ++ if (!unlocked) ++ inode_unlock_shared(h_dir); ++ AuTraceErrPtr(drinfo); ++ return drinfo; ++} ++ ++struct au_drinfo_do_load_args { ++ struct au_drinfo **drinfop; ++ struct path *h_ppath; ++ char *whname; ++ int whnamelen; ++ struct dentry **info_dentry; ++}; ++ ++static void au_call_drinfo_do_load(void *args) ++{ ++ struct au_drinfo_do_load_args *a = args; ++ ++ *a->drinfop = au_drinfo_do_load(a->h_ppath, a->whname, a->whnamelen, ++ a->info_dentry); ++} ++ ++struct au_drinfo_load { ++ struct path h_ppath; ++ struct qstr *qname; ++ unsigned char no_sio; ++ ++ aufs_bindex_t ninfo; ++ struct au_drinfo **drinfo; ++}; ++ ++static int au_drinfo_load(struct au_drinfo_load *w, aufs_bindex_t bindex, ++ struct au_branch *br) ++{ ++ int err, wkq_err, whnamelen, e; ++ char whname[sizeof(AUFS_WH_DR_INFO_PFX) + AUFS_DIRREN_ENV_VAL_SZ] ++ = AUFS_WH_DR_INFO_PFX; ++ struct au_drinfo *drinfo; ++ struct qstr oldname; ++ struct inode *h_dir, *delegated; ++ struct dentry *info_dentry; ++ struct path infopath; ++ ++ whnamelen = sizeof(AUFS_WH_DR_INFO_PFX) - 1; ++ whnamelen += au_drinfo_name(br, whname + whnamelen, ++ sizeof(whname) - whnamelen); ++ if (w->no_sio) ++ drinfo = au_drinfo_do_load(&w->h_ppath, whname, whnamelen, ++ &info_dentry); ++ else { ++ struct au_drinfo_do_load_args args = { ++ .drinfop = &drinfo, ++ .h_ppath = &w->h_ppath, ++ .whname = whname, ++ .whnamelen = whnamelen, ++ .info_dentry = &info_dentry ++ }; ++ wkq_err = au_wkq_wait(au_call_drinfo_do_load, &args); ++ if (unlikely(wkq_err)) ++ drinfo = ERR_PTR(wkq_err); ++ } ++ err = PTR_ERR(drinfo); ++ if (IS_ERR_OR_NULL(drinfo)) ++ goto out; ++ ++ err = 0; ++ oldname.len = drinfo->oldnamelen; ++ oldname.name = drinfo->oldname; ++ if (au_qstreq(w->qname, &oldname)) { ++ /* the name is renamed back */ ++ au_kfree_rcu(drinfo); ++ drinfo = NULL; ++ ++ infopath.dentry = info_dentry; ++ infopath.mnt = w->h_ppath.mnt; ++ h_dir = d_inode(w->h_ppath.dentry); ++ delegated = NULL; ++ inode_lock_nested(h_dir, AuLsc_I_PARENT); ++ e = vfsub_unlink(h_dir, &infopath, &delegated, !w->no_sio); ++ inode_unlock(h_dir); ++ if (unlikely(e)) ++ AuIOErr("ignored %d, %pd2\n", e, &infopath.dentry); ++ if (unlikely(e == -EWOULDBLOCK)) ++ iput(delegated); ++ } ++ au_kfree_rcu(w->drinfo[bindex]); ++ w->drinfo[bindex] = drinfo; ++ dput(info_dentry); ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static void au_dr_lkup_free(struct au_drinfo **drinfo, int n) ++{ ++ struct au_drinfo **p = drinfo; ++ ++ while (n-- > 0) ++ au_kfree_rcu(*drinfo++); ++ au_kfree_try_rcu(p); ++} ++ ++int au_dr_lkup(struct au_do_lookup_args *lkup, struct dentry *dentry, ++ aufs_bindex_t btgt) ++{ ++ int err, ninfo; ++ struct au_drinfo_load w; ++ aufs_bindex_t bindex, bbot; ++ struct au_branch *br; ++ struct inode *h_dir; ++ struct au_dr_hino *ent; ++ struct super_block *sb; ++ ++ AuDbg("%.*s, name %.*s, whname %.*s, b%d\n", ++ AuLNPair(&dentry->d_name), AuLNPair(&lkup->dirren.dr_name), ++ AuLNPair(&lkup->whname), btgt); ++ ++ sb = dentry->d_sb; ++ bbot = au_sbbot(sb); ++ w.ninfo = bbot + 1; ++ if (!lkup->dirren.drinfo) { ++ lkup->dirren.drinfo = kcalloc(w.ninfo, ++ sizeof(*lkup->dirren.drinfo), ++ GFP_NOFS); ++ if (unlikely(!lkup->dirren.drinfo)) { ++ err = -ENOMEM; ++ goto out; ++ } ++ lkup->dirren.ninfo = w.ninfo; ++ } ++ w.drinfo = lkup->dirren.drinfo; ++ w.no_sio = !!uid_eq(current_fsuid(), GLOBAL_ROOT_UID); ++ w.h_ppath.dentry = au_h_dptr(dentry, btgt); ++ AuDebugOn(!w.h_ppath.dentry); ++ w.h_ppath.mnt = au_sbr_mnt(sb, btgt); ++ w.qname = &dentry->d_name; ++ ++ ninfo = 0; ++ for (bindex = btgt + 1; bindex <= bbot; bindex++) { ++ br = au_sbr(sb, bindex); ++ err = au_drinfo_load(&w, bindex, br); ++ if (unlikely(err)) ++ goto out_free; ++ if (w.drinfo[bindex]) ++ ninfo++; ++ } ++ if (!ninfo) { ++ br = au_sbr(sb, btgt); ++ h_dir = d_inode(w.h_ppath.dentry); ++ ent = au_dr_hino_find(&br->br_dirren, h_dir->i_ino); ++ AuDebugOn(!ent); ++ au_dr_hino_del(&br->br_dirren, ent); ++ au_kfree_rcu(ent); ++ } ++ goto out; /* success */ ++ ++out_free: ++ au_dr_lkup_free(lkup->dirren.drinfo, lkup->dirren.ninfo); ++ lkup->dirren.ninfo = 0; ++ lkup->dirren.drinfo = NULL; ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++void au_dr_lkup_fin(struct au_do_lookup_args *lkup) ++{ ++ au_dr_lkup_free(lkup->dirren.drinfo, lkup->dirren.ninfo); ++} ++ ++int au_dr_lkup_name(struct au_do_lookup_args *lkup, aufs_bindex_t btgt) ++{ ++ int err; ++ struct au_drinfo *drinfo; ++ ++ err = 0; ++ if (!lkup->dirren.drinfo) ++ goto out; ++ AuDebugOn(lkup->dirren.ninfo < btgt + 1); ++ drinfo = lkup->dirren.drinfo[btgt + 1]; ++ if (!drinfo) ++ goto out; ++ ++ au_kfree_try_rcu(lkup->whname.name); ++ lkup->whname.name = NULL; ++ lkup->dirren.dr_name.len = drinfo->oldnamelen; ++ lkup->dirren.dr_name.name = drinfo->oldname; ++ lkup->name = &lkup->dirren.dr_name; ++ err = au_wh_name_alloc(&lkup->whname, lkup->name); ++ if (!err) ++ AuDbg("name %.*s, whname %.*s, b%d\n", ++ AuLNPair(lkup->name), AuLNPair(&lkup->whname), ++ btgt); ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++int au_dr_lkup_h_ino(struct au_do_lookup_args *lkup, aufs_bindex_t bindex, ++ ino_t h_ino) ++{ ++ int match; ++ struct au_drinfo *drinfo; ++ ++ match = 1; ++ if (!lkup->dirren.drinfo) ++ goto out; ++ AuDebugOn(lkup->dirren.ninfo < bindex + 1); ++ drinfo = lkup->dirren.drinfo[bindex + 1]; ++ if (!drinfo) ++ goto out; ++ ++ match = (drinfo->ino == h_ino); ++ AuDbg("match %d\n", match); ++ ++out: ++ return match; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++int au_dr_opt_set(struct super_block *sb) ++{ ++ int err; ++ aufs_bindex_t bindex, bbot; ++ struct au_branch *br; ++ ++ err = 0; ++ bbot = au_sbbot(sb); ++ for (bindex = 0; !err && bindex <= bbot; bindex++) { ++ br = au_sbr(sb, bindex); ++ err = au_dr_hino(sb, bindex, /*br*/NULL, &br->br_path); ++ } ++ ++ return err; ++} ++ ++int au_dr_opt_flush(struct super_block *sb) ++{ ++ int err; ++ aufs_bindex_t bindex, bbot; ++ struct au_branch *br; ++ ++ err = 0; ++ bbot = au_sbbot(sb); ++ for (bindex = 0; !err && bindex <= bbot; bindex++) { ++ br = au_sbr(sb, bindex); ++ if (au_br_writable(br->br_perm)) ++ err = au_dr_hino(sb, bindex, /*br*/NULL, /*path*/NULL); ++ } ++ ++ return err; ++} ++ ++int au_dr_opt_clr(struct super_block *sb, int no_flush) ++{ ++ int err; ++ aufs_bindex_t bindex, bbot; ++ struct au_branch *br; ++ ++ err = 0; ++ if (!no_flush) { ++ err = au_dr_opt_flush(sb); ++ if (unlikely(err)) ++ goto out; ++ } ++ ++ bbot = au_sbbot(sb); ++ for (bindex = 0; bindex <= bbot; bindex++) { ++ br = au_sbr(sb, bindex); ++ au_dr_hino_free(&br->br_dirren); ++ } ++ ++out: ++ return err; ++} +diff -Nurp linux-5.4/fs/aufs/dirren.h linux-5.4-aufs/fs/aufs/dirren.h +--- linux-5.4/fs/aufs/dirren.h 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/dirren.h 2019-11-28 01:25:59.064925618 +0200 +@@ -0,0 +1,127 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2017-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * renamed dir info ++ */ ++ ++#ifndef __AUFS_DIRREN_H__ ++#define __AUFS_DIRREN_H__ ++ ++#ifdef __KERNEL__ ++ ++#include ++#include ++#include ++#include "hbl.h" ++ ++#define AuDirren_NHASH 100 ++ ++#ifdef CONFIG_AUFS_DIRREN ++enum au_brid_type { ++ AuBrid_Unset, ++ AuBrid_UUID, ++ AuBrid_FSID, ++ AuBrid_DEV ++}; ++ ++struct au_dr_brid { ++ enum au_brid_type type; ++ union { ++ uuid_t uuid; /* unimplemented yet */ ++ fsid_t fsid; ++ dev_t dev; ++ }; ++}; ++ ++/* 20 is the max digits length of ulong 64 */ ++/* brid-type "_" uuid "_" inum */ ++#define AUFS_DIRREN_FNAME_SZ (1 + 1 + UUID_STRING_LEN + 20) ++#define AUFS_DIRREN_ENV_VAL_SZ (AUFS_DIRREN_FNAME_SZ + 1 + 20) ++ ++struct au_dr_hino { ++ struct hlist_bl_node dr_hnode; ++ ino_t dr_h_ino; ++}; ++ ++struct au_dr_br { ++ struct hlist_bl_head dr_h_ino[AuDirren_NHASH]; ++ struct au_dr_brid dr_brid; ++}; ++ ++struct au_dr_lookup { ++ /* dr_name is pointed by struct au_do_lookup_args.name */ ++ struct qstr dr_name; /* subset of dr_info */ ++ aufs_bindex_t ninfo; ++ struct au_drinfo **drinfo; ++}; ++#else ++struct au_dr_hino; ++/* empty */ ++struct au_dr_br { }; ++struct au_dr_lookup { }; ++#endif ++ ++/* ---------------------------------------------------------------------- */ ++ ++struct au_branch; ++struct au_do_lookup_args; ++struct au_hinode; ++#ifdef CONFIG_AUFS_DIRREN ++int au_dr_hino_test_add(struct au_dr_br *dr, ino_t h_ino, ++ struct au_dr_hino *add_ent); ++void au_dr_hino_free(struct au_dr_br *dr); ++int au_dr_br_init(struct super_block *sb, struct au_branch *br, ++ const struct path *path); ++int au_dr_br_fin(struct super_block *sb, struct au_branch *br); ++int au_dr_rename(struct dentry *src, aufs_bindex_t bindex, ++ struct qstr *dst_name, void *_rev); ++void au_dr_rename_fin(struct dentry *src, aufs_bindex_t btgt, void *rev); ++void au_dr_rename_rev(struct dentry *src, aufs_bindex_t bindex, void *rev); ++int au_dr_lkup(struct au_do_lookup_args *lkup, struct dentry *dentry, ++ aufs_bindex_t bindex); ++int au_dr_lkup_name(struct au_do_lookup_args *lkup, aufs_bindex_t btgt); ++int au_dr_lkup_h_ino(struct au_do_lookup_args *lkup, aufs_bindex_t bindex, ++ ino_t h_ino); ++void au_dr_lkup_fin(struct au_do_lookup_args *lkup); ++int au_dr_opt_set(struct super_block *sb); ++int au_dr_opt_flush(struct super_block *sb); ++int au_dr_opt_clr(struct super_block *sb, int no_flush); ++#else ++AuStubInt0(au_dr_hino_test_add, struct au_dr_br *dr, ino_t h_ino, ++ struct au_dr_hino *add_ent); ++AuStubVoid(au_dr_hino_free, struct au_dr_br *dr); ++AuStubInt0(au_dr_br_init, struct super_block *sb, struct au_branch *br, ++ const struct path *path); ++AuStubInt0(au_dr_br_fin, struct super_block *sb, struct au_branch *br); ++AuStubInt0(au_dr_rename, struct dentry *src, aufs_bindex_t bindex, ++ struct qstr *dst_name, void *_rev); ++AuStubVoid(au_dr_rename_fin, struct dentry *src, aufs_bindex_t btgt, void *rev); ++AuStubVoid(au_dr_rename_rev, struct dentry *src, aufs_bindex_t bindex, ++ void *rev); ++AuStubInt0(au_dr_lkup, struct au_do_lookup_args *lkup, struct dentry *dentry, ++ aufs_bindex_t bindex); ++AuStubInt0(au_dr_lkup_name, struct au_do_lookup_args *lkup, aufs_bindex_t btgt); ++AuStubInt0(au_dr_lkup_h_ino, struct au_do_lookup_args *lkup, ++ aufs_bindex_t bindex, ino_t h_ino); ++AuStubVoid(au_dr_lkup_fin, struct au_do_lookup_args *lkup); ++AuStubInt0(au_dr_opt_set, struct super_block *sb); ++AuStubInt0(au_dr_opt_flush, struct super_block *sb); ++AuStubInt0(au_dr_opt_clr, struct super_block *sb, int no_flush); ++#endif ++ ++/* ---------------------------------------------------------------------- */ ++ ++#ifdef CONFIG_AUFS_DIRREN ++static inline int au_dr_ihash(ino_t h_ino) ++{ ++ return h_ino % AuDirren_NHASH; ++} ++#else ++AuStubInt0(au_dr_ihash, ino_t h_ino); ++#endif ++ ++#endif /* __KERNEL__ */ ++#endif /* __AUFS_DIRREN_H__ */ +diff -Nurp linux-5.4/fs/aufs/dynop.c linux-5.4-aufs/fs/aufs/dynop.c +--- linux-5.4/fs/aufs/dynop.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/dynop.c 2019-11-28 01:25:59.064925618 +0200 +@@ -0,0 +1,354 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2010-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * dynamically customizable operations for regular files ++ */ ++ ++#include "aufs.h" ++ ++#define DyPrSym(key) AuDbgSym(key->dk_op.dy_hop) ++ ++/* ++ * How large will these lists be? ++ * Usually just a few elements, 20-30 at most for each, I guess. ++ */ ++static struct hlist_bl_head dynop[AuDyLast]; ++ ++static struct au_dykey *dy_gfind_get(struct hlist_bl_head *hbl, ++ const void *h_op) ++{ ++ struct au_dykey *key, *tmp; ++ struct hlist_bl_node *pos; ++ ++ key = NULL; ++ hlist_bl_lock(hbl); ++ hlist_bl_for_each_entry(tmp, pos, hbl, dk_hnode) ++ if (tmp->dk_op.dy_hop == h_op) { ++ if (kref_get_unless_zero(&tmp->dk_kref)) ++ key = tmp; ++ break; ++ } ++ hlist_bl_unlock(hbl); ++ ++ return key; ++} ++ ++static struct au_dykey *dy_bradd(struct au_branch *br, struct au_dykey *key) ++{ ++ struct au_dykey **k, *found; ++ const void *h_op = key->dk_op.dy_hop; ++ int i; ++ ++ found = NULL; ++ k = br->br_dykey; ++ for (i = 0; i < AuBrDynOp; i++) ++ if (k[i]) { ++ if (k[i]->dk_op.dy_hop == h_op) { ++ found = k[i]; ++ break; ++ } ++ } else ++ break; ++ if (!found) { ++ spin_lock(&br->br_dykey_lock); ++ for (; i < AuBrDynOp; i++) ++ if (k[i]) { ++ if (k[i]->dk_op.dy_hop == h_op) { ++ found = k[i]; ++ break; ++ } ++ } else { ++ k[i] = key; ++ break; ++ } ++ spin_unlock(&br->br_dykey_lock); ++ BUG_ON(i == AuBrDynOp); /* expand the array */ ++ } ++ ++ return found; ++} ++ ++/* kref_get() if @key is already added */ ++static struct au_dykey *dy_gadd(struct hlist_bl_head *hbl, struct au_dykey *key) ++{ ++ struct au_dykey *tmp, *found; ++ struct hlist_bl_node *pos; ++ const void *h_op = key->dk_op.dy_hop; ++ ++ found = NULL; ++ hlist_bl_lock(hbl); ++ hlist_bl_for_each_entry(tmp, pos, hbl, dk_hnode) ++ if (tmp->dk_op.dy_hop == h_op) { ++ if (kref_get_unless_zero(&tmp->dk_kref)) ++ found = tmp; ++ break; ++ } ++ if (!found) ++ hlist_bl_add_head(&key->dk_hnode, hbl); ++ hlist_bl_unlock(hbl); ++ ++ if (!found) ++ DyPrSym(key); ++ return found; ++} ++ ++static void dy_free_rcu(struct rcu_head *rcu) ++{ ++ struct au_dykey *key; ++ ++ key = container_of(rcu, struct au_dykey, dk_rcu); ++ DyPrSym(key); ++ kfree(key); ++} ++ ++static void dy_free(struct kref *kref) ++{ ++ struct au_dykey *key; ++ struct hlist_bl_head *hbl; ++ ++ key = container_of(kref, struct au_dykey, dk_kref); ++ hbl = dynop + key->dk_op.dy_type; ++ au_hbl_del(&key->dk_hnode, hbl); ++ call_rcu(&key->dk_rcu, dy_free_rcu); ++} ++ ++void au_dy_put(struct au_dykey *key) ++{ ++ kref_put(&key->dk_kref, dy_free); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++#define DyDbgSize(cnt, op) AuDebugOn(cnt != sizeof(op)/sizeof(void *)) ++ ++#ifdef CONFIG_AUFS_DEBUG ++#define DyDbgDeclare(cnt) unsigned int cnt = 0 ++#define DyDbgInc(cnt) do { cnt++; } while (0) ++#else ++#define DyDbgDeclare(cnt) do {} while (0) ++#define DyDbgInc(cnt) do {} while (0) ++#endif ++ ++#define DySet(func, dst, src, h_op, h_sb) do { \ ++ DyDbgInc(cnt); \ ++ if (h_op->func) { \ ++ if (src.func) \ ++ dst.func = src.func; \ ++ else \ ++ AuDbg("%s %s\n", au_sbtype(h_sb), #func); \ ++ } \ ++} while (0) ++ ++#define DySetForce(func, dst, src) do { \ ++ AuDebugOn(!src.func); \ ++ DyDbgInc(cnt); \ ++ dst.func = src.func; \ ++} while (0) ++ ++#define DySetAop(func) \ ++ DySet(func, dyaop->da_op, aufs_aop, h_aop, h_sb) ++#define DySetAopForce(func) \ ++ DySetForce(func, dyaop->da_op, aufs_aop) ++ ++static void dy_aop(struct au_dykey *key, const void *h_op, ++ struct super_block *h_sb __maybe_unused) ++{ ++ struct au_dyaop *dyaop = (void *)key; ++ const struct address_space_operations *h_aop = h_op; ++ DyDbgDeclare(cnt); ++ ++ AuDbg("%s\n", au_sbtype(h_sb)); ++ ++ DySetAop(writepage); ++ DySetAopForce(readpage); /* force */ ++ DySetAop(writepages); ++ DySetAop(set_page_dirty); ++ DySetAop(readpages); ++ DySetAop(write_begin); ++ DySetAop(write_end); ++ DySetAop(bmap); ++ DySetAop(invalidatepage); ++ DySetAop(releasepage); ++ DySetAop(freepage); ++ /* this one will be changed according to an aufs mount option */ ++ DySetAop(direct_IO); ++ DySetAop(migratepage); ++ DySetAop(isolate_page); ++ DySetAop(putback_page); ++ DySetAop(launder_page); ++ DySetAop(is_partially_uptodate); ++ DySetAop(is_dirty_writeback); ++ DySetAop(error_remove_page); ++ DySetAop(swap_activate); ++ DySetAop(swap_deactivate); ++ ++ DyDbgSize(cnt, *h_aop); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static void dy_bug(struct kref *kref) ++{ ++ BUG(); ++} ++ ++static struct au_dykey *dy_get(struct au_dynop *op, struct au_branch *br) ++{ ++ struct au_dykey *key, *old; ++ struct hlist_bl_head *hbl; ++ struct op { ++ unsigned int sz; ++ void (*set)(struct au_dykey *key, const void *h_op, ++ struct super_block *h_sb __maybe_unused); ++ }; ++ static const struct op a[] = { ++ [AuDy_AOP] = { ++ .sz = sizeof(struct au_dyaop), ++ .set = dy_aop ++ } ++ }; ++ const struct op *p; ++ ++ hbl = dynop + op->dy_type; ++ key = dy_gfind_get(hbl, op->dy_hop); ++ if (key) ++ goto out_add; /* success */ ++ ++ p = a + op->dy_type; ++ key = kzalloc(p->sz, GFP_NOFS); ++ if (unlikely(!key)) { ++ key = ERR_PTR(-ENOMEM); ++ goto out; ++ } ++ ++ key->dk_op.dy_hop = op->dy_hop; ++ kref_init(&key->dk_kref); ++ p->set(key, op->dy_hop, au_br_sb(br)); ++ old = dy_gadd(hbl, key); ++ if (old) { ++ au_kfree_rcu(key); ++ key = old; ++ } ++ ++out_add: ++ old = dy_bradd(br, key); ++ if (old) ++ /* its ref-count should never be zero here */ ++ kref_put(&key->dk_kref, dy_bug); ++out: ++ return key; ++} ++ ++/* ---------------------------------------------------------------------- */ ++/* ++ * Aufs prohibits O_DIRECT by default even if the branch supports it. ++ * This behaviour is necessary to return an error from open(O_DIRECT) instead ++ * of the succeeding I/O. The dio mount option enables O_DIRECT and makes ++ * open(O_DIRECT) always succeed, but the succeeding I/O may return an error. ++ * See the aufs manual in detail. ++ */ ++static void dy_adx(struct au_dyaop *dyaop, int do_dx) ++{ ++ if (!do_dx) ++ dyaop->da_op.direct_IO = NULL; ++ else ++ dyaop->da_op.direct_IO = aufs_aop.direct_IO; ++} ++ ++static struct au_dyaop *dy_aget(struct au_branch *br, ++ const struct address_space_operations *h_aop, ++ int do_dx) ++{ ++ struct au_dyaop *dyaop; ++ struct au_dynop op; ++ ++ op.dy_type = AuDy_AOP; ++ op.dy_haop = h_aop; ++ dyaop = (void *)dy_get(&op, br); ++ if (IS_ERR(dyaop)) ++ goto out; ++ dy_adx(dyaop, do_dx); ++ ++out: ++ return dyaop; ++} ++ ++int au_dy_iaop(struct inode *inode, aufs_bindex_t bindex, ++ struct inode *h_inode) ++{ ++ int err, do_dx; ++ struct super_block *sb; ++ struct au_branch *br; ++ struct au_dyaop *dyaop; ++ ++ AuDebugOn(!S_ISREG(h_inode->i_mode)); ++ IiMustWriteLock(inode); ++ ++ sb = inode->i_sb; ++ br = au_sbr(sb, bindex); ++ do_dx = !!au_opt_test(au_mntflags(sb), DIO); ++ dyaop = dy_aget(br, h_inode->i_mapping->a_ops, do_dx); ++ err = PTR_ERR(dyaop); ++ if (IS_ERR(dyaop)) ++ /* unnecessary to call dy_fput() */ ++ goto out; ++ ++ err = 0; ++ inode->i_mapping->a_ops = &dyaop->da_op; ++ ++out: ++ return err; ++} ++ ++/* ++ * Is it safe to replace a_ops during the inode/file is in operation? ++ * Yes, I hope so. ++ */ ++int au_dy_irefresh(struct inode *inode) ++{ ++ int err; ++ aufs_bindex_t btop; ++ struct inode *h_inode; ++ ++ err = 0; ++ if (S_ISREG(inode->i_mode)) { ++ btop = au_ibtop(inode); ++ h_inode = au_h_iptr(inode, btop); ++ err = au_dy_iaop(inode, btop, h_inode); ++ } ++ return err; ++} ++ ++void au_dy_arefresh(int do_dx) ++{ ++ struct hlist_bl_head *hbl; ++ struct hlist_bl_node *pos; ++ struct au_dykey *key; ++ ++ hbl = dynop + AuDy_AOP; ++ hlist_bl_lock(hbl); ++ hlist_bl_for_each_entry(key, pos, hbl, dk_hnode) ++ dy_adx((void *)key, do_dx); ++ hlist_bl_unlock(hbl); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++void __init au_dy_init(void) ++{ ++ int i; ++ ++ for (i = 0; i < AuDyLast; i++) ++ INIT_HLIST_BL_HEAD(dynop + i); ++} ++ ++void au_dy_fin(void) ++{ ++ int i; ++ ++ for (i = 0; i < AuDyLast; i++) ++ WARN_ON(!hlist_bl_empty(dynop + i)); ++} +diff -Nurp linux-5.4/fs/aufs/dynop.h linux-5.4-aufs/fs/aufs/dynop.h +--- linux-5.4/fs/aufs/dynop.h 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/dynop.h 2019-11-28 01:25:59.064925618 +0200 +@@ -0,0 +1,64 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2010-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * dynamically customizable operations (for regular files only) ++ */ ++ ++#ifndef __AUFS_DYNOP_H__ ++#define __AUFS_DYNOP_H__ ++ ++#ifdef __KERNEL__ ++ ++#include ++#include ++ ++enum {AuDy_AOP, AuDyLast}; ++ ++struct au_dynop { ++ int dy_type; ++ union { ++ const void *dy_hop; ++ const struct address_space_operations *dy_haop; ++ }; ++}; ++ ++struct au_dykey { ++ union { ++ struct hlist_bl_node dk_hnode; ++ struct rcu_head dk_rcu; ++ }; ++ struct au_dynop dk_op; ++ ++ /* ++ * during I am in the branch local array, kref is gotten. when the ++ * branch is removed, kref is put. ++ */ ++ struct kref dk_kref; ++}; ++ ++/* stop unioning since their sizes are very different from each other */ ++struct au_dyaop { ++ struct au_dykey da_key; ++ struct address_space_operations da_op; /* not const */ ++}; ++/* make sure that 'struct au_dykey *' can be any type */ ++static_assert(!offsetof(struct au_dyaop, da_key)); ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* dynop.c */ ++struct au_branch; ++void au_dy_put(struct au_dykey *key); ++int au_dy_iaop(struct inode *inode, aufs_bindex_t bindex, ++ struct inode *h_inode); ++int au_dy_irefresh(struct inode *inode); ++void au_dy_arefresh(int do_dio); ++ ++void __init au_dy_init(void); ++void au_dy_fin(void); ++ ++#endif /* __KERNEL__ */ ++#endif /* __AUFS_DYNOP_H__ */ +diff -Nurp linux-5.4/fs/aufs/export.c linux-5.4-aufs/fs/aufs/export.c +--- linux-5.4/fs/aufs/export.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/export.c 2019-11-28 01:25:59.064925618 +0200 +@@ -0,0 +1,825 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * export via nfs ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "aufs.h" ++ ++union conv { ++#ifdef CONFIG_AUFS_INO_T_64 ++ __u32 a[2]; ++#else ++ __u32 a[1]; ++#endif ++ ino_t ino; ++}; ++ ++static ino_t decode_ino(__u32 *a) ++{ ++ union conv u; ++ ++ BUILD_BUG_ON(sizeof(u.ino) != sizeof(u.a)); ++ u.a[0] = a[0]; ++#ifdef CONFIG_AUFS_INO_T_64 ++ u.a[1] = a[1]; ++#endif ++ return u.ino; ++} ++ ++static void encode_ino(__u32 *a, ino_t ino) ++{ ++ union conv u; ++ ++ u.ino = ino; ++ a[0] = u.a[0]; ++#ifdef CONFIG_AUFS_INO_T_64 ++ a[1] = u.a[1]; ++#endif ++} ++ ++/* NFS file handle */ ++enum { ++ Fh_br_id, ++ Fh_sigen, ++#ifdef CONFIG_AUFS_INO_T_64 ++ /* support 64bit inode number */ ++ Fh_ino1, ++ Fh_ino2, ++ Fh_dir_ino1, ++ Fh_dir_ino2, ++#else ++ Fh_ino1, ++ Fh_dir_ino1, ++#endif ++ Fh_igen, ++ Fh_h_type, ++ Fh_tail, ++ ++ Fh_ino = Fh_ino1, ++ Fh_dir_ino = Fh_dir_ino1 ++}; ++ ++static int au_test_anon(struct dentry *dentry) ++{ ++ /* note: read d_flags without d_lock */ ++ return !!(dentry->d_flags & DCACHE_DISCONNECTED); ++} ++ ++int au_test_nfsd(void) ++{ ++ int ret; ++ struct task_struct *tsk = current; ++ char comm[sizeof(tsk->comm)]; ++ ++ ret = 0; ++ if (tsk->flags & PF_KTHREAD) { ++ get_task_comm(comm, tsk); ++ ret = !strcmp(comm, "nfsd"); ++ } ++ ++ return ret; ++} ++ ++/* ---------------------------------------------------------------------- */ ++/* inode generation external table */ ++ ++void au_xigen_inc(struct inode *inode) ++{ ++ loff_t pos; ++ ssize_t sz; ++ __u32 igen; ++ struct super_block *sb; ++ struct au_sbinfo *sbinfo; ++ ++ sb = inode->i_sb; ++ AuDebugOn(!au_opt_test(au_mntflags(sb), XINO)); ++ ++ sbinfo = au_sbi(sb); ++ pos = inode->i_ino; ++ pos *= sizeof(igen); ++ igen = inode->i_generation + 1; ++ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xigen, &igen, ++ sizeof(igen), &pos); ++ if (sz == sizeof(igen)) ++ return; /* success */ ++ ++ if (unlikely(sz >= 0)) ++ AuIOErr("xigen error (%zd)\n", sz); ++} ++ ++int au_xigen_new(struct inode *inode) ++{ ++ int err; ++ loff_t pos; ++ ssize_t sz; ++ struct super_block *sb; ++ struct au_sbinfo *sbinfo; ++ struct file *file; ++ ++ err = 0; ++ /* todo: dirty, at mount time */ ++ if (inode->i_ino == AUFS_ROOT_INO) ++ goto out; ++ sb = inode->i_sb; ++ SiMustAnyLock(sb); ++ if (unlikely(!au_opt_test(au_mntflags(sb), XINO))) ++ goto out; ++ ++ err = -EFBIG; ++ pos = inode->i_ino; ++ if (unlikely(au_loff_max / sizeof(inode->i_generation) - 1 < pos)) { ++ AuIOErr1("too large i%lld\n", pos); ++ goto out; ++ } ++ pos *= sizeof(inode->i_generation); ++ ++ err = 0; ++ sbinfo = au_sbi(sb); ++ file = sbinfo->si_xigen; ++ BUG_ON(!file); ++ ++ if (vfsub_f_size_read(file) ++ < pos + sizeof(inode->i_generation)) { ++ inode->i_generation = atomic_inc_return(&sbinfo->si_xigen_next); ++ sz = xino_fwrite(sbinfo->si_xwrite, file, &inode->i_generation, ++ sizeof(inode->i_generation), &pos); ++ } else ++ sz = xino_fread(sbinfo->si_xread, file, &inode->i_generation, ++ sizeof(inode->i_generation), &pos); ++ if (sz == sizeof(inode->i_generation)) ++ goto out; /* success */ ++ ++ err = sz; ++ if (unlikely(sz >= 0)) { ++ err = -EIO; ++ AuIOErr("xigen error (%zd)\n", sz); ++ } ++ ++out: ++ return err; ++} ++ ++int au_xigen_set(struct super_block *sb, struct path *path) ++{ ++ int err; ++ struct au_sbinfo *sbinfo; ++ struct file *file; ++ ++ SiMustWriteLock(sb); ++ ++ sbinfo = au_sbi(sb); ++ file = au_xino_create2(sb, path, sbinfo->si_xigen); ++ err = PTR_ERR(file); ++ if (IS_ERR(file)) ++ goto out; ++ err = 0; ++ if (sbinfo->si_xigen) ++ fput(sbinfo->si_xigen); ++ sbinfo->si_xigen = file; ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++void au_xigen_clr(struct super_block *sb) ++{ ++ struct au_sbinfo *sbinfo; ++ ++ SiMustWriteLock(sb); ++ ++ sbinfo = au_sbi(sb); ++ if (sbinfo->si_xigen) { ++ fput(sbinfo->si_xigen); ++ sbinfo->si_xigen = NULL; ++ } ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static struct dentry *decode_by_ino(struct super_block *sb, ino_t ino, ++ ino_t dir_ino) ++{ ++ struct dentry *dentry, *d; ++ struct inode *inode; ++ unsigned int sigen; ++ ++ dentry = NULL; ++ inode = ilookup(sb, ino); ++ if (!inode) ++ goto out; ++ ++ dentry = ERR_PTR(-ESTALE); ++ sigen = au_sigen(sb); ++ if (unlikely(au_is_bad_inode(inode) ++ || IS_DEADDIR(inode) ++ || sigen != au_iigen(inode, NULL))) ++ goto out_iput; ++ ++ dentry = NULL; ++ if (!dir_ino || S_ISDIR(inode->i_mode)) ++ dentry = d_find_alias(inode); ++ else { ++ spin_lock(&inode->i_lock); ++ hlist_for_each_entry(d, &inode->i_dentry, d_u.d_alias) { ++ spin_lock(&d->d_lock); ++ if (!au_test_anon(d) ++ && d_inode(d->d_parent)->i_ino == dir_ino) { ++ dentry = dget_dlock(d); ++ spin_unlock(&d->d_lock); ++ break; ++ } ++ spin_unlock(&d->d_lock); ++ } ++ spin_unlock(&inode->i_lock); ++ } ++ if (unlikely(dentry && au_digen_test(dentry, sigen))) { ++ /* need to refresh */ ++ dput(dentry); ++ dentry = NULL; ++ } ++ ++out_iput: ++ iput(inode); ++out: ++ AuTraceErrPtr(dentry); ++ return dentry; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* todo: dirty? */ ++/* if exportfs_decode_fh() passed vfsmount*, we could be happy */ ++ ++struct au_compare_mnt_args { ++ /* input */ ++ struct super_block *sb; ++ ++ /* output */ ++ struct vfsmount *mnt; ++}; ++ ++static int au_compare_mnt(struct vfsmount *mnt, void *arg) ++{ ++ struct au_compare_mnt_args *a = arg; ++ ++ if (mnt->mnt_sb != a->sb) ++ return 0; ++ a->mnt = mntget(mnt); ++ return 1; ++} ++ ++static struct vfsmount *au_mnt_get(struct super_block *sb) ++{ ++ int err; ++ struct path root; ++ struct au_compare_mnt_args args = { ++ .sb = sb ++ }; ++ ++ get_fs_root(current->fs, &root); ++ rcu_read_lock(); ++ err = iterate_mounts(au_compare_mnt, &args, root.mnt); ++ rcu_read_unlock(); ++ path_put(&root); ++ AuDebugOn(!err); ++ AuDebugOn(!args.mnt); ++ return args.mnt; ++} ++ ++struct au_nfsd_si_lock { ++ unsigned int sigen; ++ aufs_bindex_t bindex, br_id; ++ unsigned char force_lock; ++}; ++ ++static int si_nfsd_read_lock(struct super_block *sb, ++ struct au_nfsd_si_lock *nsi_lock) ++{ ++ int err; ++ aufs_bindex_t bindex; ++ ++ si_read_lock(sb, AuLock_FLUSH); ++ ++ /* branch id may be wrapped around */ ++ err = 0; ++ bindex = au_br_index(sb, nsi_lock->br_id); ++ if (bindex >= 0 && nsi_lock->sigen + AUFS_BRANCH_MAX > au_sigen(sb)) ++ goto out; /* success */ ++ ++ err = -ESTALE; ++ bindex = -1; ++ if (!nsi_lock->force_lock) ++ si_read_unlock(sb); ++ ++out: ++ nsi_lock->bindex = bindex; ++ return err; ++} ++ ++struct find_name_by_ino { ++ struct dir_context ctx; ++ int called, found; ++ ino_t ino; ++ char *name; ++ int namelen; ++}; ++ ++static int ++find_name_by_ino(struct dir_context *ctx, const char *name, int namelen, ++ loff_t offset, u64 ino, unsigned int d_type) ++{ ++ struct find_name_by_ino *a = container_of(ctx, struct find_name_by_ino, ++ ctx); ++ ++ a->called++; ++ if (a->ino != ino) ++ return 0; ++ ++ memcpy(a->name, name, namelen); ++ a->namelen = namelen; ++ a->found = 1; ++ return 1; ++} ++ ++static struct dentry *au_lkup_by_ino(struct path *path, ino_t ino, ++ struct au_nfsd_si_lock *nsi_lock) ++{ ++ struct dentry *dentry, *parent; ++ struct file *file; ++ struct inode *dir; ++ struct find_name_by_ino arg = { ++ .ctx = { ++ .actor = find_name_by_ino ++ } ++ }; ++ int err; ++ ++ parent = path->dentry; ++ if (nsi_lock) ++ si_read_unlock(parent->d_sb); ++ file = vfsub_dentry_open(path, au_dir_roflags); ++ dentry = (void *)file; ++ if (IS_ERR(file)) ++ goto out; ++ ++ dentry = ERR_PTR(-ENOMEM); ++ arg.name = (void *)__get_free_page(GFP_NOFS); ++ if (unlikely(!arg.name)) ++ goto out_file; ++ arg.ino = ino; ++ arg.found = 0; ++ do { ++ arg.called = 0; ++ /* smp_mb(); */ ++ err = vfsub_iterate_dir(file, &arg.ctx); ++ } while (!err && !arg.found && arg.called); ++ dentry = ERR_PTR(err); ++ if (unlikely(err)) ++ goto out_name; ++ /* instead of ENOENT */ ++ dentry = ERR_PTR(-ESTALE); ++ if (!arg.found) ++ goto out_name; ++ ++ /* do not call vfsub_lkup_one() */ ++ dir = d_inode(parent); ++ dentry = vfsub_lookup_one_len_unlocked(arg.name, parent, arg.namelen); ++ AuTraceErrPtr(dentry); ++ if (IS_ERR(dentry)) ++ goto out_name; ++ AuDebugOn(au_test_anon(dentry)); ++ if (unlikely(d_really_is_negative(dentry))) { ++ dput(dentry); ++ dentry = ERR_PTR(-ENOENT); ++ } ++ ++out_name: ++ free_page((unsigned long)arg.name); ++out_file: ++ fput(file); ++out: ++ if (unlikely(nsi_lock ++ && si_nfsd_read_lock(parent->d_sb, nsi_lock) < 0)) ++ if (!IS_ERR(dentry)) { ++ dput(dentry); ++ dentry = ERR_PTR(-ESTALE); ++ } ++ AuTraceErrPtr(dentry); ++ return dentry; ++} ++ ++static struct dentry *decode_by_dir_ino(struct super_block *sb, ino_t ino, ++ ino_t dir_ino, ++ struct au_nfsd_si_lock *nsi_lock) ++{ ++ struct dentry *dentry; ++ struct path path; ++ ++ if (dir_ino != AUFS_ROOT_INO) { ++ path.dentry = decode_by_ino(sb, dir_ino, 0); ++ dentry = path.dentry; ++ if (!path.dentry || IS_ERR(path.dentry)) ++ goto out; ++ AuDebugOn(au_test_anon(path.dentry)); ++ } else ++ path.dentry = dget(sb->s_root); ++ ++ path.mnt = au_mnt_get(sb); ++ dentry = au_lkup_by_ino(&path, ino, nsi_lock); ++ path_put(&path); ++ ++out: ++ AuTraceErrPtr(dentry); ++ return dentry; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int h_acceptable(void *expv, struct dentry *dentry) ++{ ++ return 1; ++} ++ ++static char *au_build_path(struct dentry *h_parent, struct path *h_rootpath, ++ char *buf, int len, struct super_block *sb) ++{ ++ char *p; ++ int n; ++ struct path path; ++ ++ p = d_path(h_rootpath, buf, len); ++ if (IS_ERR(p)) ++ goto out; ++ n = strlen(p); ++ ++ path.mnt = h_rootpath->mnt; ++ path.dentry = h_parent; ++ p = d_path(&path, buf, len); ++ if (IS_ERR(p)) ++ goto out; ++ if (n != 1) ++ p += n; ++ ++ path.mnt = au_mnt_get(sb); ++ path.dentry = sb->s_root; ++ p = d_path(&path, buf, len - strlen(p)); ++ mntput(path.mnt); ++ if (IS_ERR(p)) ++ goto out; ++ if (n != 1) ++ p[strlen(p)] = '/'; ++ ++out: ++ AuTraceErrPtr(p); ++ return p; ++} ++ ++static ++struct dentry *decode_by_path(struct super_block *sb, ino_t ino, __u32 *fh, ++ int fh_len, struct au_nfsd_si_lock *nsi_lock) ++{ ++ struct dentry *dentry, *h_parent, *root; ++ struct super_block *h_sb; ++ char *pathname, *p; ++ struct vfsmount *h_mnt; ++ struct au_branch *br; ++ int err; ++ struct path path; ++ ++ br = au_sbr(sb, nsi_lock->bindex); ++ h_mnt = au_br_mnt(br); ++ h_sb = h_mnt->mnt_sb; ++ /* todo: call lower fh_to_dentry()? fh_to_parent()? */ ++ lockdep_off(); ++ h_parent = exportfs_decode_fh(h_mnt, (void *)(fh + Fh_tail), ++ fh_len - Fh_tail, fh[Fh_h_type], ++ h_acceptable, /*context*/NULL); ++ lockdep_on(); ++ dentry = h_parent; ++ if (unlikely(!h_parent || IS_ERR(h_parent))) { ++ AuWarn1("%s decode_fh failed, %ld\n", ++ au_sbtype(h_sb), PTR_ERR(h_parent)); ++ goto out; ++ } ++ dentry = NULL; ++ if (unlikely(au_test_anon(h_parent))) { ++ AuWarn1("%s decode_fh returned a disconnected dentry\n", ++ au_sbtype(h_sb)); ++ goto out_h_parent; ++ } ++ ++ dentry = ERR_PTR(-ENOMEM); ++ pathname = (void *)__get_free_page(GFP_NOFS); ++ if (unlikely(!pathname)) ++ goto out_h_parent; ++ ++ root = sb->s_root; ++ path.mnt = h_mnt; ++ di_read_lock_parent(root, !AuLock_IR); ++ path.dentry = au_h_dptr(root, nsi_lock->bindex); ++ di_read_unlock(root, !AuLock_IR); ++ p = au_build_path(h_parent, &path, pathname, PAGE_SIZE, sb); ++ dentry = (void *)p; ++ if (IS_ERR(p)) ++ goto out_pathname; ++ ++ si_read_unlock(sb); ++ err = vfsub_kern_path(p, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path); ++ dentry = ERR_PTR(err); ++ if (unlikely(err)) ++ goto out_relock; ++ ++ dentry = ERR_PTR(-ENOENT); ++ AuDebugOn(au_test_anon(path.dentry)); ++ if (unlikely(d_really_is_negative(path.dentry))) ++ goto out_path; ++ ++ if (ino != d_inode(path.dentry)->i_ino) ++ dentry = au_lkup_by_ino(&path, ino, /*nsi_lock*/NULL); ++ else ++ dentry = dget(path.dentry); ++ ++out_path: ++ path_put(&path); ++out_relock: ++ if (unlikely(si_nfsd_read_lock(sb, nsi_lock) < 0)) ++ if (!IS_ERR(dentry)) { ++ dput(dentry); ++ dentry = ERR_PTR(-ESTALE); ++ } ++out_pathname: ++ free_page((unsigned long)pathname); ++out_h_parent: ++ dput(h_parent); ++out: ++ AuTraceErrPtr(dentry); ++ return dentry; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static struct dentry * ++aufs_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len, ++ int fh_type) ++{ ++ struct dentry *dentry; ++ __u32 *fh = fid->raw; ++ struct au_branch *br; ++ ino_t ino, dir_ino; ++ struct au_nfsd_si_lock nsi_lock = { ++ .force_lock = 0 ++ }; ++ ++ dentry = ERR_PTR(-ESTALE); ++ /* it should never happen, but the file handle is unreliable */ ++ if (unlikely(fh_len < Fh_tail)) ++ goto out; ++ nsi_lock.sigen = fh[Fh_sigen]; ++ nsi_lock.br_id = fh[Fh_br_id]; ++ ++ /* branch id may be wrapped around */ ++ br = NULL; ++ if (unlikely(si_nfsd_read_lock(sb, &nsi_lock))) ++ goto out; ++ nsi_lock.force_lock = 1; ++ ++ /* is this inode still cached? */ ++ ino = decode_ino(fh + Fh_ino); ++ /* it should never happen */ ++ if (unlikely(ino == AUFS_ROOT_INO)) ++ goto out_unlock; ++ ++ dir_ino = decode_ino(fh + Fh_dir_ino); ++ dentry = decode_by_ino(sb, ino, dir_ino); ++ if (IS_ERR(dentry)) ++ goto out_unlock; ++ if (dentry) ++ goto accept; ++ ++ /* is the parent dir cached? */ ++ br = au_sbr(sb, nsi_lock.bindex); ++ au_lcnt_inc(&br->br_nfiles); ++ dentry = decode_by_dir_ino(sb, ino, dir_ino, &nsi_lock); ++ if (IS_ERR(dentry)) ++ goto out_unlock; ++ if (dentry) ++ goto accept; ++ ++ /* lookup path */ ++ dentry = decode_by_path(sb, ino, fh, fh_len, &nsi_lock); ++ if (IS_ERR(dentry)) ++ goto out_unlock; ++ if (unlikely(!dentry)) ++ /* todo?: make it ESTALE */ ++ goto out_unlock; ++ ++accept: ++ if (!au_digen_test(dentry, au_sigen(sb)) ++ && d_inode(dentry)->i_generation == fh[Fh_igen]) ++ goto out_unlock; /* success */ ++ ++ dput(dentry); ++ dentry = ERR_PTR(-ESTALE); ++out_unlock: ++ if (br) ++ au_lcnt_dec(&br->br_nfiles); ++ si_read_unlock(sb); ++out: ++ AuTraceErrPtr(dentry); ++ return dentry; ++} ++ ++#if 0 /* reserved for future use */ ++/* support subtreecheck option */ ++static struct dentry *aufs_fh_to_parent(struct super_block *sb, struct fid *fid, ++ int fh_len, int fh_type) ++{ ++ struct dentry *parent; ++ __u32 *fh = fid->raw; ++ ino_t dir_ino; ++ ++ dir_ino = decode_ino(fh + Fh_dir_ino); ++ parent = decode_by_ino(sb, dir_ino, 0); ++ if (IS_ERR(parent)) ++ goto out; ++ if (!parent) ++ parent = decode_by_path(sb, au_br_index(sb, fh[Fh_br_id]), ++ dir_ino, fh, fh_len); ++ ++out: ++ AuTraceErrPtr(parent); ++ return parent; ++} ++#endif ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int aufs_encode_fh(struct inode *inode, __u32 *fh, int *max_len, ++ struct inode *dir) ++{ ++ int err; ++ aufs_bindex_t bindex; ++ struct super_block *sb, *h_sb; ++ struct dentry *dentry, *parent, *h_parent; ++ struct inode *h_dir; ++ struct au_branch *br; ++ ++ err = -ENOSPC; ++ if (unlikely(*max_len <= Fh_tail)) { ++ AuWarn1("NFSv2 client (max_len %d)?\n", *max_len); ++ goto out; ++ } ++ ++ err = FILEID_ROOT; ++ if (inode->i_ino == AUFS_ROOT_INO) { ++ AuDebugOn(inode->i_ino != AUFS_ROOT_INO); ++ goto out; ++ } ++ ++ h_parent = NULL; ++ sb = inode->i_sb; ++ err = si_read_lock(sb, AuLock_FLUSH); ++ if (unlikely(err)) ++ goto out; ++ ++#ifdef CONFIG_AUFS_DEBUG ++ if (unlikely(!au_opt_test(au_mntflags(sb), XINO))) ++ AuWarn1("NFS-exporting requires xino\n"); ++#endif ++ err = -EIO; ++ parent = NULL; ++ ii_read_lock_child(inode); ++ bindex = au_ibtop(inode); ++ if (!dir) { ++ dentry = d_find_any_alias(inode); ++ if (unlikely(!dentry)) ++ goto out_unlock; ++ AuDebugOn(au_test_anon(dentry)); ++ parent = dget_parent(dentry); ++ dput(dentry); ++ if (unlikely(!parent)) ++ goto out_unlock; ++ if (d_really_is_positive(parent)) ++ dir = d_inode(parent); ++ } ++ ++ ii_read_lock_parent(dir); ++ h_dir = au_h_iptr(dir, bindex); ++ ii_read_unlock(dir); ++ if (unlikely(!h_dir)) ++ goto out_parent; ++ h_parent = d_find_any_alias(h_dir); ++ if (unlikely(!h_parent)) ++ goto out_hparent; ++ ++ err = -EPERM; ++ br = au_sbr(sb, bindex); ++ h_sb = au_br_sb(br); ++ if (unlikely(!h_sb->s_export_op)) { ++ AuErr1("%s branch is not exportable\n", au_sbtype(h_sb)); ++ goto out_hparent; ++ } ++ ++ fh[Fh_br_id] = br->br_id; ++ fh[Fh_sigen] = au_sigen(sb); ++ encode_ino(fh + Fh_ino, inode->i_ino); ++ encode_ino(fh + Fh_dir_ino, dir->i_ino); ++ fh[Fh_igen] = inode->i_generation; ++ ++ *max_len -= Fh_tail; ++ fh[Fh_h_type] = exportfs_encode_fh(h_parent, (void *)(fh + Fh_tail), ++ max_len, ++ /*connectable or subtreecheck*/0); ++ err = fh[Fh_h_type]; ++ *max_len += Fh_tail; ++ /* todo: macros? */ ++ if (err != FILEID_INVALID) ++ err = 99; ++ else ++ AuWarn1("%s encode_fh failed\n", au_sbtype(h_sb)); ++ ++out_hparent: ++ dput(h_parent); ++out_parent: ++ dput(parent); ++out_unlock: ++ ii_read_unlock(inode); ++ si_read_unlock(sb); ++out: ++ if (unlikely(err < 0)) ++ err = FILEID_INVALID; ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int aufs_commit_metadata(struct inode *inode) ++{ ++ int err; ++ aufs_bindex_t bindex; ++ struct super_block *sb; ++ struct inode *h_inode; ++ int (*f)(struct inode *inode); ++ ++ sb = inode->i_sb; ++ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); ++ ii_write_lock_child(inode); ++ bindex = au_ibtop(inode); ++ AuDebugOn(bindex < 0); ++ h_inode = au_h_iptr(inode, bindex); ++ ++ f = h_inode->i_sb->s_export_op->commit_metadata; ++ if (f) ++ err = f(h_inode); ++ else { ++ struct writeback_control wbc = { ++ .sync_mode = WB_SYNC_ALL, ++ .nr_to_write = 0 /* metadata only */ ++ }; ++ ++ err = sync_inode(h_inode, &wbc); ++ } ++ ++ au_cpup_attr_timesizes(inode); ++ ii_write_unlock(inode); ++ si_read_unlock(sb); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static struct export_operations aufs_export_op = { ++ .fh_to_dentry = aufs_fh_to_dentry, ++ /* .fh_to_parent = aufs_fh_to_parent, */ ++ .encode_fh = aufs_encode_fh, ++ .commit_metadata = aufs_commit_metadata ++}; ++ ++void au_export_init(struct super_block *sb) ++{ ++ struct au_sbinfo *sbinfo; ++ __u32 u; ++ ++ BUILD_BUG_ON_MSG(IS_BUILTIN(CONFIG_AUFS_FS) ++ && IS_MODULE(CONFIG_EXPORTFS), ++ AUFS_NAME ": unsupported configuration " ++ "CONFIG_EXPORTFS=m and CONFIG_AUFS_FS=y"); ++ ++ sb->s_export_op = &aufs_export_op; ++ sbinfo = au_sbi(sb); ++ sbinfo->si_xigen = NULL; ++ get_random_bytes(&u, sizeof(u)); ++ BUILD_BUG_ON(sizeof(u) != sizeof(int)); ++ atomic_set(&sbinfo->si_xigen_next, u); ++} +diff -Nurp linux-5.4/fs/aufs/fhsm.c linux-5.4-aufs/fs/aufs/fhsm.c +--- linux-5.4/fs/aufs/fhsm.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/fhsm.c 2019-11-28 01:25:59.064925618 +0200 +@@ -0,0 +1,413 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2011-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * File-based Hierarchy Storage Management ++ */ ++ ++#include ++#include ++#include ++#include ++#include "aufs.h" ++ ++static aufs_bindex_t au_fhsm_bottom(struct super_block *sb) ++{ ++ struct au_sbinfo *sbinfo; ++ struct au_fhsm *fhsm; ++ ++ SiMustAnyLock(sb); ++ ++ sbinfo = au_sbi(sb); ++ fhsm = &sbinfo->si_fhsm; ++ AuDebugOn(!fhsm); ++ return fhsm->fhsm_bottom; ++} ++ ++void au_fhsm_set_bottom(struct super_block *sb, aufs_bindex_t bindex) ++{ ++ struct au_sbinfo *sbinfo; ++ struct au_fhsm *fhsm; ++ ++ SiMustWriteLock(sb); ++ ++ sbinfo = au_sbi(sb); ++ fhsm = &sbinfo->si_fhsm; ++ AuDebugOn(!fhsm); ++ fhsm->fhsm_bottom = bindex; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int au_fhsm_test_jiffy(struct au_sbinfo *sbinfo, struct au_branch *br) ++{ ++ struct au_br_fhsm *bf; ++ ++ bf = br->br_fhsm; ++ MtxMustLock(&bf->bf_lock); ++ ++ return !bf->bf_readable ++ || time_after(jiffies, ++ bf->bf_jiffy + sbinfo->si_fhsm.fhsm_expire); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static void au_fhsm_notify(struct super_block *sb, int val) ++{ ++ struct au_sbinfo *sbinfo; ++ struct au_fhsm *fhsm; ++ ++ SiMustAnyLock(sb); ++ ++ sbinfo = au_sbi(sb); ++ fhsm = &sbinfo->si_fhsm; ++ if (au_fhsm_pid(fhsm) ++ && atomic_read(&fhsm->fhsm_readable) != -1) { ++ atomic_set(&fhsm->fhsm_readable, val); ++ if (val) ++ wake_up(&fhsm->fhsm_wqh); ++ } ++} ++ ++static int au_fhsm_stfs(struct super_block *sb, aufs_bindex_t bindex, ++ struct aufs_stfs *rstfs, int do_lock, int do_notify) ++{ ++ int err; ++ struct au_branch *br; ++ struct au_br_fhsm *bf; ++ ++ br = au_sbr(sb, bindex); ++ AuDebugOn(au_br_rdonly(br)); ++ bf = br->br_fhsm; ++ AuDebugOn(!bf); ++ ++ if (do_lock) ++ mutex_lock(&bf->bf_lock); ++ else ++ MtxMustLock(&bf->bf_lock); ++ ++ /* sb->s_root for NFS is unreliable */ ++ err = au_br_stfs(br, &bf->bf_stfs); ++ if (unlikely(err)) { ++ AuErr1("FHSM failed (%d), b%d, ignored.\n", bindex, err); ++ goto out; ++ } ++ ++ bf->bf_jiffy = jiffies; ++ bf->bf_readable = 1; ++ if (do_notify) ++ au_fhsm_notify(sb, /*val*/1); ++ if (rstfs) ++ *rstfs = bf->bf_stfs; ++ ++out: ++ if (do_lock) ++ mutex_unlock(&bf->bf_lock); ++ au_fhsm_notify(sb, /*val*/1); ++ ++ return err; ++} ++ ++void au_fhsm_wrote(struct super_block *sb, aufs_bindex_t bindex, int force) ++{ ++ int err; ++ struct au_sbinfo *sbinfo; ++ struct au_fhsm *fhsm; ++ struct au_branch *br; ++ struct au_br_fhsm *bf; ++ ++ AuDbg("b%d, force %d\n", bindex, force); ++ SiMustAnyLock(sb); ++ ++ sbinfo = au_sbi(sb); ++ fhsm = &sbinfo->si_fhsm; ++ if (!au_ftest_si(sbinfo, FHSM) ++ || fhsm->fhsm_bottom == bindex) ++ return; ++ ++ br = au_sbr(sb, bindex); ++ bf = br->br_fhsm; ++ AuDebugOn(!bf); ++ mutex_lock(&bf->bf_lock); ++ if (force ++ || au_fhsm_pid(fhsm) ++ || au_fhsm_test_jiffy(sbinfo, br)) ++ err = au_fhsm_stfs(sb, bindex, /*rstfs*/NULL, /*do_lock*/0, ++ /*do_notify*/1); ++ mutex_unlock(&bf->bf_lock); ++} ++ ++void au_fhsm_wrote_all(struct super_block *sb, int force) ++{ ++ aufs_bindex_t bindex, bbot; ++ struct au_branch *br; ++ ++ /* exclude the bottom */ ++ bbot = au_fhsm_bottom(sb); ++ for (bindex = 0; bindex < bbot; bindex++) { ++ br = au_sbr(sb, bindex); ++ if (au_br_fhsm(br->br_perm)) ++ au_fhsm_wrote(sb, bindex, force); ++ } ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static __poll_t au_fhsm_poll(struct file *file, struct poll_table_struct *wait) ++{ ++ __poll_t mask; ++ struct au_sbinfo *sbinfo; ++ struct au_fhsm *fhsm; ++ ++ mask = 0; ++ sbinfo = file->private_data; ++ fhsm = &sbinfo->si_fhsm; ++ poll_wait(file, &fhsm->fhsm_wqh, wait); ++ if (atomic_read(&fhsm->fhsm_readable)) ++ mask = EPOLLIN /* | EPOLLRDNORM */; ++ ++ if (!mask) ++ AuDbg("mask 0x%x\n", mask); ++ return mask; ++} ++ ++static int au_fhsm_do_read_one(struct aufs_stbr __user *stbr, ++ struct aufs_stfs *stfs, __s16 brid) ++{ ++ int err; ++ ++ err = copy_to_user(&stbr->stfs, stfs, sizeof(*stfs)); ++ if (!err) ++ err = __put_user(brid, &stbr->brid); ++ if (unlikely(err)) ++ err = -EFAULT; ++ ++ return err; ++} ++ ++static ssize_t au_fhsm_do_read(struct super_block *sb, ++ struct aufs_stbr __user *stbr, size_t count) ++{ ++ ssize_t err; ++ int nstbr; ++ aufs_bindex_t bindex, bbot; ++ struct au_branch *br; ++ struct au_br_fhsm *bf; ++ ++ /* except the bottom branch */ ++ err = 0; ++ nstbr = 0; ++ bbot = au_fhsm_bottom(sb); ++ for (bindex = 0; !err && bindex < bbot; bindex++) { ++ br = au_sbr(sb, bindex); ++ if (!au_br_fhsm(br->br_perm)) ++ continue; ++ ++ bf = br->br_fhsm; ++ mutex_lock(&bf->bf_lock); ++ if (bf->bf_readable) { ++ err = -EFAULT; ++ if (count >= sizeof(*stbr)) ++ err = au_fhsm_do_read_one(stbr++, &bf->bf_stfs, ++ br->br_id); ++ if (!err) { ++ bf->bf_readable = 0; ++ count -= sizeof(*stbr); ++ nstbr++; ++ } ++ } ++ mutex_unlock(&bf->bf_lock); ++ } ++ if (!err) ++ err = sizeof(*stbr) * nstbr; ++ ++ return err; ++} ++ ++static ssize_t au_fhsm_read(struct file *file, char __user *buf, size_t count, ++ loff_t *pos) ++{ ++ ssize_t err; ++ int readable; ++ aufs_bindex_t nfhsm, bindex, bbot; ++ struct au_sbinfo *sbinfo; ++ struct au_fhsm *fhsm; ++ struct au_branch *br; ++ struct super_block *sb; ++ ++ err = 0; ++ sbinfo = file->private_data; ++ fhsm = &sbinfo->si_fhsm; ++need_data: ++ spin_lock_irq(&fhsm->fhsm_wqh.lock); ++ if (!atomic_read(&fhsm->fhsm_readable)) { ++ if (vfsub_file_flags(file) & O_NONBLOCK) ++ err = -EAGAIN; ++ else ++ err = wait_event_interruptible_locked_irq ++ (fhsm->fhsm_wqh, ++ atomic_read(&fhsm->fhsm_readable)); ++ } ++ spin_unlock_irq(&fhsm->fhsm_wqh.lock); ++ if (unlikely(err)) ++ goto out; ++ ++ /* sb may already be dead */ ++ au_rw_read_lock(&sbinfo->si_rwsem); ++ readable = atomic_read(&fhsm->fhsm_readable); ++ if (readable > 0) { ++ sb = sbinfo->si_sb; ++ AuDebugOn(!sb); ++ /* exclude the bottom branch */ ++ nfhsm = 0; ++ bbot = au_fhsm_bottom(sb); ++ for (bindex = 0; bindex < bbot; bindex++) { ++ br = au_sbr(sb, bindex); ++ if (au_br_fhsm(br->br_perm)) ++ nfhsm++; ++ } ++ err = -EMSGSIZE; ++ if (nfhsm * sizeof(struct aufs_stbr) <= count) { ++ atomic_set(&fhsm->fhsm_readable, 0); ++ err = au_fhsm_do_read(sbinfo->si_sb, (void __user *)buf, ++ count); ++ } ++ } ++ au_rw_read_unlock(&sbinfo->si_rwsem); ++ if (!readable) ++ goto need_data; ++ ++out: ++ return err; ++} ++ ++static int au_fhsm_release(struct inode *inode, struct file *file) ++{ ++ struct au_sbinfo *sbinfo; ++ struct au_fhsm *fhsm; ++ ++ /* sb may already be dead */ ++ sbinfo = file->private_data; ++ fhsm = &sbinfo->si_fhsm; ++ spin_lock(&fhsm->fhsm_spin); ++ fhsm->fhsm_pid = 0; ++ spin_unlock(&fhsm->fhsm_spin); ++ kobject_put(&sbinfo->si_kobj); ++ ++ return 0; ++} ++ ++static const struct file_operations au_fhsm_fops = { ++ .owner = THIS_MODULE, ++ .llseek = noop_llseek, ++ .read = au_fhsm_read, ++ .poll = au_fhsm_poll, ++ .release = au_fhsm_release ++}; ++ ++int au_fhsm_fd(struct super_block *sb, int oflags) ++{ ++ int err, fd; ++ struct au_sbinfo *sbinfo; ++ struct au_fhsm *fhsm; ++ ++ err = -EPERM; ++ if (unlikely(!capable(CAP_SYS_ADMIN))) ++ goto out; ++ ++ err = -EINVAL; ++ if (unlikely(oflags & ~(O_CLOEXEC | O_NONBLOCK))) ++ goto out; ++ ++ err = 0; ++ sbinfo = au_sbi(sb); ++ fhsm = &sbinfo->si_fhsm; ++ spin_lock(&fhsm->fhsm_spin); ++ if (!fhsm->fhsm_pid) ++ fhsm->fhsm_pid = current->pid; ++ else ++ err = -EBUSY; ++ spin_unlock(&fhsm->fhsm_spin); ++ if (unlikely(err)) ++ goto out; ++ ++ oflags |= O_RDONLY; ++ /* oflags |= FMODE_NONOTIFY; */ ++ fd = anon_inode_getfd("[aufs_fhsm]", &au_fhsm_fops, sbinfo, oflags); ++ err = fd; ++ if (unlikely(fd < 0)) ++ goto out_pid; ++ ++ /* succeed regardless 'fhsm' status */ ++ kobject_get(&sbinfo->si_kobj); ++ si_noflush_read_lock(sb); ++ if (au_ftest_si(sbinfo, FHSM)) ++ au_fhsm_wrote_all(sb, /*force*/0); ++ si_read_unlock(sb); ++ goto out; /* success */ ++ ++out_pid: ++ spin_lock(&fhsm->fhsm_spin); ++ fhsm->fhsm_pid = 0; ++ spin_unlock(&fhsm->fhsm_spin); ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++int au_fhsm_br_alloc(struct au_branch *br) ++{ ++ int err; ++ ++ err = 0; ++ br->br_fhsm = kmalloc(sizeof(*br->br_fhsm), GFP_NOFS); ++ if (br->br_fhsm) ++ au_br_fhsm_init(br->br_fhsm); ++ else ++ err = -ENOMEM; ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++void au_fhsm_fin(struct super_block *sb) ++{ ++ au_fhsm_notify(sb, /*val*/-1); ++} ++ ++void au_fhsm_init(struct au_sbinfo *sbinfo) ++{ ++ struct au_fhsm *fhsm; ++ ++ fhsm = &sbinfo->si_fhsm; ++ spin_lock_init(&fhsm->fhsm_spin); ++ init_waitqueue_head(&fhsm->fhsm_wqh); ++ atomic_set(&fhsm->fhsm_readable, 0); ++ fhsm->fhsm_expire ++ = msecs_to_jiffies(AUFS_FHSM_CACHE_DEF_SEC * MSEC_PER_SEC); ++ fhsm->fhsm_bottom = -1; ++} ++ ++void au_fhsm_set(struct au_sbinfo *sbinfo, unsigned int sec) ++{ ++ sbinfo->si_fhsm.fhsm_expire ++ = msecs_to_jiffies(sec * MSEC_PER_SEC); ++} ++ ++void au_fhsm_show(struct seq_file *seq, struct au_sbinfo *sbinfo) ++{ ++ unsigned int u; ++ ++ if (!au_ftest_si(sbinfo, FHSM)) ++ return; ++ ++ u = jiffies_to_msecs(sbinfo->si_fhsm.fhsm_expire) / MSEC_PER_SEC; ++ if (u != AUFS_FHSM_CACHE_DEF_SEC) ++ seq_printf(seq, ",fhsm_sec=%u", u); ++} +diff -Nurp linux-5.4/fs/aufs/file.c linux-5.4-aufs/fs/aufs/file.c +--- linux-5.4/fs/aufs/file.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/file.c 2019-11-28 01:25:59.065925618 +0200 +@@ -0,0 +1,850 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * handling file/dir, and address_space operation ++ */ ++ ++#ifdef CONFIG_AUFS_DEBUG ++#include ++#endif ++#include ++#include "aufs.h" ++ ++/* drop flags for writing */ ++unsigned int au_file_roflags(unsigned int flags) ++{ ++ flags &= ~(O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_TRUNC); ++ flags |= O_RDONLY | O_NOATIME; ++ return flags; ++} ++ ++/* common functions to regular file and dir */ ++struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags, ++ struct file *file, int force_wr) ++{ ++ struct file *h_file; ++ struct dentry *h_dentry; ++ struct inode *h_inode; ++ struct super_block *sb; ++ struct au_branch *br; ++ struct path h_path; ++ int err; ++ ++ /* a race condition can happen between open and unlink/rmdir */ ++ h_file = ERR_PTR(-ENOENT); ++ h_dentry = au_h_dptr(dentry, bindex); ++ if (au_test_nfsd() && (!h_dentry || d_is_negative(h_dentry))) ++ goto out; ++ h_inode = d_inode(h_dentry); ++ spin_lock(&h_dentry->d_lock); ++ err = (!d_unhashed(dentry) && d_unlinked(h_dentry)) ++ /* || !d_inode(dentry)->i_nlink */ ++ ; ++ spin_unlock(&h_dentry->d_lock); ++ if (unlikely(err)) ++ goto out; ++ ++ sb = dentry->d_sb; ++ br = au_sbr(sb, bindex); ++ err = au_br_test_oflag(flags, br); ++ h_file = ERR_PTR(err); ++ if (unlikely(err)) ++ goto out; ++ ++ /* drop flags for writing */ ++ if (au_test_ro(sb, bindex, d_inode(dentry))) { ++ if (force_wr && !(flags & O_WRONLY)) ++ force_wr = 0; ++ flags = au_file_roflags(flags); ++ if (force_wr) { ++ h_file = ERR_PTR(-EROFS); ++ flags = au_file_roflags(flags); ++ if (unlikely(vfsub_native_ro(h_inode) ++ || IS_APPEND(h_inode))) ++ goto out; ++ flags &= ~O_ACCMODE; ++ flags |= O_WRONLY; ++ } ++ } ++ flags &= ~O_CREAT; ++ au_lcnt_inc(&br->br_nfiles); ++ h_path.dentry = h_dentry; ++ h_path.mnt = au_br_mnt(br); ++ h_file = vfsub_dentry_open(&h_path, flags); ++ if (IS_ERR(h_file)) ++ goto out_br; ++ ++ if (flags & __FMODE_EXEC) { ++ err = deny_write_access(h_file); ++ if (unlikely(err)) { ++ fput(h_file); ++ h_file = ERR_PTR(err); ++ goto out_br; ++ } ++ } ++ fsnotify_open(h_file); ++ goto out; /* success */ ++ ++out_br: ++ au_lcnt_dec(&br->br_nfiles); ++out: ++ return h_file; ++} ++ ++static int au_cmoo(struct dentry *dentry) ++{ ++ int err, cmoo, matched; ++ unsigned int udba; ++ struct path h_path; ++ struct au_pin pin; ++ struct au_cp_generic cpg = { ++ .dentry = dentry, ++ .bdst = -1, ++ .bsrc = -1, ++ .len = -1, ++ .pin = &pin, ++ .flags = AuCpup_DTIME | AuCpup_HOPEN ++ }; ++ struct inode *delegated; ++ struct super_block *sb; ++ struct au_sbinfo *sbinfo; ++ struct au_fhsm *fhsm; ++ pid_t pid; ++ struct au_branch *br; ++ struct dentry *parent; ++ struct au_hinode *hdir; ++ ++ DiMustWriteLock(dentry); ++ IiMustWriteLock(d_inode(dentry)); ++ ++ err = 0; ++ if (IS_ROOT(dentry)) ++ goto out; ++ cpg.bsrc = au_dbtop(dentry); ++ if (!cpg.bsrc) ++ goto out; ++ ++ sb = dentry->d_sb; ++ sbinfo = au_sbi(sb); ++ fhsm = &sbinfo->si_fhsm; ++ pid = au_fhsm_pid(fhsm); ++ rcu_read_lock(); ++ matched = (pid ++ && (current->pid == pid ++ || rcu_dereference(current->real_parent)->pid == pid)); ++ rcu_read_unlock(); ++ if (matched) ++ goto out; ++ ++ br = au_sbr(sb, cpg.bsrc); ++ cmoo = au_br_cmoo(br->br_perm); ++ if (!cmoo) ++ goto out; ++ if (!d_is_reg(dentry)) ++ cmoo &= AuBrAttr_COO_ALL; ++ if (!cmoo) ++ goto out; ++ ++ parent = dget_parent(dentry); ++ di_write_lock_parent(parent); ++ err = au_wbr_do_copyup_bu(dentry, cpg.bsrc - 1); ++ cpg.bdst = err; ++ if (unlikely(err < 0)) { ++ err = 0; /* there is no upper writable branch */ ++ goto out_dgrade; ++ } ++ AuDbg("bsrc %d, bdst %d\n", cpg.bsrc, cpg.bdst); ++ ++ /* do not respect the coo attrib for the target branch */ ++ err = au_cpup_dirs(dentry, cpg.bdst); ++ if (unlikely(err)) ++ goto out_dgrade; ++ ++ di_downgrade_lock(parent, AuLock_IR); ++ udba = au_opt_udba(sb); ++ err = au_pin(&pin, dentry, cpg.bdst, udba, ++ AuPin_DI_LOCKED | AuPin_MNT_WRITE); ++ if (unlikely(err)) ++ goto out_parent; ++ ++ err = au_sio_cpup_simple(&cpg); ++ au_unpin(&pin); ++ if (unlikely(err)) ++ goto out_parent; ++ if (!(cmoo & AuBrWAttr_MOO)) ++ goto out_parent; /* success */ ++ ++ err = au_pin(&pin, dentry, cpg.bsrc, udba, ++ AuPin_DI_LOCKED | AuPin_MNT_WRITE); ++ if (unlikely(err)) ++ goto out_parent; ++ ++ h_path.mnt = au_br_mnt(br); ++ h_path.dentry = au_h_dptr(dentry, cpg.bsrc); ++ hdir = au_hi(d_inode(parent), cpg.bsrc); ++ delegated = NULL; ++ err = vfsub_unlink(hdir->hi_inode, &h_path, &delegated, /*force*/1); ++ au_unpin(&pin); ++ /* todo: keep h_dentry or not? */ ++ if (unlikely(err == -EWOULDBLOCK)) { ++ pr_warn("cannot retry for NFSv4 delegation" ++ " for an internal unlink\n"); ++ iput(delegated); ++ } ++ if (unlikely(err)) { ++ pr_err("unlink %pd after coo failed (%d), ignored\n", ++ dentry, err); ++ err = 0; ++ } ++ goto out_parent; /* success */ ++ ++out_dgrade: ++ di_downgrade_lock(parent, AuLock_IR); ++out_parent: ++ di_read_unlock(parent, AuLock_IR); ++ dput(parent); ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++int au_do_open(struct file *file, struct au_do_open_args *args) ++{ ++ int err, aopen = args->aopen; ++ struct dentry *dentry; ++ struct au_finfo *finfo; ++ ++ if (!aopen) ++ err = au_finfo_init(file, args->fidir); ++ else { ++ lockdep_off(); ++ err = au_finfo_init(file, args->fidir); ++ lockdep_on(); ++ } ++ if (unlikely(err)) ++ goto out; ++ ++ dentry = file->f_path.dentry; ++ AuDebugOn(IS_ERR_OR_NULL(dentry)); ++ di_write_lock_child(dentry); ++ err = au_cmoo(dentry); ++ di_downgrade_lock(dentry, AuLock_IR); ++ if (!err) { ++ if (!aopen) ++ err = args->open(file, vfsub_file_flags(file), NULL); ++ else { ++ lockdep_off(); ++ err = args->open(file, vfsub_file_flags(file), ++ args->h_file); ++ lockdep_on(); ++ } ++ } ++ di_read_unlock(dentry, AuLock_IR); ++ ++ finfo = au_fi(file); ++ if (!err) { ++ finfo->fi_file = file; ++ au_hbl_add(&finfo->fi_hlist, ++ &au_sbi(file->f_path.dentry->d_sb)->si_files); ++ } ++ if (!aopen) ++ fi_write_unlock(file); ++ else { ++ lockdep_off(); ++ fi_write_unlock(file); ++ lockdep_on(); ++ } ++ if (unlikely(err)) { ++ finfo->fi_hdir = NULL; ++ au_finfo_fin(file); ++ } ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++int au_reopen_nondir(struct file *file) ++{ ++ int err; ++ aufs_bindex_t btop; ++ struct dentry *dentry; ++ struct au_branch *br; ++ struct file *h_file, *h_file_tmp; ++ ++ dentry = file->f_path.dentry; ++ btop = au_dbtop(dentry); ++ br = au_sbr(dentry->d_sb, btop); ++ h_file_tmp = NULL; ++ if (au_fbtop(file) == btop) { ++ h_file = au_hf_top(file); ++ if (file->f_mode == h_file->f_mode) ++ return 0; /* success */ ++ h_file_tmp = h_file; ++ get_file(h_file_tmp); ++ au_lcnt_inc(&br->br_nfiles); ++ au_set_h_fptr(file, btop, NULL); ++ } ++ AuDebugOn(au_fi(file)->fi_hdir); ++ /* ++ * it can happen ++ * file exists on both of rw and ro ++ * open --> dbtop and fbtop are both 0 ++ * prepend a branch as rw, "rw" become ro ++ * remove rw/file ++ * delete the top branch, "rw" becomes rw again ++ * --> dbtop is 1, fbtop is still 0 ++ * write --> fbtop is 0 but dbtop is 1 ++ */ ++ /* AuDebugOn(au_fbtop(file) < btop); */ ++ ++ h_file = au_h_open(dentry, btop, vfsub_file_flags(file) & ~O_TRUNC, ++ file, /*force_wr*/0); ++ err = PTR_ERR(h_file); ++ if (IS_ERR(h_file)) { ++ if (h_file_tmp) { ++ /* revert */ ++ au_set_h_fptr(file, btop, h_file_tmp); ++ h_file_tmp = NULL; ++ } ++ goto out; /* todo: close all? */ ++ } ++ ++ err = 0; ++ au_set_fbtop(file, btop); ++ au_set_h_fptr(file, btop, h_file); ++ au_update_figen(file); ++ /* todo: necessary? */ ++ /* file->f_ra = h_file->f_ra; */ ++ ++out: ++ if (h_file_tmp) { ++ fput(h_file_tmp); ++ au_lcnt_dec(&br->br_nfiles); ++ } ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int au_reopen_wh(struct file *file, aufs_bindex_t btgt, ++ struct dentry *hi_wh) ++{ ++ int err; ++ aufs_bindex_t btop; ++ struct au_dinfo *dinfo; ++ struct dentry *h_dentry; ++ struct au_hdentry *hdp; ++ ++ dinfo = au_di(file->f_path.dentry); ++ AuRwMustWriteLock(&dinfo->di_rwsem); ++ ++ btop = dinfo->di_btop; ++ dinfo->di_btop = btgt; ++ hdp = au_hdentry(dinfo, btgt); ++ h_dentry = hdp->hd_dentry; ++ hdp->hd_dentry = hi_wh; ++ err = au_reopen_nondir(file); ++ hdp->hd_dentry = h_dentry; ++ dinfo->di_btop = btop; ++ ++ return err; ++} ++ ++static int au_ready_to_write_wh(struct file *file, loff_t len, ++ aufs_bindex_t bcpup, struct au_pin *pin) ++{ ++ int err; ++ struct inode *inode, *h_inode; ++ struct dentry *h_dentry, *hi_wh; ++ struct au_cp_generic cpg = { ++ .dentry = file->f_path.dentry, ++ .bdst = bcpup, ++ .bsrc = -1, ++ .len = len, ++ .pin = pin ++ }; ++ ++ au_update_dbtop(cpg.dentry); ++ inode = d_inode(cpg.dentry); ++ h_inode = NULL; ++ if (au_dbtop(cpg.dentry) <= bcpup ++ && au_dbbot(cpg.dentry) >= bcpup) { ++ h_dentry = au_h_dptr(cpg.dentry, bcpup); ++ if (h_dentry && d_is_positive(h_dentry)) ++ h_inode = d_inode(h_dentry); ++ } ++ hi_wh = au_hi_wh(inode, bcpup); ++ if (!hi_wh && !h_inode) ++ err = au_sio_cpup_wh(&cpg, file); ++ else ++ /* already copied-up after unlink */ ++ err = au_reopen_wh(file, bcpup, hi_wh); ++ ++ if (!err ++ && (inode->i_nlink > 1 ++ || (inode->i_state & I_LINKABLE)) ++ && au_opt_test(au_mntflags(cpg.dentry->d_sb), PLINK)) ++ au_plink_append(inode, bcpup, au_h_dptr(cpg.dentry, bcpup)); ++ ++ return err; ++} ++ ++/* ++ * prepare the @file for writing. ++ */ ++int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin) ++{ ++ int err; ++ aufs_bindex_t dbtop; ++ struct dentry *parent; ++ struct inode *inode; ++ struct super_block *sb; ++ struct file *h_file; ++ struct au_cp_generic cpg = { ++ .dentry = file->f_path.dentry, ++ .bdst = -1, ++ .bsrc = -1, ++ .len = len, ++ .pin = pin, ++ .flags = AuCpup_DTIME ++ }; ++ ++ sb = cpg.dentry->d_sb; ++ inode = d_inode(cpg.dentry); ++ cpg.bsrc = au_fbtop(file); ++ err = au_test_ro(sb, cpg.bsrc, inode); ++ if (!err && (au_hf_top(file)->f_mode & FMODE_WRITE)) { ++ err = au_pin(pin, cpg.dentry, cpg.bsrc, AuOpt_UDBA_NONE, ++ /*flags*/0); ++ goto out; ++ } ++ ++ /* need to cpup or reopen */ ++ parent = dget_parent(cpg.dentry); ++ di_write_lock_parent(parent); ++ err = AuWbrCopyup(au_sbi(sb), cpg.dentry); ++ cpg.bdst = err; ++ if (unlikely(err < 0)) ++ goto out_dgrade; ++ err = 0; ++ ++ if (!d_unhashed(cpg.dentry) && !au_h_dptr(parent, cpg.bdst)) { ++ err = au_cpup_dirs(cpg.dentry, cpg.bdst); ++ if (unlikely(err)) ++ goto out_dgrade; ++ } ++ ++ err = au_pin(pin, cpg.dentry, cpg.bdst, AuOpt_UDBA_NONE, ++ AuPin_DI_LOCKED | AuPin_MNT_WRITE); ++ if (unlikely(err)) ++ goto out_dgrade; ++ ++ dbtop = au_dbtop(cpg.dentry); ++ if (dbtop <= cpg.bdst) ++ cpg.bsrc = cpg.bdst; ++ ++ if (dbtop <= cpg.bdst /* just reopen */ ++ || !d_unhashed(cpg.dentry) /* copyup and reopen */ ++ ) { ++ h_file = au_h_open_pre(cpg.dentry, cpg.bsrc, /*force_wr*/0); ++ if (IS_ERR(h_file)) ++ err = PTR_ERR(h_file); ++ else { ++ di_downgrade_lock(parent, AuLock_IR); ++ if (dbtop > cpg.bdst) ++ err = au_sio_cpup_simple(&cpg); ++ if (!err) ++ err = au_reopen_nondir(file); ++ au_h_open_post(cpg.dentry, cpg.bsrc, h_file); ++ } ++ } else { /* copyup as wh and reopen */ ++ /* ++ * since writable hfsplus branch is not supported, ++ * h_open_pre/post() are unnecessary. ++ */ ++ err = au_ready_to_write_wh(file, len, cpg.bdst, pin); ++ di_downgrade_lock(parent, AuLock_IR); ++ } ++ ++ if (!err) { ++ au_pin_set_parent_lflag(pin, /*lflag*/0); ++ goto out_dput; /* success */ ++ } ++ au_unpin(pin); ++ goto out_unlock; ++ ++out_dgrade: ++ di_downgrade_lock(parent, AuLock_IR); ++out_unlock: ++ di_read_unlock(parent, AuLock_IR); ++out_dput: ++ dput(parent); ++out: ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++int au_do_flush(struct file *file, fl_owner_t id, ++ int (*flush)(struct file *file, fl_owner_t id)) ++{ ++ int err; ++ struct super_block *sb; ++ struct inode *inode; ++ ++ inode = file_inode(file); ++ sb = inode->i_sb; ++ si_noflush_read_lock(sb); ++ fi_read_lock(file); ++ ii_read_lock_child(inode); ++ ++ err = flush(file, id); ++ au_cpup_attr_timesizes(inode); ++ ++ ii_read_unlock(inode); ++ fi_read_unlock(file); ++ si_read_unlock(sb); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int au_file_refresh_by_inode(struct file *file, int *need_reopen) ++{ ++ int err; ++ struct au_pin pin; ++ struct au_finfo *finfo; ++ struct dentry *parent, *hi_wh; ++ struct inode *inode; ++ struct super_block *sb; ++ struct au_cp_generic cpg = { ++ .dentry = file->f_path.dentry, ++ .bdst = -1, ++ .bsrc = -1, ++ .len = -1, ++ .pin = &pin, ++ .flags = AuCpup_DTIME ++ }; ++ ++ FiMustWriteLock(file); ++ ++ err = 0; ++ finfo = au_fi(file); ++ sb = cpg.dentry->d_sb; ++ inode = d_inode(cpg.dentry); ++ cpg.bdst = au_ibtop(inode); ++ if (cpg.bdst == finfo->fi_btop || IS_ROOT(cpg.dentry)) ++ goto out; ++ ++ parent = dget_parent(cpg.dentry); ++ if (au_test_ro(sb, cpg.bdst, inode)) { ++ di_read_lock_parent(parent, !AuLock_IR); ++ err = AuWbrCopyup(au_sbi(sb), cpg.dentry); ++ cpg.bdst = err; ++ di_read_unlock(parent, !AuLock_IR); ++ if (unlikely(err < 0)) ++ goto out_parent; ++ err = 0; ++ } ++ ++ di_read_lock_parent(parent, AuLock_IR); ++ hi_wh = au_hi_wh(inode, cpg.bdst); ++ if (!S_ISDIR(inode->i_mode) ++ && au_opt_test(au_mntflags(sb), PLINK) ++ && au_plink_test(inode) ++ && !d_unhashed(cpg.dentry) ++ && cpg.bdst < au_dbtop(cpg.dentry)) { ++ err = au_test_and_cpup_dirs(cpg.dentry, cpg.bdst); ++ if (unlikely(err)) ++ goto out_unlock; ++ ++ /* always superio. */ ++ err = au_pin(&pin, cpg.dentry, cpg.bdst, AuOpt_UDBA_NONE, ++ AuPin_DI_LOCKED | AuPin_MNT_WRITE); ++ if (!err) { ++ err = au_sio_cpup_simple(&cpg); ++ au_unpin(&pin); ++ } ++ } else if (hi_wh) { ++ /* already copied-up after unlink */ ++ err = au_reopen_wh(file, cpg.bdst, hi_wh); ++ *need_reopen = 0; ++ } ++ ++out_unlock: ++ di_read_unlock(parent, AuLock_IR); ++out_parent: ++ dput(parent); ++out: ++ return err; ++} ++ ++static void au_do_refresh_dir(struct file *file) ++{ ++ aufs_bindex_t bindex, bbot, new_bindex, brid; ++ struct au_hfile *p, tmp, *q; ++ struct au_finfo *finfo; ++ struct super_block *sb; ++ struct au_fidir *fidir; ++ ++ FiMustWriteLock(file); ++ ++ sb = file->f_path.dentry->d_sb; ++ finfo = au_fi(file); ++ fidir = finfo->fi_hdir; ++ AuDebugOn(!fidir); ++ p = fidir->fd_hfile + finfo->fi_btop; ++ brid = p->hf_br->br_id; ++ bbot = fidir->fd_bbot; ++ for (bindex = finfo->fi_btop; bindex <= bbot; bindex++, p++) { ++ if (!p->hf_file) ++ continue; ++ ++ new_bindex = au_br_index(sb, p->hf_br->br_id); ++ if (new_bindex == bindex) ++ continue; ++ if (new_bindex < 0) { ++ au_set_h_fptr(file, bindex, NULL); ++ continue; ++ } ++ ++ /* swap two lower inode, and loop again */ ++ q = fidir->fd_hfile + new_bindex; ++ tmp = *q; ++ *q = *p; ++ *p = tmp; ++ if (tmp.hf_file) { ++ bindex--; ++ p--; ++ } ++ } ++ ++ p = fidir->fd_hfile; ++ if (!au_test_mmapped(file) && !d_unlinked(file->f_path.dentry)) { ++ bbot = au_sbbot(sb); ++ for (finfo->fi_btop = 0; finfo->fi_btop <= bbot; ++ finfo->fi_btop++, p++) ++ if (p->hf_file) { ++ if (file_inode(p->hf_file)) ++ break; ++ au_hfput(p, /*execed*/0); ++ } ++ } else { ++ bbot = au_br_index(sb, brid); ++ for (finfo->fi_btop = 0; finfo->fi_btop < bbot; ++ finfo->fi_btop++, p++) ++ if (p->hf_file) ++ au_hfput(p, /*execed*/0); ++ bbot = au_sbbot(sb); ++ } ++ ++ p = fidir->fd_hfile + bbot; ++ for (fidir->fd_bbot = bbot; fidir->fd_bbot >= finfo->fi_btop; ++ fidir->fd_bbot--, p--) ++ if (p->hf_file) { ++ if (file_inode(p->hf_file)) ++ break; ++ au_hfput(p, /*execed*/0); ++ } ++ AuDebugOn(fidir->fd_bbot < finfo->fi_btop); ++} ++ ++/* ++ * after branch manipulating, refresh the file. ++ */ ++static int refresh_file(struct file *file, int (*reopen)(struct file *file)) ++{ ++ int err, need_reopen, nbr; ++ aufs_bindex_t bbot, bindex; ++ struct dentry *dentry; ++ struct super_block *sb; ++ struct au_finfo *finfo; ++ struct au_hfile *hfile; ++ ++ dentry = file->f_path.dentry; ++ sb = dentry->d_sb; ++ nbr = au_sbbot(sb) + 1; ++ finfo = au_fi(file); ++ if (!finfo->fi_hdir) { ++ hfile = &finfo->fi_htop; ++ AuDebugOn(!hfile->hf_file); ++ bindex = au_br_index(sb, hfile->hf_br->br_id); ++ AuDebugOn(bindex < 0); ++ if (bindex != finfo->fi_btop) ++ au_set_fbtop(file, bindex); ++ } else { ++ err = au_fidir_realloc(finfo, nbr, /*may_shrink*/0); ++ if (unlikely(err)) ++ goto out; ++ au_do_refresh_dir(file); ++ } ++ ++ err = 0; ++ need_reopen = 1; ++ if (!au_test_mmapped(file)) ++ err = au_file_refresh_by_inode(file, &need_reopen); ++ if (finfo->fi_hdir) ++ /* harmless if err */ ++ au_fidir_realloc(finfo, nbr, /*may_shrink*/1); ++ if (!err && need_reopen && !d_unlinked(dentry)) ++ err = reopen(file); ++ if (!err) { ++ au_update_figen(file); ++ goto out; /* success */ ++ } ++ ++ /* error, close all lower files */ ++ if (finfo->fi_hdir) { ++ bbot = au_fbbot_dir(file); ++ for (bindex = au_fbtop(file); bindex <= bbot; bindex++) ++ au_set_h_fptr(file, bindex, NULL); ++ } ++ ++out: ++ return err; ++} ++ ++/* common function to regular file and dir */ ++int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file), ++ int wlock, unsigned int fi_lsc) ++{ ++ int err; ++ unsigned int sigen, figen; ++ aufs_bindex_t btop; ++ unsigned char pseudo_link; ++ struct dentry *dentry; ++ struct inode *inode; ++ ++ err = 0; ++ dentry = file->f_path.dentry; ++ inode = d_inode(dentry); ++ sigen = au_sigen(dentry->d_sb); ++ fi_write_lock_nested(file, fi_lsc); ++ figen = au_figen(file); ++ if (!fi_lsc) ++ di_write_lock_child(dentry); ++ else ++ di_write_lock_child2(dentry); ++ btop = au_dbtop(dentry); ++ pseudo_link = (btop != au_ibtop(inode)); ++ if (sigen == figen && !pseudo_link && au_fbtop(file) == btop) { ++ if (!wlock) { ++ di_downgrade_lock(dentry, AuLock_IR); ++ fi_downgrade_lock(file); ++ } ++ goto out; /* success */ ++ } ++ ++ AuDbg("sigen %d, figen %d\n", sigen, figen); ++ if (au_digen_test(dentry, sigen)) { ++ err = au_reval_dpath(dentry, sigen); ++ AuDebugOn(!err && au_digen_test(dentry, sigen)); ++ } ++ ++ if (!err) ++ err = refresh_file(file, reopen); ++ if (!err) { ++ if (!wlock) { ++ di_downgrade_lock(dentry, AuLock_IR); ++ fi_downgrade_lock(file); ++ } ++ } else { ++ di_write_unlock(dentry); ++ fi_write_unlock(file); ++ } ++ ++out: ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* cf. aufs_nopage() */ ++/* for madvise(2) */ ++static int aufs_readpage(struct file *file __maybe_unused, struct page *page) ++{ ++ unlock_page(page); ++ return 0; ++} ++ ++/* it will never be called, but necessary to support O_DIRECT */ ++static ssize_t aufs_direct_IO(struct kiocb *iocb, struct iov_iter *iter) ++{ BUG(); return 0; } ++ ++/* they will never be called. */ ++#ifdef CONFIG_AUFS_DEBUG ++static int aufs_write_begin(struct file *file, struct address_space *mapping, ++ loff_t pos, unsigned len, unsigned flags, ++ struct page **pagep, void **fsdata) ++{ AuUnsupport(); return 0; } ++static int aufs_write_end(struct file *file, struct address_space *mapping, ++ loff_t pos, unsigned len, unsigned copied, ++ struct page *page, void *fsdata) ++{ AuUnsupport(); return 0; } ++static int aufs_writepage(struct page *page, struct writeback_control *wbc) ++{ AuUnsupport(); return 0; } ++ ++static int aufs_set_page_dirty(struct page *page) ++{ AuUnsupport(); return 0; } ++static void aufs_invalidatepage(struct page *page, unsigned int offset, ++ unsigned int length) ++{ AuUnsupport(); } ++static int aufs_releasepage(struct page *page, gfp_t gfp) ++{ AuUnsupport(); return 0; } ++#if 0 /* called by memory compaction regardless file */ ++static int aufs_migratepage(struct address_space *mapping, struct page *newpage, ++ struct page *page, enum migrate_mode mode) ++{ AuUnsupport(); return 0; } ++#endif ++static bool aufs_isolate_page(struct page *page, isolate_mode_t mode) ++{ AuUnsupport(); return true; } ++static void aufs_putback_page(struct page *page) ++{ AuUnsupport(); } ++static int aufs_launder_page(struct page *page) ++{ AuUnsupport(); return 0; } ++static int aufs_is_partially_uptodate(struct page *page, ++ unsigned long from, ++ unsigned long count) ++{ AuUnsupport(); return 0; } ++static void aufs_is_dirty_writeback(struct page *page, bool *dirty, ++ bool *writeback) ++{ AuUnsupport(); } ++static int aufs_error_remove_page(struct address_space *mapping, ++ struct page *page) ++{ AuUnsupport(); return 0; } ++static int aufs_swap_activate(struct swap_info_struct *sis, struct file *file, ++ sector_t *span) ++{ AuUnsupport(); return 0; } ++static void aufs_swap_deactivate(struct file *file) ++{ AuUnsupport(); } ++#endif /* CONFIG_AUFS_DEBUG */ ++ ++const struct address_space_operations aufs_aop = { ++ .readpage = aufs_readpage, ++ .direct_IO = aufs_direct_IO, ++#ifdef CONFIG_AUFS_DEBUG ++ .writepage = aufs_writepage, ++ /* no writepages, because of writepage */ ++ .set_page_dirty = aufs_set_page_dirty, ++ /* no readpages, because of readpage */ ++ .write_begin = aufs_write_begin, ++ .write_end = aufs_write_end, ++ /* no bmap, no block device */ ++ .invalidatepage = aufs_invalidatepage, ++ .releasepage = aufs_releasepage, ++ /* is fallback_migrate_page ok? */ ++ /* .migratepage = aufs_migratepage, */ ++ .isolate_page = aufs_isolate_page, ++ .putback_page = aufs_putback_page, ++ .launder_page = aufs_launder_page, ++ .is_partially_uptodate = aufs_is_partially_uptodate, ++ .is_dirty_writeback = aufs_is_dirty_writeback, ++ .error_remove_page = aufs_error_remove_page, ++ .swap_activate = aufs_swap_activate, ++ .swap_deactivate = aufs_swap_deactivate ++#endif /* CONFIG_AUFS_DEBUG */ ++}; +diff -Nurp linux-5.4/fs/aufs/file.h linux-5.4-aufs/fs/aufs/file.h +--- linux-5.4/fs/aufs/file.h 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/file.h 2019-11-28 01:25:59.065925618 +0200 +@@ -0,0 +1,329 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * file operations ++ */ ++ ++#ifndef __AUFS_FILE_H__ ++#define __AUFS_FILE_H__ ++ ++#ifdef __KERNEL__ ++ ++#include ++#include ++#include ++#include ++#include "rwsem.h" ++ ++struct au_branch; ++struct au_hfile { ++ struct file *hf_file; ++ struct au_branch *hf_br; ++}; ++ ++struct au_vdir; ++struct au_fidir { ++ aufs_bindex_t fd_bbot; ++ aufs_bindex_t fd_nent; ++ struct au_vdir *fd_vdir_cache; ++ struct au_hfile fd_hfile[]; ++}; ++ ++static inline int au_fidir_sz(int nent) ++{ ++ AuDebugOn(nent < 0); ++ return sizeof(struct au_fidir) + sizeof(struct au_hfile) * nent; ++} ++ ++struct au_finfo { ++ atomic_t fi_generation; ++ ++ struct au_rwsem fi_rwsem; ++ aufs_bindex_t fi_btop; ++ ++ /* do not union them */ ++ struct { /* for non-dir */ ++ struct au_hfile fi_htop; ++ atomic_t fi_mmapped; ++ }; ++ struct au_fidir *fi_hdir; /* for dir only */ ++ ++ struct hlist_bl_node fi_hlist; ++ struct file *fi_file; /* very ugly */ ++ struct rcu_head rcu; ++} ____cacheline_aligned_in_smp; ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* file.c */ ++extern const struct address_space_operations aufs_aop; ++unsigned int au_file_roflags(unsigned int flags); ++struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags, ++ struct file *file, int force_wr); ++struct au_do_open_args { ++ int aopen; ++ int (*open)(struct file *file, int flags, ++ struct file *h_file); ++ struct au_fidir *fidir; ++ struct file *h_file; ++}; ++int au_do_open(struct file *file, struct au_do_open_args *args); ++int au_reopen_nondir(struct file *file); ++struct au_pin; ++int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin); ++int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file), ++ int wlock, unsigned int fi_lsc); ++int au_do_flush(struct file *file, fl_owner_t id, ++ int (*flush)(struct file *file, fl_owner_t id)); ++ ++/* poll.c */ ++#ifdef CONFIG_AUFS_POLL ++__poll_t aufs_poll(struct file *file, struct poll_table_struct *pt); ++#endif ++ ++#ifdef CONFIG_AUFS_BR_HFSPLUS ++/* hfsplus.c */ ++struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex, ++ int force_wr); ++void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex, ++ struct file *h_file); ++#else ++AuStub(struct file *, au_h_open_pre, return NULL, struct dentry *dentry, ++ aufs_bindex_t bindex, int force_wr) ++AuStubVoid(au_h_open_post, struct dentry *dentry, aufs_bindex_t bindex, ++ struct file *h_file); ++#endif ++ ++/* f_op.c */ ++extern const struct file_operations aufs_file_fop; ++int au_do_open_nondir(struct file *file, int flags, struct file *h_file); ++int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file); ++struct file *au_read_pre(struct file *file, int keep_fi, unsigned int lsc); ++ ++/* finfo.c */ ++void au_hfput(struct au_hfile *hf, int execed); ++void au_set_h_fptr(struct file *file, aufs_bindex_t bindex, ++ struct file *h_file); ++ ++void au_update_figen(struct file *file); ++struct au_fidir *au_fidir_alloc(struct super_block *sb); ++int au_fidir_realloc(struct au_finfo *finfo, int nbr, int may_shrink); ++ ++void au_fi_init_once(void *_fi); ++void au_finfo_fin(struct file *file); ++int au_finfo_init(struct file *file, struct au_fidir *fidir); ++ ++/* ioctl.c */ ++long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg); ++#ifdef CONFIG_COMPAT ++long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd, ++ unsigned long arg); ++long aufs_compat_ioctl_nondir(struct file *file, unsigned int cmd, ++ unsigned long arg); ++#endif ++ ++/* ---------------------------------------------------------------------- */ ++ ++static inline struct au_finfo *au_fi(struct file *file) ++{ ++ return file->private_data; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++#define fi_read_lock(f) au_rw_read_lock(&au_fi(f)->fi_rwsem) ++#define fi_write_lock(f) au_rw_write_lock(&au_fi(f)->fi_rwsem) ++#define fi_read_trylock(f) au_rw_read_trylock(&au_fi(f)->fi_rwsem) ++#define fi_write_trylock(f) au_rw_write_trylock(&au_fi(f)->fi_rwsem) ++/* ++#define fi_read_trylock_nested(f) \ ++ au_rw_read_trylock_nested(&au_fi(f)->fi_rwsem) ++#define fi_write_trylock_nested(f) \ ++ au_rw_write_trylock_nested(&au_fi(f)->fi_rwsem) ++*/ ++ ++#define fi_read_unlock(f) au_rw_read_unlock(&au_fi(f)->fi_rwsem) ++#define fi_write_unlock(f) au_rw_write_unlock(&au_fi(f)->fi_rwsem) ++#define fi_downgrade_lock(f) au_rw_dgrade_lock(&au_fi(f)->fi_rwsem) ++ ++/* lock subclass for finfo */ ++enum { ++ AuLsc_FI_1, ++ AuLsc_FI_2 ++}; ++ ++static inline void fi_read_lock_nested(struct file *f, unsigned int lsc) ++{ ++ au_rw_read_lock_nested(&au_fi(f)->fi_rwsem, lsc); ++} ++ ++static inline void fi_write_lock_nested(struct file *f, unsigned int lsc) ++{ ++ au_rw_write_lock_nested(&au_fi(f)->fi_rwsem, lsc); ++} ++ ++/* ++ * fi_read_lock_1, fi_write_lock_1, ++ * fi_read_lock_2, fi_write_lock_2 ++ */ ++#define AuReadLockFunc(name) \ ++static inline void fi_read_lock_##name(struct file *f) \ ++{ fi_read_lock_nested(f, AuLsc_FI_##name); } ++ ++#define AuWriteLockFunc(name) \ ++static inline void fi_write_lock_##name(struct file *f) \ ++{ fi_write_lock_nested(f, AuLsc_FI_##name); } ++ ++#define AuRWLockFuncs(name) \ ++ AuReadLockFunc(name) \ ++ AuWriteLockFunc(name) ++ ++AuRWLockFuncs(1); ++AuRWLockFuncs(2); ++ ++#undef AuReadLockFunc ++#undef AuWriteLockFunc ++#undef AuRWLockFuncs ++ ++#define FiMustNoWaiters(f) AuRwMustNoWaiters(&au_fi(f)->fi_rwsem) ++#define FiMustAnyLock(f) AuRwMustAnyLock(&au_fi(f)->fi_rwsem) ++#define FiMustWriteLock(f) AuRwMustWriteLock(&au_fi(f)->fi_rwsem) ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* todo: hard/soft set? */ ++static inline aufs_bindex_t au_fbtop(struct file *file) ++{ ++ FiMustAnyLock(file); ++ return au_fi(file)->fi_btop; ++} ++ ++static inline aufs_bindex_t au_fbbot_dir(struct file *file) ++{ ++ FiMustAnyLock(file); ++ AuDebugOn(!au_fi(file)->fi_hdir); ++ return au_fi(file)->fi_hdir->fd_bbot; ++} ++ ++static inline struct au_vdir *au_fvdir_cache(struct file *file) ++{ ++ FiMustAnyLock(file); ++ AuDebugOn(!au_fi(file)->fi_hdir); ++ return au_fi(file)->fi_hdir->fd_vdir_cache; ++} ++ ++static inline void au_set_fbtop(struct file *file, aufs_bindex_t bindex) ++{ ++ FiMustWriteLock(file); ++ au_fi(file)->fi_btop = bindex; ++} ++ ++static inline void au_set_fbbot_dir(struct file *file, aufs_bindex_t bindex) ++{ ++ FiMustWriteLock(file); ++ AuDebugOn(!au_fi(file)->fi_hdir); ++ au_fi(file)->fi_hdir->fd_bbot = bindex; ++} ++ ++static inline void au_set_fvdir_cache(struct file *file, ++ struct au_vdir *vdir_cache) ++{ ++ FiMustWriteLock(file); ++ AuDebugOn(!au_fi(file)->fi_hdir); ++ au_fi(file)->fi_hdir->fd_vdir_cache = vdir_cache; ++} ++ ++static inline struct file *au_hf_top(struct file *file) ++{ ++ FiMustAnyLock(file); ++ AuDebugOn(au_fi(file)->fi_hdir); ++ return au_fi(file)->fi_htop.hf_file; ++} ++ ++static inline struct file *au_hf_dir(struct file *file, aufs_bindex_t bindex) ++{ ++ FiMustAnyLock(file); ++ AuDebugOn(!au_fi(file)->fi_hdir); ++ return au_fi(file)->fi_hdir->fd_hfile[0 + bindex].hf_file; ++} ++ ++/* todo: memory barrier? */ ++static inline unsigned int au_figen(struct file *f) ++{ ++ return atomic_read(&au_fi(f)->fi_generation); ++} ++ ++static inline void au_set_mmapped(struct file *f) ++{ ++ if (atomic_inc_return(&au_fi(f)->fi_mmapped)) ++ return; ++ pr_warn("fi_mmapped wrapped around\n"); ++ while (!atomic_inc_return(&au_fi(f)->fi_mmapped)) ++ ; ++} ++ ++static inline void au_unset_mmapped(struct file *f) ++{ ++ atomic_dec(&au_fi(f)->fi_mmapped); ++} ++ ++static inline int au_test_mmapped(struct file *f) ++{ ++ return atomic_read(&au_fi(f)->fi_mmapped); ++} ++ ++/* customize vma->vm_file */ ++ ++static inline void au_do_vm_file_reset(struct vm_area_struct *vma, ++ struct file *file) ++{ ++ struct file *f; ++ ++ f = vma->vm_file; ++ get_file(file); ++ vma->vm_file = file; ++ fput(f); ++} ++ ++#ifdef CONFIG_MMU ++#define AuDbgVmRegion(file, vma) do {} while (0) ++ ++static inline void au_vm_file_reset(struct vm_area_struct *vma, ++ struct file *file) ++{ ++ au_do_vm_file_reset(vma, file); ++} ++#else ++#define AuDbgVmRegion(file, vma) \ ++ AuDebugOn((vma)->vm_region && (vma)->vm_region->vm_file != (file)) ++ ++static inline void au_vm_file_reset(struct vm_area_struct *vma, ++ struct file *file) ++{ ++ struct file *f; ++ ++ au_do_vm_file_reset(vma, file); ++ f = vma->vm_region->vm_file; ++ get_file(file); ++ vma->vm_region->vm_file = file; ++ fput(f); ++} ++#endif /* CONFIG_MMU */ ++ ++/* handle vma->vm_prfile */ ++static inline void au_vm_prfile_set(struct vm_area_struct *vma, ++ struct file *file) ++{ ++ get_file(file); ++ vma->vm_prfile = file; ++#ifndef CONFIG_MMU ++ get_file(file); ++ vma->vm_region->vm_prfile = file; ++#endif ++} ++ ++#endif /* __KERNEL__ */ ++#endif /* __AUFS_FILE_H__ */ +diff -Nurp linux-5.4/fs/aufs/finfo.c linux-5.4-aufs/fs/aufs/finfo.c +--- linux-5.4/fs/aufs/finfo.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/finfo.c 2019-11-28 01:25:59.065925618 +0200 +@@ -0,0 +1,136 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * file private data ++ */ ++ ++#include "aufs.h" ++ ++void au_hfput(struct au_hfile *hf, int execed) ++{ ++ if (execed) ++ allow_write_access(hf->hf_file); ++ fput(hf->hf_file); ++ hf->hf_file = NULL; ++ au_lcnt_dec(&hf->hf_br->br_nfiles); ++ hf->hf_br = NULL; ++} ++ ++void au_set_h_fptr(struct file *file, aufs_bindex_t bindex, struct file *val) ++{ ++ struct au_finfo *finfo = au_fi(file); ++ struct au_hfile *hf; ++ struct au_fidir *fidir; ++ ++ fidir = finfo->fi_hdir; ++ if (!fidir) { ++ AuDebugOn(finfo->fi_btop != bindex); ++ hf = &finfo->fi_htop; ++ } else ++ hf = fidir->fd_hfile + bindex; ++ ++ if (hf && hf->hf_file) ++ au_hfput(hf, vfsub_file_execed(file)); ++ if (val) { ++ FiMustWriteLock(file); ++ AuDebugOn(IS_ERR_OR_NULL(file->f_path.dentry)); ++ hf->hf_file = val; ++ hf->hf_br = au_sbr(file->f_path.dentry->d_sb, bindex); ++ } ++} ++ ++void au_update_figen(struct file *file) ++{ ++ atomic_set(&au_fi(file)->fi_generation, au_digen(file->f_path.dentry)); ++ /* smp_mb(); */ /* atomic_set */ ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++struct au_fidir *au_fidir_alloc(struct super_block *sb) ++{ ++ struct au_fidir *fidir; ++ int nbr; ++ ++ nbr = au_sbbot(sb) + 1; ++ if (nbr < 2) ++ nbr = 2; /* initial allocate for 2 branches */ ++ fidir = kzalloc(au_fidir_sz(nbr), GFP_NOFS); ++ if (fidir) { ++ fidir->fd_bbot = -1; ++ fidir->fd_nent = nbr; ++ } ++ ++ return fidir; ++} ++ ++int au_fidir_realloc(struct au_finfo *finfo, int nbr, int may_shrink) ++{ ++ int err; ++ struct au_fidir *fidir, *p; ++ ++ AuRwMustWriteLock(&finfo->fi_rwsem); ++ fidir = finfo->fi_hdir; ++ AuDebugOn(!fidir); ++ ++ err = -ENOMEM; ++ p = au_kzrealloc(fidir, au_fidir_sz(fidir->fd_nent), au_fidir_sz(nbr), ++ GFP_NOFS, may_shrink); ++ if (p) { ++ p->fd_nent = nbr; ++ finfo->fi_hdir = p; ++ err = 0; ++ } ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++void au_finfo_fin(struct file *file) ++{ ++ struct au_finfo *finfo; ++ ++ au_lcnt_dec(&au_sbi(file->f_path.dentry->d_sb)->si_nfiles); ++ ++ finfo = au_fi(file); ++ AuDebugOn(finfo->fi_hdir); ++ AuRwDestroy(&finfo->fi_rwsem); ++ au_cache_free_finfo(finfo); ++} ++ ++void au_fi_init_once(void *_finfo) ++{ ++ struct au_finfo *finfo = _finfo; ++ ++ au_rw_init(&finfo->fi_rwsem); ++} ++ ++int au_finfo_init(struct file *file, struct au_fidir *fidir) ++{ ++ int err; ++ struct au_finfo *finfo; ++ struct dentry *dentry; ++ ++ err = -ENOMEM; ++ dentry = file->f_path.dentry; ++ finfo = au_cache_alloc_finfo(); ++ if (unlikely(!finfo)) ++ goto out; ++ ++ err = 0; ++ au_lcnt_inc(&au_sbi(dentry->d_sb)->si_nfiles); ++ au_rw_write_lock(&finfo->fi_rwsem); ++ finfo->fi_btop = -1; ++ finfo->fi_hdir = fidir; ++ atomic_set(&finfo->fi_generation, au_digen(dentry)); ++ /* smp_mb(); */ /* atomic_set */ ++ ++ file->private_data = finfo; ++ ++out: ++ return err; ++} +diff -Nurp linux-5.4/fs/aufs/f_op.c linux-5.4-aufs/fs/aufs/f_op.c +--- linux-5.4/fs/aufs/f_op.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/f_op.c 2019-11-28 01:25:59.064925618 +0200 +@@ -0,0 +1,806 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * file and vm operations ++ */ ++ ++#include ++#include ++#include ++#include ++#include "aufs.h" ++ ++int au_do_open_nondir(struct file *file, int flags, struct file *h_file) ++{ ++ int err; ++ aufs_bindex_t bindex; ++ struct dentry *dentry, *h_dentry; ++ struct au_finfo *finfo; ++ struct inode *h_inode; ++ ++ FiMustWriteLock(file); ++ ++ err = 0; ++ dentry = file->f_path.dentry; ++ AuDebugOn(IS_ERR_OR_NULL(dentry)); ++ finfo = au_fi(file); ++ memset(&finfo->fi_htop, 0, sizeof(finfo->fi_htop)); ++ atomic_set(&finfo->fi_mmapped, 0); ++ bindex = au_dbtop(dentry); ++ if (!h_file) { ++ h_dentry = au_h_dptr(dentry, bindex); ++ err = vfsub_test_mntns(file->f_path.mnt, h_dentry->d_sb); ++ if (unlikely(err)) ++ goto out; ++ h_file = au_h_open(dentry, bindex, flags, file, /*force_wr*/0); ++ if (IS_ERR(h_file)) { ++ err = PTR_ERR(h_file); ++ goto out; ++ } ++ } else { ++ h_dentry = h_file->f_path.dentry; ++ err = vfsub_test_mntns(file->f_path.mnt, h_dentry->d_sb); ++ if (unlikely(err)) ++ goto out; ++ /* br ref is already inc-ed */ ++ } ++ ++ if ((flags & __O_TMPFILE) ++ && !(flags & O_EXCL)) { ++ h_inode = file_inode(h_file); ++ spin_lock(&h_inode->i_lock); ++ h_inode->i_state |= I_LINKABLE; ++ spin_unlock(&h_inode->i_lock); ++ } ++ au_set_fbtop(file, bindex); ++ au_set_h_fptr(file, bindex, h_file); ++ au_update_figen(file); ++ /* todo: necessary? */ ++ /* file->f_ra = h_file->f_ra; */ ++ ++out: ++ return err; ++} ++ ++static int aufs_open_nondir(struct inode *inode __maybe_unused, ++ struct file *file) ++{ ++ int err; ++ struct super_block *sb; ++ struct au_do_open_args args = { ++ .open = au_do_open_nondir ++ }; ++ ++ AuDbg("%pD, f_flags 0x%x, f_mode 0x%x\n", ++ file, vfsub_file_flags(file), file->f_mode); ++ ++ sb = file->f_path.dentry->d_sb; ++ si_read_lock(sb, AuLock_FLUSH); ++ err = au_do_open(file, &args); ++ si_read_unlock(sb); ++ return err; ++} ++ ++int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file) ++{ ++ struct au_finfo *finfo; ++ aufs_bindex_t bindex; ++ ++ finfo = au_fi(file); ++ au_hbl_del(&finfo->fi_hlist, ++ &au_sbi(file->f_path.dentry->d_sb)->si_files); ++ bindex = finfo->fi_btop; ++ if (bindex >= 0) ++ au_set_h_fptr(file, bindex, NULL); ++ ++ au_finfo_fin(file); ++ return 0; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int au_do_flush_nondir(struct file *file, fl_owner_t id) ++{ ++ int err; ++ struct file *h_file; ++ ++ err = 0; ++ h_file = au_hf_top(file); ++ if (h_file) ++ err = vfsub_flush(h_file, id); ++ return err; ++} ++ ++static int aufs_flush_nondir(struct file *file, fl_owner_t id) ++{ ++ return au_do_flush(file, id, au_do_flush_nondir); ++} ++ ++/* ---------------------------------------------------------------------- */ ++/* ++ * read and write functions acquire [fdi]_rwsem once, but release before ++ * mmap_sem. This is because to stop a race condition between mmap(2). ++ * Releasing these aufs-rwsem should be safe, no branch-management (by keeping ++ * si_rwsem), no harmful copy-up should happen. Actually copy-up may happen in ++ * read functions after [fdi]_rwsem are released, but it should be harmless. ++ */ ++ ++/* Callers should call au_read_post() or fput() in the end */ ++struct file *au_read_pre(struct file *file, int keep_fi, unsigned int lsc) ++{ ++ struct file *h_file; ++ int err; ++ ++ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0, lsc); ++ if (!err) { ++ di_read_unlock(file->f_path.dentry, AuLock_IR); ++ h_file = au_hf_top(file); ++ get_file(h_file); ++ if (!keep_fi) ++ fi_read_unlock(file); ++ } else ++ h_file = ERR_PTR(err); ++ ++ return h_file; ++} ++ ++static void au_read_post(struct inode *inode, struct file *h_file) ++{ ++ /* update without lock, I don't think it a problem */ ++ fsstack_copy_attr_atime(inode, file_inode(h_file)); ++ fput(h_file); ++} ++ ++struct au_write_pre { ++ /* input */ ++ unsigned int lsc; ++ ++ /* output */ ++ blkcnt_t blks; ++ aufs_bindex_t btop; ++}; ++ ++/* ++ * return with iinfo is write-locked ++ * callers should call au_write_post() or iinfo_write_unlock() + fput() in the ++ * end ++ */ ++static struct file *au_write_pre(struct file *file, int do_ready, ++ struct au_write_pre *wpre) ++{ ++ struct file *h_file; ++ struct dentry *dentry; ++ int err; ++ unsigned int lsc; ++ struct au_pin pin; ++ ++ lsc = 0; ++ if (wpre) ++ lsc = wpre->lsc; ++ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1, lsc); ++ h_file = ERR_PTR(err); ++ if (unlikely(err)) ++ goto out; ++ ++ dentry = file->f_path.dentry; ++ if (do_ready) { ++ err = au_ready_to_write(file, -1, &pin); ++ if (unlikely(err)) { ++ h_file = ERR_PTR(err); ++ di_write_unlock(dentry); ++ goto out_fi; ++ } ++ } ++ ++ di_downgrade_lock(dentry, /*flags*/0); ++ if (wpre) ++ wpre->btop = au_fbtop(file); ++ h_file = au_hf_top(file); ++ get_file(h_file); ++ if (wpre) ++ wpre->blks = file_inode(h_file)->i_blocks; ++ if (do_ready) ++ au_unpin(&pin); ++ di_read_unlock(dentry, /*flags*/0); ++ ++out_fi: ++ fi_write_unlock(file); ++out: ++ return h_file; ++} ++ ++static void au_write_post(struct inode *inode, struct file *h_file, ++ struct au_write_pre *wpre, ssize_t written) ++{ ++ struct inode *h_inode; ++ ++ au_cpup_attr_timesizes(inode); ++ AuDebugOn(au_ibtop(inode) != wpre->btop); ++ h_inode = file_inode(h_file); ++ inode->i_mode = h_inode->i_mode; ++ ii_write_unlock(inode); ++ /* AuDbg("blks %llu, %llu\n", (u64)blks, (u64)h_inode->i_blocks); */ ++ if (written > 0) ++ au_fhsm_wrote(inode->i_sb, wpre->btop, ++ /*force*/h_inode->i_blocks > wpre->blks); ++ fput(h_file); ++} ++ ++static ssize_t aufs_read(struct file *file, char __user *buf, size_t count, ++ loff_t *ppos) ++{ ++ ssize_t err; ++ struct inode *inode; ++ struct file *h_file; ++ struct super_block *sb; ++ ++ inode = file_inode(file); ++ sb = inode->i_sb; ++ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); ++ ++ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0); ++ err = PTR_ERR(h_file); ++ if (IS_ERR(h_file)) ++ goto out; ++ ++ /* filedata may be obsoleted by concurrent copyup, but no problem */ ++ err = vfsub_read_u(h_file, buf, count, ppos); ++ /* todo: necessary? */ ++ /* file->f_ra = h_file->f_ra; */ ++ au_read_post(inode, h_file); ++ ++out: ++ si_read_unlock(sb); ++ return err; ++} ++ ++/* ++ * todo: very ugly ++ * it locks both of i_mutex and si_rwsem for read in safe. ++ * if the plink maintenance mode continues forever (that is the problem), ++ * may loop forever. ++ */ ++static void au_mtx_and_read_lock(struct inode *inode) ++{ ++ int err; ++ struct super_block *sb = inode->i_sb; ++ ++ while (1) { ++ inode_lock(inode); ++ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM); ++ if (!err) ++ break; ++ inode_unlock(inode); ++ si_read_lock(sb, AuLock_NOPLMW); ++ si_read_unlock(sb); ++ } ++} ++ ++static ssize_t aufs_write(struct file *file, const char __user *ubuf, ++ size_t count, loff_t *ppos) ++{ ++ ssize_t err; ++ struct au_write_pre wpre; ++ struct inode *inode; ++ struct file *h_file; ++ char __user *buf = (char __user *)ubuf; ++ ++ inode = file_inode(file); ++ au_mtx_and_read_lock(inode); ++ ++ wpre.lsc = 0; ++ h_file = au_write_pre(file, /*do_ready*/1, &wpre); ++ err = PTR_ERR(h_file); ++ if (IS_ERR(h_file)) ++ goto out; ++ ++ err = vfsub_write_u(h_file, buf, count, ppos); ++ au_write_post(inode, h_file, &wpre, err); ++ ++out: ++ si_read_unlock(inode->i_sb); ++ inode_unlock(inode); ++ return err; ++} ++ ++static ssize_t au_do_iter(struct file *h_file, int rw, struct kiocb *kio, ++ struct iov_iter *iov_iter) ++{ ++ ssize_t err; ++ struct file *file; ++ ssize_t (*iter)(struct kiocb *, struct iov_iter *); ++ ++ err = security_file_permission(h_file, rw); ++ if (unlikely(err)) ++ goto out; ++ ++ err = -ENOSYS; ++ iter = NULL; ++ if (rw == MAY_READ) ++ iter = h_file->f_op->read_iter; ++ else if (rw == MAY_WRITE) ++ iter = h_file->f_op->write_iter; ++ ++ file = kio->ki_filp; ++ kio->ki_filp = h_file; ++ if (iter) { ++ lockdep_off(); ++ err = iter(kio, iov_iter); ++ lockdep_on(); ++ } else ++ /* currently there is no such fs */ ++ WARN_ON_ONCE(1); ++ kio->ki_filp = file; ++ ++out: ++ return err; ++} ++ ++static ssize_t aufs_read_iter(struct kiocb *kio, struct iov_iter *iov_iter) ++{ ++ ssize_t err; ++ struct file *file, *h_file; ++ struct inode *inode; ++ struct super_block *sb; ++ ++ file = kio->ki_filp; ++ inode = file_inode(file); ++ sb = inode->i_sb; ++ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); ++ ++ h_file = au_read_pre(file, /*keep_fi*/1, /*lsc*/0); ++ err = PTR_ERR(h_file); ++ if (IS_ERR(h_file)) ++ goto out; ++ ++ if (au_test_loopback_kthread()) { ++ au_warn_loopback(h_file->f_path.dentry->d_sb); ++ if (file->f_mapping != h_file->f_mapping) { ++ file->f_mapping = h_file->f_mapping; ++ smp_mb(); /* unnecessary? */ ++ } ++ } ++ fi_read_unlock(file); ++ ++ err = au_do_iter(h_file, MAY_READ, kio, iov_iter); ++ /* todo: necessary? */ ++ /* file->f_ra = h_file->f_ra; */ ++ au_read_post(inode, h_file); ++ ++out: ++ si_read_unlock(sb); ++ return err; ++} ++ ++static ssize_t aufs_write_iter(struct kiocb *kio, struct iov_iter *iov_iter) ++{ ++ ssize_t err; ++ struct au_write_pre wpre; ++ struct inode *inode; ++ struct file *file, *h_file; ++ ++ file = kio->ki_filp; ++ inode = file_inode(file); ++ au_mtx_and_read_lock(inode); ++ ++ wpre.lsc = 0; ++ h_file = au_write_pre(file, /*do_ready*/1, &wpre); ++ err = PTR_ERR(h_file); ++ if (IS_ERR(h_file)) ++ goto out; ++ ++ err = au_do_iter(h_file, MAY_WRITE, kio, iov_iter); ++ au_write_post(inode, h_file, &wpre, err); ++ ++out: ++ si_read_unlock(inode->i_sb); ++ inode_unlock(inode); ++ return err; ++} ++ ++static ssize_t aufs_splice_read(struct file *file, loff_t *ppos, ++ struct pipe_inode_info *pipe, size_t len, ++ unsigned int flags) ++{ ++ ssize_t err; ++ struct file *h_file; ++ struct inode *inode; ++ struct super_block *sb; ++ ++ inode = file_inode(file); ++ sb = inode->i_sb; ++ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); ++ ++ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0); ++ err = PTR_ERR(h_file); ++ if (IS_ERR(h_file)) ++ goto out; ++ ++ err = vfsub_splice_to(h_file, ppos, pipe, len, flags); ++ /* todo: necessary? */ ++ /* file->f_ra = h_file->f_ra; */ ++ au_read_post(inode, h_file); ++ ++out: ++ si_read_unlock(sb); ++ return err; ++} ++ ++static ssize_t ++aufs_splice_write(struct pipe_inode_info *pipe, struct file *file, loff_t *ppos, ++ size_t len, unsigned int flags) ++{ ++ ssize_t err; ++ struct au_write_pre wpre; ++ struct inode *inode; ++ struct file *h_file; ++ ++ inode = file_inode(file); ++ au_mtx_and_read_lock(inode); ++ ++ wpre.lsc = 0; ++ h_file = au_write_pre(file, /*do_ready*/1, &wpre); ++ err = PTR_ERR(h_file); ++ if (IS_ERR(h_file)) ++ goto out; ++ ++ err = vfsub_splice_from(pipe, h_file, ppos, len, flags); ++ au_write_post(inode, h_file, &wpre, err); ++ ++out: ++ si_read_unlock(inode->i_sb); ++ inode_unlock(inode); ++ return err; ++} ++ ++static long aufs_fallocate(struct file *file, int mode, loff_t offset, ++ loff_t len) ++{ ++ long err; ++ struct au_write_pre wpre; ++ struct inode *inode; ++ struct file *h_file; ++ ++ inode = file_inode(file); ++ au_mtx_and_read_lock(inode); ++ ++ wpre.lsc = 0; ++ h_file = au_write_pre(file, /*do_ready*/1, &wpre); ++ err = PTR_ERR(h_file); ++ if (IS_ERR(h_file)) ++ goto out; ++ ++ lockdep_off(); ++ err = vfs_fallocate(h_file, mode, offset, len); ++ lockdep_on(); ++ au_write_post(inode, h_file, &wpre, /*written*/1); ++ ++out: ++ si_read_unlock(inode->i_sb); ++ inode_unlock(inode); ++ return err; ++} ++ ++static ssize_t aufs_copy_file_range(struct file *src, loff_t src_pos, ++ struct file *dst, loff_t dst_pos, ++ size_t len, unsigned int flags) ++{ ++ ssize_t err; ++ struct au_write_pre wpre; ++ enum { SRC, DST }; ++ struct { ++ struct inode *inode; ++ struct file *h_file; ++ struct super_block *h_sb; ++ } a[2]; ++#define a_src a[SRC] ++#define a_dst a[DST] ++ ++ err = -EINVAL; ++ a_src.inode = file_inode(src); ++ if (unlikely(!S_ISREG(a_src.inode->i_mode))) ++ goto out; ++ a_dst.inode = file_inode(dst); ++ if (unlikely(!S_ISREG(a_dst.inode->i_mode))) ++ goto out; ++ ++ au_mtx_and_read_lock(a_dst.inode); ++ /* ++ * in order to match the order in di_write_lock2_{child,parent}(), ++ * use f_path.dentry for this comparison. ++ */ ++ if (src->f_path.dentry < dst->f_path.dentry) { ++ a_src.h_file = au_read_pre(src, /*keep_fi*/1, AuLsc_FI_1); ++ err = PTR_ERR(a_src.h_file); ++ if (IS_ERR(a_src.h_file)) ++ goto out_si; ++ ++ wpre.lsc = AuLsc_FI_2; ++ a_dst.h_file = au_write_pre(dst, /*do_ready*/1, &wpre); ++ err = PTR_ERR(a_dst.h_file); ++ if (IS_ERR(a_dst.h_file)) { ++ au_read_post(a_src.inode, a_src.h_file); ++ goto out_si; ++ } ++ } else { ++ wpre.lsc = AuLsc_FI_1; ++ a_dst.h_file = au_write_pre(dst, /*do_ready*/1, &wpre); ++ err = PTR_ERR(a_dst.h_file); ++ if (IS_ERR(a_dst.h_file)) ++ goto out_si; ++ ++ a_src.h_file = au_read_pre(src, /*keep_fi*/1, AuLsc_FI_2); ++ err = PTR_ERR(a_src.h_file); ++ if (IS_ERR(a_src.h_file)) { ++ au_write_post(a_dst.inode, a_dst.h_file, &wpre, ++ /*written*/0); ++ goto out_si; ++ } ++ } ++ ++ err = -EXDEV; ++ a_src.h_sb = file_inode(a_src.h_file)->i_sb; ++ a_dst.h_sb = file_inode(a_dst.h_file)->i_sb; ++ if (unlikely(a_src.h_sb != a_dst.h_sb)) { ++ AuDbgFile(src); ++ AuDbgFile(dst); ++ goto out_file; ++ } ++ ++ err = vfsub_copy_file_range(a_src.h_file, src_pos, a_dst.h_file, ++ dst_pos, len, flags); ++ ++out_file: ++ au_write_post(a_dst.inode, a_dst.h_file, &wpre, err); ++ fi_read_unlock(src); ++ au_read_post(a_src.inode, a_src.h_file); ++out_si: ++ si_read_unlock(a_dst.inode->i_sb); ++ inode_unlock(a_dst.inode); ++out: ++ return err; ++#undef a_src ++#undef a_dst ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * The locking order around current->mmap_sem. ++ * - in most and regular cases ++ * file I/O syscall -- aufs_read() or something ++ * -- si_rwsem for read -- mmap_sem ++ * (Note that [fdi]i_rwsem are released before mmap_sem). ++ * - in mmap case ++ * mmap(2) -- mmap_sem -- aufs_mmap() -- si_rwsem for read -- [fdi]i_rwsem ++ * This AB-BA order is definitely bad, but is not a problem since "si_rwsem for ++ * read" allows multiple processes to acquire it and [fdi]i_rwsem are not held ++ * in file I/O. Aufs needs to stop lockdep in aufs_mmap() though. ++ * It means that when aufs acquires si_rwsem for write, the process should never ++ * acquire mmap_sem. ++ * ++ * Actually aufs_iterate() holds [fdi]i_rwsem before mmap_sem, but this is not a ++ * problem either since any directory is not able to be mmap-ed. ++ * The similar scenario is applied to aufs_readlink() too. ++ */ ++ ++#if 0 /* stop calling security_file_mmap() */ ++/* cf. linux/include/linux/mman.h: calc_vm_prot_bits() */ ++#define AuConv_VM_PROT(f, b) _calc_vm_trans(f, VM_##b, PROT_##b) ++ ++static unsigned long au_arch_prot_conv(unsigned long flags) ++{ ++ /* currently ppc64 only */ ++#ifdef CONFIG_PPC64 ++ /* cf. linux/arch/powerpc/include/asm/mman.h */ ++ AuDebugOn(arch_calc_vm_prot_bits(-1) != VM_SAO); ++ return AuConv_VM_PROT(flags, SAO); ++#else ++ AuDebugOn(arch_calc_vm_prot_bits(-1)); ++ return 0; ++#endif ++} ++ ++static unsigned long au_prot_conv(unsigned long flags) ++{ ++ return AuConv_VM_PROT(flags, READ) ++ | AuConv_VM_PROT(flags, WRITE) ++ | AuConv_VM_PROT(flags, EXEC) ++ | au_arch_prot_conv(flags); ++} ++ ++/* cf. linux/include/linux/mman.h: calc_vm_flag_bits() */ ++#define AuConv_VM_MAP(f, b) _calc_vm_trans(f, VM_##b, MAP_##b) ++ ++static unsigned long au_flag_conv(unsigned long flags) ++{ ++ return AuConv_VM_MAP(flags, GROWSDOWN) ++ | AuConv_VM_MAP(flags, DENYWRITE) ++ | AuConv_VM_MAP(flags, LOCKED); ++} ++#endif ++ ++static int aufs_mmap(struct file *file, struct vm_area_struct *vma) ++{ ++ int err; ++ const unsigned char wlock ++ = (file->f_mode & FMODE_WRITE) && (vma->vm_flags & VM_SHARED); ++ struct super_block *sb; ++ struct file *h_file; ++ struct inode *inode; ++ ++ AuDbgVmRegion(file, vma); ++ ++ inode = file_inode(file); ++ sb = inode->i_sb; ++ lockdep_off(); ++ si_read_lock(sb, AuLock_NOPLMW); ++ ++ h_file = au_write_pre(file, wlock, /*wpre*/NULL); ++ lockdep_on(); ++ err = PTR_ERR(h_file); ++ if (IS_ERR(h_file)) ++ goto out; ++ ++ err = 0; ++ au_set_mmapped(file); ++ au_vm_file_reset(vma, h_file); ++ /* ++ * we cannot call security_mmap_file() here since it may acquire ++ * mmap_sem or i_mutex. ++ * ++ * err = security_mmap_file(h_file, au_prot_conv(vma->vm_flags), ++ * au_flag_conv(vma->vm_flags)); ++ */ ++ if (!err) ++ err = call_mmap(h_file, vma); ++ if (!err) { ++ au_vm_prfile_set(vma, file); ++ fsstack_copy_attr_atime(inode, file_inode(h_file)); ++ goto out_fput; /* success */ ++ } ++ au_unset_mmapped(file); ++ au_vm_file_reset(vma, file); ++ ++out_fput: ++ lockdep_off(); ++ ii_write_unlock(inode); ++ lockdep_on(); ++ fput(h_file); ++out: ++ lockdep_off(); ++ si_read_unlock(sb); ++ lockdep_on(); ++ AuTraceErr(err); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int aufs_fsync_nondir(struct file *file, loff_t start, loff_t end, ++ int datasync) ++{ ++ int err; ++ struct au_write_pre wpre; ++ struct inode *inode; ++ struct file *h_file; ++ ++ err = 0; /* -EBADF; */ /* posix? */ ++ if (unlikely(!(file->f_mode & FMODE_WRITE))) ++ goto out; ++ ++ inode = file_inode(file); ++ au_mtx_and_read_lock(inode); ++ ++ wpre.lsc = 0; ++ h_file = au_write_pre(file, /*do_ready*/1, &wpre); ++ err = PTR_ERR(h_file); ++ if (IS_ERR(h_file)) ++ goto out_unlock; ++ ++ err = vfsub_fsync(h_file, &h_file->f_path, datasync); ++ au_write_post(inode, h_file, &wpre, /*written*/0); ++ ++out_unlock: ++ si_read_unlock(inode->i_sb); ++ inode_unlock(inode); ++out: ++ return err; ++} ++ ++static int aufs_fasync(int fd, struct file *file, int flag) ++{ ++ int err; ++ struct file *h_file; ++ struct super_block *sb; ++ ++ sb = file->f_path.dentry->d_sb; ++ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); ++ ++ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0); ++ err = PTR_ERR(h_file); ++ if (IS_ERR(h_file)) ++ goto out; ++ ++ if (h_file->f_op->fasync) ++ err = h_file->f_op->fasync(fd, h_file, flag); ++ fput(h_file); /* instead of au_read_post() */ ++ ++out: ++ si_read_unlock(sb); ++ return err; ++} ++ ++static int aufs_setfl(struct file *file, unsigned long arg) ++{ ++ int err; ++ struct file *h_file; ++ struct super_block *sb; ++ ++ sb = file->f_path.dentry->d_sb; ++ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); ++ ++ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0); ++ err = PTR_ERR(h_file); ++ if (IS_ERR(h_file)) ++ goto out; ++ ++ /* stop calling h_file->fasync */ ++ arg |= vfsub_file_flags(file) & FASYNC; ++ err = setfl(/*unused fd*/-1, h_file, arg); ++ fput(h_file); /* instead of au_read_post() */ ++ ++out: ++ si_read_unlock(sb); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* no one supports this operation, currently */ ++#if 0 ++static ssize_t aufs_sendpage(struct file *file, struct page *page, int offset, ++ size_t len, loff_t *pos, int more) ++{ ++} ++#endif ++ ++/* ---------------------------------------------------------------------- */ ++ ++const struct file_operations aufs_file_fop = { ++ .owner = THIS_MODULE, ++ ++ .llseek = default_llseek, ++ ++ .read = aufs_read, ++ .write = aufs_write, ++ .read_iter = aufs_read_iter, ++ .write_iter = aufs_write_iter, ++ ++#ifdef CONFIG_AUFS_POLL ++ .poll = aufs_poll, ++#endif ++ .unlocked_ioctl = aufs_ioctl_nondir, ++#ifdef CONFIG_COMPAT ++ .compat_ioctl = aufs_compat_ioctl_nondir, ++#endif ++ .mmap = aufs_mmap, ++ .open = aufs_open_nondir, ++ .flush = aufs_flush_nondir, ++ .release = aufs_release_nondir, ++ .fsync = aufs_fsync_nondir, ++ .fasync = aufs_fasync, ++ /* .sendpage = aufs_sendpage, */ ++ .setfl = aufs_setfl, ++ .splice_write = aufs_splice_write, ++ .splice_read = aufs_splice_read, ++#if 0 ++ .aio_splice_write = aufs_aio_splice_write, ++ .aio_splice_read = aufs_aio_splice_read, ++#endif ++ .fallocate = aufs_fallocate, ++ .copy_file_range = aufs_copy_file_range ++}; +diff -Nurp linux-5.4/fs/aufs/fstype.h linux-5.4-aufs/fs/aufs/fstype.h +--- linux-5.4/fs/aufs/fstype.h 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/fstype.h 2019-11-28 01:25:59.065925618 +0200 +@@ -0,0 +1,388 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * judging filesystem type ++ */ ++ ++#ifndef __AUFS_FSTYPE_H__ ++#define __AUFS_FSTYPE_H__ ++ ++#ifdef __KERNEL__ ++ ++#include ++#include ++#include ++#include ++ ++static inline int au_test_aufs(struct super_block *sb) ++{ ++ return sb->s_magic == AUFS_SUPER_MAGIC; ++} ++ ++static inline const char *au_sbtype(struct super_block *sb) ++{ ++ return sb->s_type->name; ++} ++ ++static inline int au_test_iso9660(struct super_block *sb __maybe_unused) ++{ ++#if IS_ENABLED(CONFIG_ISO9660_FS) ++ return sb->s_magic == ISOFS_SUPER_MAGIC; ++#else ++ return 0; ++#endif ++} ++ ++static inline int au_test_romfs(struct super_block *sb __maybe_unused) ++{ ++#if IS_ENABLED(CONFIG_ROMFS_FS) ++ return sb->s_magic == ROMFS_MAGIC; ++#else ++ return 0; ++#endif ++} ++ ++static inline int au_test_cramfs(struct super_block *sb __maybe_unused) ++{ ++#if IS_ENABLED(CONFIG_CRAMFS) ++ return sb->s_magic == CRAMFS_MAGIC; ++#endif ++ return 0; ++} ++ ++static inline int au_test_nfs(struct super_block *sb __maybe_unused) ++{ ++#if IS_ENABLED(CONFIG_NFS_FS) ++ return sb->s_magic == NFS_SUPER_MAGIC; ++#else ++ return 0; ++#endif ++} ++ ++static inline int au_test_fuse(struct super_block *sb __maybe_unused) ++{ ++#if IS_ENABLED(CONFIG_FUSE_FS) ++ return sb->s_magic == FUSE_SUPER_MAGIC; ++#else ++ return 0; ++#endif ++} ++ ++static inline int au_test_xfs(struct super_block *sb __maybe_unused) ++{ ++#if IS_ENABLED(CONFIG_XFS_FS) ++ return sb->s_magic == XFS_SB_MAGIC; ++#else ++ return 0; ++#endif ++} ++ ++static inline int au_test_tmpfs(struct super_block *sb __maybe_unused) ++{ ++#ifdef CONFIG_TMPFS ++ return sb->s_magic == TMPFS_MAGIC; ++#else ++ return 0; ++#endif ++} ++ ++static inline int au_test_ecryptfs(struct super_block *sb __maybe_unused) ++{ ++#if IS_ENABLED(CONFIG_ECRYPT_FS) ++ return !strcmp(au_sbtype(sb), "ecryptfs"); ++#else ++ return 0; ++#endif ++} ++ ++static inline int au_test_ramfs(struct super_block *sb) ++{ ++ return sb->s_magic == RAMFS_MAGIC; ++} ++ ++static inline int au_test_ubifs(struct super_block *sb __maybe_unused) ++{ ++#if IS_ENABLED(CONFIG_UBIFS_FS) ++ return sb->s_magic == UBIFS_SUPER_MAGIC; ++#else ++ return 0; ++#endif ++} ++ ++static inline int au_test_procfs(struct super_block *sb __maybe_unused) ++{ ++#ifdef CONFIG_PROC_FS ++ return sb->s_magic == PROC_SUPER_MAGIC; ++#else ++ return 0; ++#endif ++} ++ ++static inline int au_test_sysfs(struct super_block *sb __maybe_unused) ++{ ++#ifdef CONFIG_SYSFS ++ return sb->s_magic == SYSFS_MAGIC; ++#else ++ return 0; ++#endif ++} ++ ++static inline int au_test_configfs(struct super_block *sb __maybe_unused) ++{ ++#if IS_ENABLED(CONFIG_CONFIGFS_FS) ++ return sb->s_magic == CONFIGFS_MAGIC; ++#else ++ return 0; ++#endif ++} ++ ++static inline int au_test_minix(struct super_block *sb __maybe_unused) ++{ ++#if IS_ENABLED(CONFIG_MINIX_FS) ++ return sb->s_magic == MINIX3_SUPER_MAGIC ++ || sb->s_magic == MINIX2_SUPER_MAGIC ++ || sb->s_magic == MINIX2_SUPER_MAGIC2 ++ || sb->s_magic == MINIX_SUPER_MAGIC ++ || sb->s_magic == MINIX_SUPER_MAGIC2; ++#else ++ return 0; ++#endif ++} ++ ++static inline int au_test_fat(struct super_block *sb __maybe_unused) ++{ ++#if IS_ENABLED(CONFIG_FAT_FS) ++ return sb->s_magic == MSDOS_SUPER_MAGIC; ++#else ++ return 0; ++#endif ++} ++ ++static inline int au_test_msdos(struct super_block *sb) ++{ ++ return au_test_fat(sb); ++} ++ ++static inline int au_test_vfat(struct super_block *sb) ++{ ++ return au_test_fat(sb); ++} ++ ++static inline int au_test_securityfs(struct super_block *sb __maybe_unused) ++{ ++#ifdef CONFIG_SECURITYFS ++ return sb->s_magic == SECURITYFS_MAGIC; ++#else ++ return 0; ++#endif ++} ++ ++static inline int au_test_squashfs(struct super_block *sb __maybe_unused) ++{ ++#if IS_ENABLED(CONFIG_SQUASHFS) ++ return sb->s_magic == SQUASHFS_MAGIC; ++#else ++ return 0; ++#endif ++} ++ ++static inline int au_test_btrfs(struct super_block *sb __maybe_unused) ++{ ++#if IS_ENABLED(CONFIG_BTRFS_FS) ++ return sb->s_magic == BTRFS_SUPER_MAGIC; ++#else ++ return 0; ++#endif ++} ++ ++static inline int au_test_xenfs(struct super_block *sb __maybe_unused) ++{ ++#if IS_ENABLED(CONFIG_XENFS) ++ return sb->s_magic == XENFS_SUPER_MAGIC; ++#else ++ return 0; ++#endif ++} ++ ++static inline int au_test_debugfs(struct super_block *sb __maybe_unused) ++{ ++#ifdef CONFIG_DEBUG_FS ++ return sb->s_magic == DEBUGFS_MAGIC; ++#else ++ return 0; ++#endif ++} ++ ++static inline int au_test_nilfs(struct super_block *sb __maybe_unused) ++{ ++#if IS_ENABLED(CONFIG_NILFS) ++ return sb->s_magic == NILFS_SUPER_MAGIC; ++#else ++ return 0; ++#endif ++} ++ ++static inline int au_test_hfsplus(struct super_block *sb __maybe_unused) ++{ ++#if IS_ENABLED(CONFIG_HFSPLUS_FS) ++ return sb->s_magic == HFSPLUS_SUPER_MAGIC; ++#else ++ return 0; ++#endif ++} ++ ++/* ---------------------------------------------------------------------- */ ++/* ++ * they can't be an aufs branch. ++ */ ++static inline int au_test_fs_unsuppoted(struct super_block *sb) ++{ ++ return ++#ifndef CONFIG_AUFS_BR_RAMFS ++ au_test_ramfs(sb) || ++#endif ++ au_test_procfs(sb) ++ || au_test_sysfs(sb) ++ || au_test_configfs(sb) ++ || au_test_debugfs(sb) ++ || au_test_securityfs(sb) ++ || au_test_xenfs(sb) ++ || au_test_ecryptfs(sb) ++ /* || !strcmp(au_sbtype(sb), "unionfs") */ ++ || au_test_aufs(sb); /* will be supported in next version */ ++} ++ ++static inline int au_test_fs_remote(struct super_block *sb) ++{ ++ return !au_test_tmpfs(sb) ++#ifdef CONFIG_AUFS_BR_RAMFS ++ && !au_test_ramfs(sb) ++#endif ++ && !(sb->s_type->fs_flags & FS_REQUIRES_DEV); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * Note: these functions (below) are created after reading ->getattr() in all ++ * filesystems under linux/fs. it means we have to do so in every update... ++ */ ++ ++/* ++ * some filesystems require getattr to refresh the inode attributes before ++ * referencing. ++ * in most cases, we can rely on the inode attribute in NFS (or every remote fs) ++ * and leave the work for d_revalidate() ++ */ ++static inline int au_test_fs_refresh_iattr(struct super_block *sb) ++{ ++ return au_test_nfs(sb) ++ || au_test_fuse(sb) ++ /* || au_test_btrfs(sb) */ /* untested */ ++ ; ++} ++ ++/* ++ * filesystems which don't maintain i_size or i_blocks. ++ */ ++static inline int au_test_fs_bad_iattr_size(struct super_block *sb) ++{ ++ return au_test_xfs(sb) ++ || au_test_btrfs(sb) ++ || au_test_ubifs(sb) ++ || au_test_hfsplus(sb) /* maintained, but incorrect */ ++ /* || au_test_minix(sb) */ /* untested */ ++ ; ++} ++ ++/* ++ * filesystems which don't store the correct value in some of their inode ++ * attributes. ++ */ ++static inline int au_test_fs_bad_iattr(struct super_block *sb) ++{ ++ return au_test_fs_bad_iattr_size(sb) ++ || au_test_fat(sb) ++ || au_test_msdos(sb) ++ || au_test_vfat(sb); ++} ++ ++/* they don't check i_nlink in link(2) */ ++static inline int au_test_fs_no_limit_nlink(struct super_block *sb) ++{ ++ return au_test_tmpfs(sb) ++#ifdef CONFIG_AUFS_BR_RAMFS ++ || au_test_ramfs(sb) ++#endif ++ || au_test_ubifs(sb) ++ || au_test_hfsplus(sb); ++} ++ ++/* ++ * filesystems which sets S_NOATIME and S_NOCMTIME. ++ */ ++static inline int au_test_fs_notime(struct super_block *sb) ++{ ++ return au_test_nfs(sb) ++ || au_test_fuse(sb) ++ || au_test_ubifs(sb) ++ ; ++} ++ ++/* temporary support for i#1 in cramfs */ ++static inline int au_test_fs_unique_ino(struct inode *inode) ++{ ++ if (au_test_cramfs(inode->i_sb)) ++ return inode->i_ino != 1; ++ return 1; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * the filesystem where the xino files placed must support i/o after unlink and ++ * maintain i_size and i_blocks. ++ */ ++static inline int au_test_fs_bad_xino(struct super_block *sb) ++{ ++ return au_test_fs_remote(sb) ++ || au_test_fs_bad_iattr_size(sb) ++ /* don't want unnecessary work for xino */ ++ || au_test_aufs(sb) ++ || au_test_ecryptfs(sb) ++ || au_test_nilfs(sb); ++} ++ ++static inline int au_test_fs_trunc_xino(struct super_block *sb) ++{ ++ return au_test_tmpfs(sb) ++ || au_test_ramfs(sb); ++} ++ ++/* ++ * test if the @sb is real-readonly. ++ */ ++static inline int au_test_fs_rr(struct super_block *sb) ++{ ++ return au_test_squashfs(sb) ++ || au_test_iso9660(sb) ++ || au_test_cramfs(sb) ++ || au_test_romfs(sb); ++} ++ ++/* ++ * test if the @inode is nfs with 'noacl' option ++ * NFS always sets SB_POSIXACL regardless its mount option 'noacl.' ++ */ ++static inline int au_test_nfs_noacl(struct inode *inode) ++{ ++ return au_test_nfs(inode->i_sb) ++ /* && IS_POSIXACL(inode) */ ++ && !nfs_server_capable(inode, NFS_CAP_ACLS); ++} ++ ++#endif /* __KERNEL__ */ ++#endif /* __AUFS_FSTYPE_H__ */ +diff -Nurp linux-5.4/fs/aufs/hbl.h linux-5.4-aufs/fs/aufs/hbl.h +--- linux-5.4/fs/aufs/hbl.h 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/hbl.h 2019-11-28 01:25:59.065925618 +0200 +@@ -0,0 +1,52 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2017-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * helpers for hlist_bl.h ++ */ ++ ++#ifndef __AUFS_HBL_H__ ++#define __AUFS_HBL_H__ ++ ++#ifdef __KERNEL__ ++ ++#include ++ ++static inline void au_hbl_add(struct hlist_bl_node *node, ++ struct hlist_bl_head *hbl) ++{ ++ hlist_bl_lock(hbl); ++ hlist_bl_add_head(node, hbl); ++ hlist_bl_unlock(hbl); ++} ++ ++static inline void au_hbl_del(struct hlist_bl_node *node, ++ struct hlist_bl_head *hbl) ++{ ++ hlist_bl_lock(hbl); ++ hlist_bl_del(node); ++ hlist_bl_unlock(hbl); ++} ++ ++#define au_hbl_for_each(pos, head) \ ++ for (pos = hlist_bl_first(head); \ ++ pos; \ ++ pos = pos->next) ++ ++static inline unsigned long au_hbl_count(struct hlist_bl_head *hbl) ++{ ++ unsigned long cnt; ++ struct hlist_bl_node *pos; ++ ++ cnt = 0; ++ hlist_bl_lock(hbl); ++ au_hbl_for_each(pos, hbl) ++ cnt++; ++ hlist_bl_unlock(hbl); ++ return cnt; ++} ++ ++#endif /* __KERNEL__ */ ++#endif /* __AUFS_HBL_H__ */ +diff -Nurp linux-5.4/fs/aufs/hfsnotify.c linux-5.4-aufs/fs/aufs/hfsnotify.c +--- linux-5.4/fs/aufs/hfsnotify.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/hfsnotify.c 2019-11-28 01:25:59.065925618 +0200 +@@ -0,0 +1,275 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * fsnotify for the lower directories ++ */ ++ ++#include "aufs.h" ++ ++/* FS_IN_IGNORED is unnecessary */ ++static const __u32 AuHfsnMask = (FS_MOVED_TO | FS_MOVED_FROM | FS_DELETE ++ | FS_CREATE | FS_EVENT_ON_CHILD); ++static DECLARE_WAIT_QUEUE_HEAD(au_hfsn_wq); ++static __cacheline_aligned_in_smp atomic64_t au_hfsn_ifree = ATOMIC64_INIT(0); ++ ++static void au_hfsn_free_mark(struct fsnotify_mark *mark) ++{ ++ struct au_hnotify *hn = container_of(mark, struct au_hnotify, ++ hn_mark); ++ /* AuDbg("here\n"); */ ++ au_cache_free_hnotify(hn); ++ smp_mb__before_atomic(); /* for atomic64_dec */ ++ if (atomic64_dec_and_test(&au_hfsn_ifree)) ++ wake_up(&au_hfsn_wq); ++} ++ ++static int au_hfsn_alloc(struct au_hinode *hinode) ++{ ++ int err; ++ struct au_hnotify *hn; ++ struct super_block *sb; ++ struct au_branch *br; ++ struct fsnotify_mark *mark; ++ aufs_bindex_t bindex; ++ ++ hn = hinode->hi_notify; ++ sb = hn->hn_aufs_inode->i_sb; ++ bindex = au_br_index(sb, hinode->hi_id); ++ br = au_sbr(sb, bindex); ++ AuDebugOn(!br->br_hfsn); ++ ++ mark = &hn->hn_mark; ++ fsnotify_init_mark(mark, br->br_hfsn->hfsn_group); ++ mark->mask = AuHfsnMask; ++ /* ++ * by udba rename or rmdir, aufs assign a new inode to the known ++ * h_inode, so specify 1 to allow dups. ++ */ ++ lockdep_off(); ++ err = fsnotify_add_inode_mark(mark, hinode->hi_inode, /*allow_dups*/1); ++ lockdep_on(); ++ ++ return err; ++} ++ ++static int au_hfsn_free(struct au_hinode *hinode, struct au_hnotify *hn) ++{ ++ struct fsnotify_mark *mark; ++ unsigned long long ull; ++ struct fsnotify_group *group; ++ ++ ull = atomic64_inc_return(&au_hfsn_ifree); ++ BUG_ON(!ull); ++ ++ mark = &hn->hn_mark; ++ spin_lock(&mark->lock); ++ group = mark->group; ++ fsnotify_get_group(group); ++ spin_unlock(&mark->lock); ++ lockdep_off(); ++ fsnotify_destroy_mark(mark, group); ++ fsnotify_put_mark(mark); ++ fsnotify_put_group(group); ++ lockdep_on(); ++ ++ /* free hn by myself */ ++ return 0; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static void au_hfsn_ctl(struct au_hinode *hinode, int do_set) ++{ ++ struct fsnotify_mark *mark; ++ ++ mark = &hinode->hi_notify->hn_mark; ++ spin_lock(&mark->lock); ++ if (do_set) { ++ AuDebugOn(mark->mask & AuHfsnMask); ++ mark->mask |= AuHfsnMask; ++ } else { ++ AuDebugOn(!(mark->mask & AuHfsnMask)); ++ mark->mask &= ~AuHfsnMask; ++ } ++ spin_unlock(&mark->lock); ++ /* fsnotify_recalc_inode_mask(hinode->hi_inode); */ ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* #define AuDbgHnotify */ ++#ifdef AuDbgHnotify ++static char *au_hfsn_name(u32 mask) ++{ ++#ifdef CONFIG_AUFS_DEBUG ++#define test_ret(flag) \ ++ do { \ ++ if (mask & flag) \ ++ return #flag; \ ++ } while (0) ++ test_ret(FS_ACCESS); ++ test_ret(FS_MODIFY); ++ test_ret(FS_ATTRIB); ++ test_ret(FS_CLOSE_WRITE); ++ test_ret(FS_CLOSE_NOWRITE); ++ test_ret(FS_OPEN); ++ test_ret(FS_MOVED_FROM); ++ test_ret(FS_MOVED_TO); ++ test_ret(FS_CREATE); ++ test_ret(FS_DELETE); ++ test_ret(FS_DELETE_SELF); ++ test_ret(FS_MOVE_SELF); ++ test_ret(FS_UNMOUNT); ++ test_ret(FS_Q_OVERFLOW); ++ test_ret(FS_IN_IGNORED); ++ test_ret(FS_ISDIR); ++ test_ret(FS_IN_ONESHOT); ++ test_ret(FS_EVENT_ON_CHILD); ++ return ""; ++#undef test_ret ++#else ++ return "??"; ++#endif ++} ++#endif ++ ++/* ---------------------------------------------------------------------- */ ++ ++static void au_hfsn_free_group(struct fsnotify_group *group) ++{ ++ struct au_br_hfsnotify *hfsn = group->private; ++ ++ /* AuDbg("here\n"); */ ++ au_kfree_try_rcu(hfsn); ++} ++ ++static int au_hfsn_handle_event(struct fsnotify_group *group, ++ struct inode *inode, ++ u32 mask, const void *data, int data_type, ++ const struct qstr *file_name, u32 cookie, ++ struct fsnotify_iter_info *iter_info) ++{ ++ int err; ++ struct au_hnotify *hnotify; ++ struct inode *h_dir, *h_inode; ++ struct fsnotify_mark *inode_mark; ++ ++ AuDebugOn(data_type != FSNOTIFY_EVENT_INODE); ++ ++ err = 0; ++ /* if FS_UNMOUNT happens, there must be another bug */ ++ AuDebugOn(mask & FS_UNMOUNT); ++ if (mask & (FS_IN_IGNORED | FS_UNMOUNT)) ++ goto out; ++ ++ h_dir = inode; ++ h_inode = NULL; ++#ifdef AuDbgHnotify ++ au_debug_on(); ++ if (1 || h_child_qstr.len != sizeof(AUFS_XINO_FNAME) - 1 ++ || strncmp(h_child_qstr.name, AUFS_XINO_FNAME, h_child_qstr.len)) { ++ AuDbg("i%lu, mask 0x%x %s, hcname %.*s, hi%lu\n", ++ h_dir->i_ino, mask, au_hfsn_name(mask), ++ AuLNPair(&h_child_qstr), h_inode ? h_inode->i_ino : 0); ++ /* WARN_ON(1); */ ++ } ++ au_debug_off(); ++#endif ++ ++ inode_mark = fsnotify_iter_inode_mark(iter_info); ++ AuDebugOn(!inode_mark); ++ hnotify = container_of(inode_mark, struct au_hnotify, hn_mark); ++ err = au_hnotify(h_dir, hnotify, mask, file_name, h_inode); ++ ++out: ++ return err; ++} ++ ++static struct fsnotify_ops au_hfsn_ops = { ++ .handle_event = au_hfsn_handle_event, ++ .free_group_priv = au_hfsn_free_group, ++ .free_mark = au_hfsn_free_mark ++}; ++ ++/* ---------------------------------------------------------------------- */ ++ ++static void au_hfsn_fin_br(struct au_branch *br) ++{ ++ struct au_br_hfsnotify *hfsn; ++ ++ hfsn = br->br_hfsn; ++ if (hfsn) { ++ lockdep_off(); ++ fsnotify_put_group(hfsn->hfsn_group); ++ lockdep_on(); ++ } ++} ++ ++static int au_hfsn_init_br(struct au_branch *br, int perm) ++{ ++ int err; ++ struct fsnotify_group *group; ++ struct au_br_hfsnotify *hfsn; ++ ++ err = 0; ++ br->br_hfsn = NULL; ++ if (!au_br_hnotifyable(perm)) ++ goto out; ++ ++ err = -ENOMEM; ++ hfsn = kmalloc(sizeof(*hfsn), GFP_NOFS); ++ if (unlikely(!hfsn)) ++ goto out; ++ ++ err = 0; ++ group = fsnotify_alloc_group(&au_hfsn_ops); ++ if (IS_ERR(group)) { ++ err = PTR_ERR(group); ++ pr_err("fsnotify_alloc_group() failed, %d\n", err); ++ goto out_hfsn; ++ } ++ ++ group->private = hfsn; ++ hfsn->hfsn_group = group; ++ br->br_hfsn = hfsn; ++ goto out; /* success */ ++ ++out_hfsn: ++ au_kfree_try_rcu(hfsn); ++out: ++ return err; ++} ++ ++static int au_hfsn_reset_br(unsigned int udba, struct au_branch *br, int perm) ++{ ++ int err; ++ ++ err = 0; ++ if (!br->br_hfsn) ++ err = au_hfsn_init_br(br, perm); ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static void au_hfsn_fin(void) ++{ ++ AuDbg("au_hfsn_ifree %lld\n", (long long)atomic64_read(&au_hfsn_ifree)); ++ wait_event(au_hfsn_wq, !atomic64_read(&au_hfsn_ifree)); ++} ++ ++const struct au_hnotify_op au_hnotify_op = { ++ .ctl = au_hfsn_ctl, ++ .alloc = au_hfsn_alloc, ++ .free = au_hfsn_free, ++ ++ .fin = au_hfsn_fin, ++ ++ .reset_br = au_hfsn_reset_br, ++ .fin_br = au_hfsn_fin_br, ++ .init_br = au_hfsn_init_br ++}; +diff -Nurp linux-5.4/fs/aufs/hfsplus.c linux-5.4-aufs/fs/aufs/hfsplus.c +--- linux-5.4/fs/aufs/hfsplus.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/hfsplus.c 2019-11-28 01:25:59.065925618 +0200 +@@ -0,0 +1,47 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2010-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * special support for filesystems which acquires an inode mutex ++ * at final closing a file, eg, hfsplus. ++ * ++ * This trick is very simple and stupid, just to open the file before really ++ * necessary open to tell hfsplus that this is not the final closing. ++ * The caller should call au_h_open_pre() after acquiring the inode mutex, ++ * and au_h_open_post() after releasing it. ++ */ ++ ++#include "aufs.h" ++ ++struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex, ++ int force_wr) ++{ ++ struct file *h_file; ++ struct dentry *h_dentry; ++ ++ h_dentry = au_h_dptr(dentry, bindex); ++ AuDebugOn(!h_dentry); ++ AuDebugOn(d_is_negative(h_dentry)); ++ ++ h_file = NULL; ++ if (au_test_hfsplus(h_dentry->d_sb) ++ && d_is_reg(h_dentry)) ++ h_file = au_h_open(dentry, bindex, ++ O_RDONLY | O_NOATIME | O_LARGEFILE, ++ /*file*/NULL, force_wr); ++ return h_file; ++} ++ ++void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex, ++ struct file *h_file) ++{ ++ struct au_branch *br; ++ ++ if (h_file) { ++ fput(h_file); ++ br = au_sbr(dentry->d_sb, bindex); ++ au_lcnt_dec(&br->br_nfiles); ++ } ++} +diff -Nurp linux-5.4/fs/aufs/hnotify.c linux-5.4-aufs/fs/aufs/hnotify.c +--- linux-5.4/fs/aufs/hnotify.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/hnotify.c 2019-11-28 01:25:59.065925618 +0200 +@@ -0,0 +1,708 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * abstraction to notify the direct changes on lower directories ++ */ ++ ++/* #include */ ++#include "aufs.h" ++ ++int au_hn_alloc(struct au_hinode *hinode, struct inode *inode) ++{ ++ int err; ++ struct au_hnotify *hn; ++ ++ err = -ENOMEM; ++ hn = au_cache_alloc_hnotify(); ++ if (hn) { ++ hn->hn_aufs_inode = inode; ++ hinode->hi_notify = hn; ++ err = au_hnotify_op.alloc(hinode); ++ AuTraceErr(err); ++ if (unlikely(err)) { ++ hinode->hi_notify = NULL; ++ au_cache_free_hnotify(hn); ++ /* ++ * The upper dir was removed by udba, but the same named ++ * dir left. In this case, aufs assigns a new inode ++ * number and set the monitor again. ++ * For the lower dir, the old monitor is still left. ++ */ ++ if (err == -EEXIST) ++ err = 0; ++ } ++ } ++ ++ AuTraceErr(err); ++ return err; ++} ++ ++void au_hn_free(struct au_hinode *hinode) ++{ ++ struct au_hnotify *hn; ++ ++ hn = hinode->hi_notify; ++ if (hn) { ++ hinode->hi_notify = NULL; ++ if (au_hnotify_op.free(hinode, hn)) ++ au_cache_free_hnotify(hn); ++ } ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++void au_hn_ctl(struct au_hinode *hinode, int do_set) ++{ ++ if (hinode->hi_notify) ++ au_hnotify_op.ctl(hinode, do_set); ++} ++ ++void au_hn_reset(struct inode *inode, unsigned int flags) ++{ ++ aufs_bindex_t bindex, bbot; ++ struct inode *hi; ++ struct dentry *iwhdentry; ++ ++ bbot = au_ibbot(inode); ++ for (bindex = au_ibtop(inode); bindex <= bbot; bindex++) { ++ hi = au_h_iptr(inode, bindex); ++ if (!hi) ++ continue; ++ ++ /* inode_lock_nested(hi, AuLsc_I_CHILD); */ ++ iwhdentry = au_hi_wh(inode, bindex); ++ if (iwhdentry) ++ dget(iwhdentry); ++ au_igrab(hi); ++ au_set_h_iptr(inode, bindex, NULL, 0); ++ au_set_h_iptr(inode, bindex, au_igrab(hi), ++ flags & ~AuHi_XINO); ++ iput(hi); ++ dput(iwhdentry); ++ /* inode_unlock(hi); */ ++ } ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int hn_xino(struct inode *inode, struct inode *h_inode) ++{ ++ int err; ++ aufs_bindex_t bindex, bbot, bfound, btop; ++ struct inode *h_i; ++ ++ err = 0; ++ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) { ++ pr_warn("branch root dir was changed\n"); ++ goto out; ++ } ++ ++ bfound = -1; ++ bbot = au_ibbot(inode); ++ btop = au_ibtop(inode); ++#if 0 /* reserved for future use */ ++ if (bindex == bbot) { ++ /* keep this ino in rename case */ ++ goto out; ++ } ++#endif ++ for (bindex = btop; bindex <= bbot; bindex++) ++ if (au_h_iptr(inode, bindex) == h_inode) { ++ bfound = bindex; ++ break; ++ } ++ if (bfound < 0) ++ goto out; ++ ++ for (bindex = btop; bindex <= bbot; bindex++) { ++ h_i = au_h_iptr(inode, bindex); ++ if (!h_i) ++ continue; ++ ++ err = au_xino_write(inode->i_sb, bindex, h_i->i_ino, /*ino*/0); ++ /* ignore this error */ ++ /* bad action? */ ++ } ++ ++ /* children inode number will be broken */ ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++static int hn_gen_tree(struct dentry *dentry) ++{ ++ int err, i, j, ndentry; ++ struct au_dcsub_pages dpages; ++ struct au_dpage *dpage; ++ struct dentry **dentries; ++ ++ err = au_dpages_init(&dpages, GFP_NOFS); ++ if (unlikely(err)) ++ goto out; ++ err = au_dcsub_pages(&dpages, dentry, NULL, NULL); ++ if (unlikely(err)) ++ goto out_dpages; ++ ++ for (i = 0; i < dpages.ndpage; i++) { ++ dpage = dpages.dpages + i; ++ dentries = dpage->dentries; ++ ndentry = dpage->ndentry; ++ for (j = 0; j < ndentry; j++) { ++ struct dentry *d; ++ ++ d = dentries[j]; ++ if (IS_ROOT(d)) ++ continue; ++ ++ au_digen_dec(d); ++ if (d_really_is_positive(d)) ++ /* todo: reset children xino? ++ cached children only? */ ++ au_iigen_dec(d_inode(d)); ++ } ++ } ++ ++out_dpages: ++ au_dpages_free(&dpages); ++ ++#if 0 ++ /* discard children */ ++ dentry_unhash(dentry); ++ dput(dentry); ++#endif ++out: ++ return err; ++} ++ ++/* ++ * return 0 if processed. ++ */ ++static int hn_gen_by_inode(char *name, unsigned int nlen, struct inode *inode, ++ const unsigned int isdir) ++{ ++ int err; ++ struct dentry *d; ++ struct qstr *dname; ++ ++ err = 1; ++ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) { ++ pr_warn("branch root dir was changed\n"); ++ err = 0; ++ goto out; ++ } ++ ++ if (!isdir) { ++ AuDebugOn(!name); ++ au_iigen_dec(inode); ++ spin_lock(&inode->i_lock); ++ hlist_for_each_entry(d, &inode->i_dentry, d_u.d_alias) { ++ spin_lock(&d->d_lock); ++ dname = &d->d_name; ++ if (dname->len != nlen ++ && memcmp(dname->name, name, nlen)) { ++ spin_unlock(&d->d_lock); ++ continue; ++ } ++ err = 0; ++ au_digen_dec(d); ++ spin_unlock(&d->d_lock); ++ break; ++ } ++ spin_unlock(&inode->i_lock); ++ } else { ++ au_fset_si(au_sbi(inode->i_sb), FAILED_REFRESH_DIR); ++ d = d_find_any_alias(inode); ++ if (!d) { ++ au_iigen_dec(inode); ++ goto out; ++ } ++ ++ spin_lock(&d->d_lock); ++ dname = &d->d_name; ++ if (dname->len == nlen && !memcmp(dname->name, name, nlen)) { ++ spin_unlock(&d->d_lock); ++ err = hn_gen_tree(d); ++ spin_lock(&d->d_lock); ++ } ++ spin_unlock(&d->d_lock); ++ dput(d); ++ } ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++static int hn_gen_by_name(struct dentry *dentry, const unsigned int isdir) ++{ ++ int err; ++ ++ if (IS_ROOT(dentry)) { ++ pr_warn("branch root dir was changed\n"); ++ return 0; ++ } ++ ++ err = 0; ++ if (!isdir) { ++ au_digen_dec(dentry); ++ if (d_really_is_positive(dentry)) ++ au_iigen_dec(d_inode(dentry)); ++ } else { ++ au_fset_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIR); ++ if (d_really_is_positive(dentry)) ++ err = hn_gen_tree(dentry); ++ } ++ ++ AuTraceErr(err); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* hnotify job flags */ ++#define AuHnJob_XINO0 1 ++#define AuHnJob_GEN (1 << 1) ++#define AuHnJob_DIRENT (1 << 2) ++#define AuHnJob_ISDIR (1 << 3) ++#define AuHnJob_TRYXINO0 (1 << 4) ++#define AuHnJob_MNTPNT (1 << 5) ++#define au_ftest_hnjob(flags, name) ((flags) & AuHnJob_##name) ++#define au_fset_hnjob(flags, name) \ ++ do { (flags) |= AuHnJob_##name; } while (0) ++#define au_fclr_hnjob(flags, name) \ ++ do { (flags) &= ~AuHnJob_##name; } while (0) ++ ++enum { ++ AuHn_CHILD, ++ AuHn_PARENT, ++ AuHnLast ++}; ++ ++struct au_hnotify_args { ++ struct inode *h_dir, *dir, *h_child_inode; ++ u32 mask; ++ unsigned int flags[AuHnLast]; ++ unsigned int h_child_nlen; ++ char h_child_name[]; ++}; ++ ++struct hn_job_args { ++ unsigned int flags; ++ struct inode *inode, *h_inode, *dir, *h_dir; ++ struct dentry *dentry; ++ char *h_name; ++ int h_nlen; ++}; ++ ++static int hn_job(struct hn_job_args *a) ++{ ++ const unsigned int isdir = au_ftest_hnjob(a->flags, ISDIR); ++ int e; ++ ++ /* reset xino */ ++ if (au_ftest_hnjob(a->flags, XINO0) && a->inode) ++ hn_xino(a->inode, a->h_inode); /* ignore this error */ ++ ++ if (au_ftest_hnjob(a->flags, TRYXINO0) ++ && a->inode ++ && a->h_inode) { ++ inode_lock_shared_nested(a->h_inode, AuLsc_I_CHILD); ++ if (!a->h_inode->i_nlink ++ && !(a->h_inode->i_state & I_LINKABLE)) ++ hn_xino(a->inode, a->h_inode); /* ignore this error */ ++ inode_unlock_shared(a->h_inode); ++ } ++ ++ /* make the generation obsolete */ ++ if (au_ftest_hnjob(a->flags, GEN)) { ++ e = -1; ++ if (a->inode) ++ e = hn_gen_by_inode(a->h_name, a->h_nlen, a->inode, ++ isdir); ++ if (e && a->dentry) ++ hn_gen_by_name(a->dentry, isdir); ++ /* ignore this error */ ++ } ++ ++ /* make dir entries obsolete */ ++ if (au_ftest_hnjob(a->flags, DIRENT) && a->inode) { ++ struct au_vdir *vdir; ++ ++ vdir = au_ivdir(a->inode); ++ if (vdir) ++ vdir->vd_jiffy = 0; ++ /* IMustLock(a->inode); */ ++ /* inode_inc_iversion(a->inode); */ ++ } ++ ++ /* can do nothing but warn */ ++ if (au_ftest_hnjob(a->flags, MNTPNT) ++ && a->dentry ++ && d_mountpoint(a->dentry)) ++ pr_warn("mount-point %pd is removed or renamed\n", a->dentry); ++ ++ return 0; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static struct dentry *lookup_wlock_by_name(char *name, unsigned int nlen, ++ struct inode *dir) ++{ ++ struct dentry *dentry, *d, *parent; ++ struct qstr *dname; ++ ++ parent = d_find_any_alias(dir); ++ if (!parent) ++ return NULL; ++ ++ dentry = NULL; ++ spin_lock(&parent->d_lock); ++ list_for_each_entry(d, &parent->d_subdirs, d_child) { ++ /* AuDbg("%pd\n", d); */ ++ spin_lock_nested(&d->d_lock, DENTRY_D_LOCK_NESTED); ++ dname = &d->d_name; ++ if (dname->len != nlen || memcmp(dname->name, name, nlen)) ++ goto cont_unlock; ++ if (au_di(d)) ++ au_digen_dec(d); ++ else ++ goto cont_unlock; ++ if (au_dcount(d) > 0) { ++ dentry = dget_dlock(d); ++ spin_unlock(&d->d_lock); ++ break; ++ } ++ ++cont_unlock: ++ spin_unlock(&d->d_lock); ++ } ++ spin_unlock(&parent->d_lock); ++ dput(parent); ++ ++ if (dentry) ++ di_write_lock_child(dentry); ++ ++ return dentry; ++} ++ ++static struct inode *lookup_wlock_by_ino(struct super_block *sb, ++ aufs_bindex_t bindex, ino_t h_ino) ++{ ++ struct inode *inode; ++ ino_t ino; ++ int err; ++ ++ inode = NULL; ++ err = au_xino_read(sb, bindex, h_ino, &ino); ++ if (!err && ino) ++ inode = ilookup(sb, ino); ++ if (!inode) ++ goto out; ++ ++ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) { ++ pr_warn("wrong root branch\n"); ++ iput(inode); ++ inode = NULL; ++ goto out; ++ } ++ ++ ii_write_lock_child(inode); ++ ++out: ++ return inode; ++} ++ ++static void au_hn_bh(void *_args) ++{ ++ struct au_hnotify_args *a = _args; ++ struct super_block *sb; ++ aufs_bindex_t bindex, bbot, bfound; ++ unsigned char xino, try_iput; ++ int err; ++ struct inode *inode; ++ ino_t h_ino; ++ struct hn_job_args args; ++ struct dentry *dentry; ++ struct au_sbinfo *sbinfo; ++ ++ AuDebugOn(!_args); ++ AuDebugOn(!a->h_dir); ++ AuDebugOn(!a->dir); ++ AuDebugOn(!a->mask); ++ AuDbg("mask 0x%x, i%lu, hi%lu, hci%lu\n", ++ a->mask, a->dir->i_ino, a->h_dir->i_ino, ++ a->h_child_inode ? a->h_child_inode->i_ino : 0); ++ ++ inode = NULL; ++ dentry = NULL; ++ /* ++ * do not lock a->dir->i_mutex here ++ * because of d_revalidate() may cause a deadlock. ++ */ ++ sb = a->dir->i_sb; ++ AuDebugOn(!sb); ++ sbinfo = au_sbi(sb); ++ AuDebugOn(!sbinfo); ++ si_write_lock(sb, AuLock_NOPLMW); ++ ++ if (au_opt_test(sbinfo->si_mntflags, DIRREN)) ++ switch (a->mask & FS_EVENTS_POSS_ON_CHILD) { ++ case FS_MOVED_FROM: ++ case FS_MOVED_TO: ++ AuWarn1("DIRREN with UDBA may not work correctly " ++ "for the direct rename(2)\n"); ++ } ++ ++ ii_read_lock_parent(a->dir); ++ bfound = -1; ++ bbot = au_ibbot(a->dir); ++ for (bindex = au_ibtop(a->dir); bindex <= bbot; bindex++) ++ if (au_h_iptr(a->dir, bindex) == a->h_dir) { ++ bfound = bindex; ++ break; ++ } ++ ii_read_unlock(a->dir); ++ if (unlikely(bfound < 0)) ++ goto out; ++ ++ xino = !!au_opt_test(au_mntflags(sb), XINO); ++ h_ino = 0; ++ if (a->h_child_inode) ++ h_ino = a->h_child_inode->i_ino; ++ ++ if (a->h_child_nlen ++ && (au_ftest_hnjob(a->flags[AuHn_CHILD], GEN) ++ || au_ftest_hnjob(a->flags[AuHn_CHILD], MNTPNT))) ++ dentry = lookup_wlock_by_name(a->h_child_name, a->h_child_nlen, ++ a->dir); ++ try_iput = 0; ++ if (dentry && d_really_is_positive(dentry)) ++ inode = d_inode(dentry); ++ if (xino && !inode && h_ino ++ && (au_ftest_hnjob(a->flags[AuHn_CHILD], XINO0) ++ || au_ftest_hnjob(a->flags[AuHn_CHILD], TRYXINO0) ++ || au_ftest_hnjob(a->flags[AuHn_CHILD], GEN))) { ++ inode = lookup_wlock_by_ino(sb, bfound, h_ino); ++ try_iput = 1; ++ } ++ ++ args.flags = a->flags[AuHn_CHILD]; ++ args.dentry = dentry; ++ args.inode = inode; ++ args.h_inode = a->h_child_inode; ++ args.dir = a->dir; ++ args.h_dir = a->h_dir; ++ args.h_name = a->h_child_name; ++ args.h_nlen = a->h_child_nlen; ++ err = hn_job(&args); ++ if (dentry) { ++ if (au_di(dentry)) ++ di_write_unlock(dentry); ++ dput(dentry); ++ } ++ if (inode && try_iput) { ++ ii_write_unlock(inode); ++ iput(inode); ++ } ++ ++ ii_write_lock_parent(a->dir); ++ args.flags = a->flags[AuHn_PARENT]; ++ args.dentry = NULL; ++ args.inode = a->dir; ++ args.h_inode = a->h_dir; ++ args.dir = NULL; ++ args.h_dir = NULL; ++ args.h_name = NULL; ++ args.h_nlen = 0; ++ err = hn_job(&args); ++ ii_write_unlock(a->dir); ++ ++out: ++ iput(a->h_child_inode); ++ iput(a->h_dir); ++ iput(a->dir); ++ si_write_unlock(sb); ++ au_nwt_done(&sbinfo->si_nowait); ++ au_kfree_rcu(a); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask, ++ const struct qstr *h_child_qstr, struct inode *h_child_inode) ++{ ++ int err, len; ++ unsigned int flags[AuHnLast], f; ++ unsigned char isdir, isroot, wh; ++ struct inode *dir; ++ struct au_hnotify_args *args; ++ char *p, *h_child_name; ++ ++ err = 0; ++ AuDebugOn(!hnotify || !hnotify->hn_aufs_inode); ++ dir = igrab(hnotify->hn_aufs_inode); ++ if (!dir) ++ goto out; ++ ++ isroot = (dir->i_ino == AUFS_ROOT_INO); ++ wh = 0; ++ h_child_name = (void *)h_child_qstr->name; ++ len = h_child_qstr->len; ++ if (h_child_name) { ++ if (len > AUFS_WH_PFX_LEN ++ && !memcmp(h_child_name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) { ++ h_child_name += AUFS_WH_PFX_LEN; ++ len -= AUFS_WH_PFX_LEN; ++ wh = 1; ++ } ++ } ++ ++ isdir = 0; ++ if (h_child_inode) ++ isdir = !!S_ISDIR(h_child_inode->i_mode); ++ flags[AuHn_PARENT] = AuHnJob_ISDIR; ++ flags[AuHn_CHILD] = 0; ++ if (isdir) ++ flags[AuHn_CHILD] = AuHnJob_ISDIR; ++ au_fset_hnjob(flags[AuHn_PARENT], DIRENT); ++ au_fset_hnjob(flags[AuHn_CHILD], GEN); ++ switch (mask & ALL_FSNOTIFY_DIRENT_EVENTS) { ++ case FS_MOVED_FROM: ++ case FS_MOVED_TO: ++ au_fset_hnjob(flags[AuHn_CHILD], XINO0); ++ au_fset_hnjob(flags[AuHn_CHILD], MNTPNT); ++ /*FALLTHROUGH*/ ++ case FS_CREATE: ++ AuDebugOn(!h_child_name); ++ break; ++ ++ case FS_DELETE: ++ /* ++ * aufs never be able to get this child inode. ++ * revalidation should be in d_revalidate() ++ * by checking i_nlink, i_generation or d_unhashed(). ++ */ ++ AuDebugOn(!h_child_name); ++ au_fset_hnjob(flags[AuHn_CHILD], TRYXINO0); ++ au_fset_hnjob(flags[AuHn_CHILD], MNTPNT); ++ break; ++ ++ default: ++ AuDebugOn(1); ++ } ++ ++ if (wh) ++ h_child_inode = NULL; ++ ++ err = -ENOMEM; ++ /* iput() and kfree() will be called in au_hnotify() */ ++ args = kmalloc(sizeof(*args) + len + 1, GFP_NOFS); ++ if (unlikely(!args)) { ++ AuErr1("no memory\n"); ++ iput(dir); ++ goto out; ++ } ++ args->flags[AuHn_PARENT] = flags[AuHn_PARENT]; ++ args->flags[AuHn_CHILD] = flags[AuHn_CHILD]; ++ args->mask = mask; ++ args->dir = dir; ++ args->h_dir = igrab(h_dir); ++ if (h_child_inode) ++ h_child_inode = igrab(h_child_inode); /* can be NULL */ ++ args->h_child_inode = h_child_inode; ++ args->h_child_nlen = len; ++ if (len) { ++ p = (void *)args; ++ p += sizeof(*args); ++ memcpy(p, h_child_name, len); ++ p[len] = 0; ++ } ++ ++ /* NFS fires the event for silly-renamed one from kworker */ ++ f = 0; ++ if (!dir->i_nlink ++ || (au_test_nfs(h_dir->i_sb) && (mask & FS_DELETE))) ++ f = AuWkq_NEST; ++ err = au_wkq_nowait(au_hn_bh, args, dir->i_sb, f); ++ if (unlikely(err)) { ++ pr_err("wkq %d\n", err); ++ iput(args->h_child_inode); ++ iput(args->h_dir); ++ iput(args->dir); ++ au_kfree_rcu(args); ++ } ++ ++out: ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++int au_hnotify_reset_br(unsigned int udba, struct au_branch *br, int perm) ++{ ++ int err; ++ ++ AuDebugOn(!(udba & AuOptMask_UDBA)); ++ ++ err = 0; ++ if (au_hnotify_op.reset_br) ++ err = au_hnotify_op.reset_br(udba, br, perm); ++ ++ return err; ++} ++ ++int au_hnotify_init_br(struct au_branch *br, int perm) ++{ ++ int err; ++ ++ err = 0; ++ if (au_hnotify_op.init_br) ++ err = au_hnotify_op.init_br(br, perm); ++ ++ return err; ++} ++ ++void au_hnotify_fin_br(struct au_branch *br) ++{ ++ if (au_hnotify_op.fin_br) ++ au_hnotify_op.fin_br(br); ++} ++ ++static void au_hn_destroy_cache(void) ++{ ++ kmem_cache_destroy(au_cache[AuCache_HNOTIFY]); ++ au_cache[AuCache_HNOTIFY] = NULL; ++} ++ ++int __init au_hnotify_init(void) ++{ ++ int err; ++ ++ err = -ENOMEM; ++ au_cache[AuCache_HNOTIFY] = AuCache(au_hnotify); ++ if (au_cache[AuCache_HNOTIFY]) { ++ err = 0; ++ if (au_hnotify_op.init) ++ err = au_hnotify_op.init(); ++ if (unlikely(err)) ++ au_hn_destroy_cache(); ++ } ++ AuTraceErr(err); ++ return err; ++} ++ ++void au_hnotify_fin(void) ++{ ++ if (au_hnotify_op.fin) ++ au_hnotify_op.fin(); ++ ++ /* cf. au_cache_fin() */ ++ if (au_cache[AuCache_HNOTIFY]) ++ au_hn_destroy_cache(); ++} +diff -Nurp linux-5.4/fs/aufs/iinfo.c linux-5.4-aufs/fs/aufs/iinfo.c +--- linux-5.4/fs/aufs/iinfo.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/iinfo.c 2019-11-28 01:25:59.066925618 +0200 +@@ -0,0 +1,273 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * inode private data ++ */ ++ ++#include "aufs.h" ++ ++struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex) ++{ ++ struct inode *h_inode; ++ struct au_hinode *hinode; ++ ++ IiMustAnyLock(inode); ++ ++ hinode = au_hinode(au_ii(inode), bindex); ++ h_inode = hinode->hi_inode; ++ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0); ++ return h_inode; ++} ++ ++/* todo: hard/soft set? */ ++void au_hiput(struct au_hinode *hinode) ++{ ++ au_hn_free(hinode); ++ dput(hinode->hi_whdentry); ++ iput(hinode->hi_inode); ++} ++ ++unsigned int au_hi_flags(struct inode *inode, int isdir) ++{ ++ unsigned int flags; ++ const unsigned int mnt_flags = au_mntflags(inode->i_sb); ++ ++ flags = 0; ++ if (au_opt_test(mnt_flags, XINO)) ++ au_fset_hi(flags, XINO); ++ if (isdir && au_opt_test(mnt_flags, UDBA_HNOTIFY)) ++ au_fset_hi(flags, HNOTIFY); ++ return flags; ++} ++ ++void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex, ++ struct inode *h_inode, unsigned int flags) ++{ ++ struct au_hinode *hinode; ++ struct inode *hi; ++ struct au_iinfo *iinfo = au_ii(inode); ++ ++ IiMustWriteLock(inode); ++ ++ hinode = au_hinode(iinfo, bindex); ++ hi = hinode->hi_inode; ++ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0); ++ ++ if (hi) ++ au_hiput(hinode); ++ hinode->hi_inode = h_inode; ++ if (h_inode) { ++ int err; ++ struct super_block *sb = inode->i_sb; ++ struct au_branch *br; ++ ++ AuDebugOn(inode->i_mode ++ && (h_inode->i_mode & S_IFMT) ++ != (inode->i_mode & S_IFMT)); ++ if (bindex == iinfo->ii_btop) ++ au_cpup_igen(inode, h_inode); ++ br = au_sbr(sb, bindex); ++ hinode->hi_id = br->br_id; ++ if (au_ftest_hi(flags, XINO)) { ++ err = au_xino_write(sb, bindex, h_inode->i_ino, ++ inode->i_ino); ++ if (unlikely(err)) ++ AuIOErr1("failed au_xino_write() %d\n", err); ++ } ++ ++ if (au_ftest_hi(flags, HNOTIFY) ++ && au_br_hnotifyable(br->br_perm)) { ++ err = au_hn_alloc(hinode, inode); ++ if (unlikely(err)) ++ AuIOErr1("au_hn_alloc() %d\n", err); ++ } ++ } ++} ++ ++void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex, ++ struct dentry *h_wh) ++{ ++ struct au_hinode *hinode; ++ ++ IiMustWriteLock(inode); ++ ++ hinode = au_hinode(au_ii(inode), bindex); ++ AuDebugOn(hinode->hi_whdentry); ++ hinode->hi_whdentry = h_wh; ++} ++ ++void au_update_iigen(struct inode *inode, int half) ++{ ++ struct au_iinfo *iinfo; ++ struct au_iigen *iigen; ++ unsigned int sigen; ++ ++ sigen = au_sigen(inode->i_sb); ++ iinfo = au_ii(inode); ++ iigen = &iinfo->ii_generation; ++ spin_lock(&iigen->ig_spin); ++ iigen->ig_generation = sigen; ++ if (half) ++ au_ig_fset(iigen->ig_flags, HALF_REFRESHED); ++ else ++ au_ig_fclr(iigen->ig_flags, HALF_REFRESHED); ++ spin_unlock(&iigen->ig_spin); ++} ++ ++/* it may be called at remount time, too */ ++void au_update_ibrange(struct inode *inode, int do_put_zero) ++{ ++ struct au_iinfo *iinfo; ++ aufs_bindex_t bindex, bbot; ++ ++ AuDebugOn(au_is_bad_inode(inode)); ++ IiMustWriteLock(inode); ++ ++ iinfo = au_ii(inode); ++ if (do_put_zero && iinfo->ii_btop >= 0) { ++ for (bindex = iinfo->ii_btop; bindex <= iinfo->ii_bbot; ++ bindex++) { ++ struct inode *h_i; ++ ++ h_i = au_hinode(iinfo, bindex)->hi_inode; ++ if (h_i ++ && !h_i->i_nlink ++ && !(h_i->i_state & I_LINKABLE)) ++ au_set_h_iptr(inode, bindex, NULL, 0); ++ } ++ } ++ ++ iinfo->ii_btop = -1; ++ iinfo->ii_bbot = -1; ++ bbot = au_sbbot(inode->i_sb); ++ for (bindex = 0; bindex <= bbot; bindex++) ++ if (au_hinode(iinfo, bindex)->hi_inode) { ++ iinfo->ii_btop = bindex; ++ break; ++ } ++ if (iinfo->ii_btop >= 0) ++ for (bindex = bbot; bindex >= iinfo->ii_btop; bindex--) ++ if (au_hinode(iinfo, bindex)->hi_inode) { ++ iinfo->ii_bbot = bindex; ++ break; ++ } ++ AuDebugOn(iinfo->ii_btop > iinfo->ii_bbot); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++void au_icntnr_init_once(void *_c) ++{ ++ struct au_icntnr *c = _c; ++ struct au_iinfo *iinfo = &c->iinfo; ++ ++ spin_lock_init(&iinfo->ii_generation.ig_spin); ++ au_rw_init(&iinfo->ii_rwsem); ++ inode_init_once(&c->vfs_inode); ++} ++ ++void au_hinode_init(struct au_hinode *hinode) ++{ ++ hinode->hi_inode = NULL; ++ hinode->hi_id = -1; ++ au_hn_init(hinode); ++ hinode->hi_whdentry = NULL; ++} ++ ++int au_iinfo_init(struct inode *inode) ++{ ++ struct au_iinfo *iinfo; ++ struct super_block *sb; ++ struct au_hinode *hi; ++ int nbr, i; ++ ++ sb = inode->i_sb; ++ iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo); ++ nbr = au_sbbot(sb) + 1; ++ if (unlikely(nbr <= 0)) ++ nbr = 1; ++ hi = kmalloc_array(nbr, sizeof(*iinfo->ii_hinode), GFP_NOFS); ++ if (hi) { ++ au_lcnt_inc(&au_sbi(sb)->si_ninodes); ++ ++ iinfo->ii_hinode = hi; ++ for (i = 0; i < nbr; i++, hi++) ++ au_hinode_init(hi); ++ ++ iinfo->ii_generation.ig_generation = au_sigen(sb); ++ iinfo->ii_btop = -1; ++ iinfo->ii_bbot = -1; ++ iinfo->ii_vdir = NULL; ++ return 0; ++ } ++ return -ENOMEM; ++} ++ ++int au_hinode_realloc(struct au_iinfo *iinfo, int nbr, int may_shrink) ++{ ++ int err, i; ++ struct au_hinode *hip; ++ ++ AuRwMustWriteLock(&iinfo->ii_rwsem); ++ ++ err = -ENOMEM; ++ hip = au_krealloc(iinfo->ii_hinode, sizeof(*hip) * nbr, GFP_NOFS, ++ may_shrink); ++ if (hip) { ++ iinfo->ii_hinode = hip; ++ i = iinfo->ii_bbot + 1; ++ hip += i; ++ for (; i < nbr; i++, hip++) ++ au_hinode_init(hip); ++ err = 0; ++ } ++ ++ return err; ++} ++ ++void au_iinfo_fin(struct inode *inode) ++{ ++ struct au_iinfo *iinfo; ++ struct au_hinode *hi; ++ struct super_block *sb; ++ aufs_bindex_t bindex, bbot; ++ const unsigned char unlinked = !inode->i_nlink; ++ ++ AuDebugOn(au_is_bad_inode(inode)); ++ ++ sb = inode->i_sb; ++ au_lcnt_dec(&au_sbi(sb)->si_ninodes); ++ if (si_pid_test(sb)) ++ au_xino_delete_inode(inode, unlinked); ++ else { ++ /* ++ * it is safe to hide the dependency between sbinfo and ++ * sb->s_umount. ++ */ ++ lockdep_off(); ++ si_noflush_read_lock(sb); ++ au_xino_delete_inode(inode, unlinked); ++ si_read_unlock(sb); ++ lockdep_on(); ++ } ++ ++ iinfo = au_ii(inode); ++ if (iinfo->ii_vdir) ++ au_vdir_free(iinfo->ii_vdir); ++ ++ bindex = iinfo->ii_btop; ++ if (bindex >= 0) { ++ hi = au_hinode(iinfo, bindex); ++ bbot = iinfo->ii_bbot; ++ while (bindex++ <= bbot) { ++ if (hi->hi_inode) ++ au_hiput(hi); ++ hi++; ++ } ++ } ++ au_kfree_rcu(iinfo->ii_hinode); ++ AuRwDestroy(&iinfo->ii_rwsem); ++} +diff -Nurp linux-5.4/fs/aufs/inode.c linux-5.4-aufs/fs/aufs/inode.c +--- linux-5.4/fs/aufs/inode.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/inode.c 2019-11-28 01:25:59.066925618 +0200 +@@ -0,0 +1,516 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * inode functions ++ */ ++ ++#include ++#include "aufs.h" ++ ++struct inode *au_igrab(struct inode *inode) ++{ ++ if (inode) { ++ AuDebugOn(!atomic_read(&inode->i_count)); ++ ihold(inode); ++ } ++ return inode; ++} ++ ++static void au_refresh_hinode_attr(struct inode *inode, int do_version) ++{ ++ au_cpup_attr_all(inode, /*force*/0); ++ au_update_iigen(inode, /*half*/1); ++ if (do_version) ++ inode_inc_iversion(inode); ++} ++ ++static int au_ii_refresh(struct inode *inode, int *update) ++{ ++ int err, e, nbr; ++ umode_t type; ++ aufs_bindex_t bindex, new_bindex; ++ struct super_block *sb; ++ struct au_iinfo *iinfo; ++ struct au_hinode *p, *q, tmp; ++ ++ AuDebugOn(au_is_bad_inode(inode)); ++ IiMustWriteLock(inode); ++ ++ *update = 0; ++ sb = inode->i_sb; ++ nbr = au_sbbot(sb) + 1; ++ type = inode->i_mode & S_IFMT; ++ iinfo = au_ii(inode); ++ err = au_hinode_realloc(iinfo, nbr, /*may_shrink*/0); ++ if (unlikely(err)) ++ goto out; ++ ++ AuDebugOn(iinfo->ii_btop < 0); ++ p = au_hinode(iinfo, iinfo->ii_btop); ++ for (bindex = iinfo->ii_btop; bindex <= iinfo->ii_bbot; ++ bindex++, p++) { ++ if (!p->hi_inode) ++ continue; ++ ++ AuDebugOn(type != (p->hi_inode->i_mode & S_IFMT)); ++ new_bindex = au_br_index(sb, p->hi_id); ++ if (new_bindex == bindex) ++ continue; ++ ++ if (new_bindex < 0) { ++ *update = 1; ++ au_hiput(p); ++ p->hi_inode = NULL; ++ continue; ++ } ++ ++ if (new_bindex < iinfo->ii_btop) ++ iinfo->ii_btop = new_bindex; ++ if (iinfo->ii_bbot < new_bindex) ++ iinfo->ii_bbot = new_bindex; ++ /* swap two lower inode, and loop again */ ++ q = au_hinode(iinfo, new_bindex); ++ tmp = *q; ++ *q = *p; ++ *p = tmp; ++ if (tmp.hi_inode) { ++ bindex--; ++ p--; ++ } ++ } ++ au_update_ibrange(inode, /*do_put_zero*/0); ++ au_hinode_realloc(iinfo, nbr, /*may_shrink*/1); /* harmless if err */ ++ e = au_dy_irefresh(inode); ++ if (unlikely(e && !err)) ++ err = e; ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++void au_refresh_iop(struct inode *inode, int force_getattr) ++{ ++ int type; ++ struct au_sbinfo *sbi = au_sbi(inode->i_sb); ++ const struct inode_operations *iop ++ = force_getattr ? aufs_iop : sbi->si_iop_array; ++ ++ if (inode->i_op == iop) ++ return; ++ ++ switch (inode->i_mode & S_IFMT) { ++ case S_IFDIR: ++ type = AuIop_DIR; ++ break; ++ case S_IFLNK: ++ type = AuIop_SYMLINK; ++ break; ++ default: ++ type = AuIop_OTHER; ++ break; ++ } ++ ++ inode->i_op = iop + type; ++ /* unnecessary smp_wmb() */ ++} ++ ++int au_refresh_hinode_self(struct inode *inode) ++{ ++ int err, update; ++ ++ err = au_ii_refresh(inode, &update); ++ if (!err) ++ au_refresh_hinode_attr(inode, update && S_ISDIR(inode->i_mode)); ++ ++ AuTraceErr(err); ++ return err; ++} ++ ++int au_refresh_hinode(struct inode *inode, struct dentry *dentry) ++{ ++ int err, e, update; ++ unsigned int flags; ++ umode_t mode; ++ aufs_bindex_t bindex, bbot; ++ unsigned char isdir; ++ struct au_hinode *p; ++ struct au_iinfo *iinfo; ++ ++ err = au_ii_refresh(inode, &update); ++ if (unlikely(err)) ++ goto out; ++ ++ update = 0; ++ iinfo = au_ii(inode); ++ p = au_hinode(iinfo, iinfo->ii_btop); ++ mode = (inode->i_mode & S_IFMT); ++ isdir = S_ISDIR(mode); ++ flags = au_hi_flags(inode, isdir); ++ bbot = au_dbbot(dentry); ++ for (bindex = au_dbtop(dentry); bindex <= bbot; bindex++) { ++ struct inode *h_i, *h_inode; ++ struct dentry *h_d; ++ ++ h_d = au_h_dptr(dentry, bindex); ++ if (!h_d || d_is_negative(h_d)) ++ continue; ++ ++ h_inode = d_inode(h_d); ++ AuDebugOn(mode != (h_inode->i_mode & S_IFMT)); ++ if (iinfo->ii_btop <= bindex && bindex <= iinfo->ii_bbot) { ++ h_i = au_h_iptr(inode, bindex); ++ if (h_i) { ++ if (h_i == h_inode) ++ continue; ++ err = -EIO; ++ break; ++ } ++ } ++ if (bindex < iinfo->ii_btop) ++ iinfo->ii_btop = bindex; ++ if (iinfo->ii_bbot < bindex) ++ iinfo->ii_bbot = bindex; ++ au_set_h_iptr(inode, bindex, au_igrab(h_inode), flags); ++ update = 1; ++ } ++ au_update_ibrange(inode, /*do_put_zero*/0); ++ e = au_dy_irefresh(inode); ++ if (unlikely(e && !err)) ++ err = e; ++ if (!err) ++ au_refresh_hinode_attr(inode, update && isdir); ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++static int set_inode(struct inode *inode, struct dentry *dentry) ++{ ++ int err; ++ unsigned int flags; ++ umode_t mode; ++ aufs_bindex_t bindex, btop, btail; ++ unsigned char isdir; ++ struct dentry *h_dentry; ++ struct inode *h_inode; ++ struct au_iinfo *iinfo; ++ struct inode_operations *iop; ++ ++ IiMustWriteLock(inode); ++ ++ err = 0; ++ isdir = 0; ++ iop = au_sbi(inode->i_sb)->si_iop_array; ++ btop = au_dbtop(dentry); ++ h_dentry = au_h_dptr(dentry, btop); ++ h_inode = d_inode(h_dentry); ++ mode = h_inode->i_mode; ++ switch (mode & S_IFMT) { ++ case S_IFREG: ++ btail = au_dbtail(dentry); ++ inode->i_op = iop + AuIop_OTHER; ++ inode->i_fop = &aufs_file_fop; ++ err = au_dy_iaop(inode, btop, h_inode); ++ if (unlikely(err)) ++ goto out; ++ break; ++ case S_IFDIR: ++ isdir = 1; ++ btail = au_dbtaildir(dentry); ++ inode->i_op = iop + AuIop_DIR; ++ inode->i_fop = &aufs_dir_fop; ++ break; ++ case S_IFLNK: ++ btail = au_dbtail(dentry); ++ inode->i_op = iop + AuIop_SYMLINK; ++ break; ++ case S_IFBLK: ++ case S_IFCHR: ++ case S_IFIFO: ++ case S_IFSOCK: ++ btail = au_dbtail(dentry); ++ inode->i_op = iop + AuIop_OTHER; ++ init_special_inode(inode, mode, h_inode->i_rdev); ++ break; ++ default: ++ AuIOErr("Unknown file type 0%o\n", mode); ++ err = -EIO; ++ goto out; ++ } ++ ++ /* do not set hnotify for whiteouted dirs (SHWH mode) */ ++ flags = au_hi_flags(inode, isdir); ++ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH) ++ && au_ftest_hi(flags, HNOTIFY) ++ && dentry->d_name.len > AUFS_WH_PFX_LEN ++ && !memcmp(dentry->d_name.name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) ++ au_fclr_hi(flags, HNOTIFY); ++ iinfo = au_ii(inode); ++ iinfo->ii_btop = btop; ++ iinfo->ii_bbot = btail; ++ for (bindex = btop; bindex <= btail; bindex++) { ++ h_dentry = au_h_dptr(dentry, bindex); ++ if (h_dentry) ++ au_set_h_iptr(inode, bindex, ++ au_igrab(d_inode(h_dentry)), flags); ++ } ++ au_cpup_attr_all(inode, /*force*/1); ++ /* ++ * to force calling aufs_get_acl() every time, ++ * do not call cache_no_acl() for aufs inode. ++ */ ++ ++out: ++ return err; ++} ++ ++/* ++ * successful returns with iinfo write_locked ++ * minus: errno ++ * zero: success, matched ++ * plus: no error, but unmatched ++ */ ++static int reval_inode(struct inode *inode, struct dentry *dentry) ++{ ++ int err; ++ unsigned int gen, igflags; ++ aufs_bindex_t bindex, bbot; ++ struct inode *h_inode, *h_dinode; ++ struct dentry *h_dentry; ++ ++ /* ++ * before this function, if aufs got any iinfo lock, it must be only ++ * one, the parent dir. ++ * it can happen by UDBA and the obsoleted inode number. ++ */ ++ err = -EIO; ++ if (unlikely(inode->i_ino == parent_ino(dentry))) ++ goto out; ++ ++ err = 1; ++ ii_write_lock_new_child(inode); ++ h_dentry = au_h_dptr(dentry, au_dbtop(dentry)); ++ h_dinode = d_inode(h_dentry); ++ bbot = au_ibbot(inode); ++ for (bindex = au_ibtop(inode); bindex <= bbot; bindex++) { ++ h_inode = au_h_iptr(inode, bindex); ++ if (!h_inode || h_inode != h_dinode) ++ continue; ++ ++ err = 0; ++ gen = au_iigen(inode, &igflags); ++ if (gen == au_digen(dentry) ++ && !au_ig_ftest(igflags, HALF_REFRESHED)) ++ break; ++ ++ /* fully refresh inode using dentry */ ++ err = au_refresh_hinode(inode, dentry); ++ if (!err) ++ au_update_iigen(inode, /*half*/0); ++ break; ++ } ++ ++ if (unlikely(err)) ++ ii_write_unlock(inode); ++out: ++ return err; ++} ++ ++int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, ++ unsigned int d_type, ino_t *ino) ++{ ++ int err, idx; ++ const int isnondir = d_type != DT_DIR; ++ ++ /* prevent hardlinked inode number from race condition */ ++ if (isnondir) { ++ err = au_xinondir_enter(sb, bindex, h_ino, &idx); ++ if (unlikely(err)) ++ goto out; ++ } ++ ++ err = au_xino_read(sb, bindex, h_ino, ino); ++ if (unlikely(err)) ++ goto out_xinondir; ++ ++ if (!*ino) { ++ err = -EIO; ++ *ino = au_xino_new_ino(sb); ++ if (unlikely(!*ino)) ++ goto out_xinondir; ++ err = au_xino_write(sb, bindex, h_ino, *ino); ++ if (unlikely(err)) ++ goto out_xinondir; ++ } ++ ++out_xinondir: ++ if (isnondir && idx >= 0) ++ au_xinondir_leave(sb, bindex, h_ino, idx); ++out: ++ return err; ++} ++ ++/* successful returns with iinfo write_locked */ ++/* todo: return with unlocked? */ ++struct inode *au_new_inode(struct dentry *dentry, int must_new) ++{ ++ struct inode *inode, *h_inode; ++ struct dentry *h_dentry; ++ struct super_block *sb; ++ ino_t h_ino, ino; ++ int err, idx, hlinked; ++ aufs_bindex_t btop; ++ ++ sb = dentry->d_sb; ++ btop = au_dbtop(dentry); ++ h_dentry = au_h_dptr(dentry, btop); ++ h_inode = d_inode(h_dentry); ++ h_ino = h_inode->i_ino; ++ hlinked = !d_is_dir(h_dentry) && h_inode->i_nlink > 1; ++ ++new_ino: ++ /* ++ * stop 'race'-ing between hardlinks under different ++ * parents. ++ */ ++ if (hlinked) { ++ err = au_xinondir_enter(sb, btop, h_ino, &idx); ++ inode = ERR_PTR(err); ++ if (unlikely(err)) ++ goto out; ++ } ++ ++ err = au_xino_read(sb, btop, h_ino, &ino); ++ inode = ERR_PTR(err); ++ if (unlikely(err)) ++ goto out_xinondir; ++ ++ if (!ino) { ++ ino = au_xino_new_ino(sb); ++ if (unlikely(!ino)) { ++ inode = ERR_PTR(-EIO); ++ goto out_xinondir; ++ } ++ } ++ ++ AuDbg("i%lu\n", (unsigned long)ino); ++ inode = au_iget_locked(sb, ino); ++ err = PTR_ERR(inode); ++ if (IS_ERR(inode)) ++ goto out_xinondir; ++ ++ AuDbg("%lx, new %d\n", inode->i_state, !!(inode->i_state & I_NEW)); ++ if (inode->i_state & I_NEW) { ++ ii_write_lock_new_child(inode); ++ err = set_inode(inode, dentry); ++ if (!err) { ++ unlock_new_inode(inode); ++ goto out_xinondir; /* success */ ++ } ++ ++ /* ++ * iget_failed() calls iput(), but we need to call ++ * ii_write_unlock() after iget_failed(). so dirty hack for ++ * i_count. ++ */ ++ atomic_inc(&inode->i_count); ++ iget_failed(inode); ++ ii_write_unlock(inode); ++ au_xino_write(sb, btop, h_ino, /*ino*/0); ++ /* ignore this error */ ++ goto out_iput; ++ } else if (!must_new && !IS_DEADDIR(inode) && inode->i_nlink) { ++ /* ++ * horrible race condition between lookup, readdir and copyup ++ * (or something). ++ */ ++ if (hlinked && idx >= 0) ++ au_xinondir_leave(sb, btop, h_ino, idx); ++ err = reval_inode(inode, dentry); ++ if (unlikely(err < 0)) { ++ hlinked = 0; ++ goto out_iput; ++ } ++ if (!err) ++ goto out; /* success */ ++ else if (hlinked && idx >= 0) { ++ err = au_xinondir_enter(sb, btop, h_ino, &idx); ++ if (unlikely(err)) { ++ iput(inode); ++ inode = ERR_PTR(err); ++ goto out; ++ } ++ } ++ } ++ ++ if (unlikely(au_test_fs_unique_ino(h_inode))) ++ AuWarn1("Warning: Un-notified UDBA or repeatedly renamed dir," ++ " b%d, %s, %pd, hi%lu, i%lu.\n", ++ btop, au_sbtype(h_dentry->d_sb), dentry, ++ (unsigned long)h_ino, (unsigned long)ino); ++ ino = 0; ++ err = au_xino_write(sb, btop, h_ino, /*ino*/0); ++ if (!err) { ++ iput(inode); ++ if (hlinked && idx >= 0) ++ au_xinondir_leave(sb, btop, h_ino, idx); ++ goto new_ino; ++ } ++ ++out_iput: ++ iput(inode); ++ inode = ERR_PTR(err); ++out_xinondir: ++ if (hlinked && idx >= 0) ++ au_xinondir_leave(sb, btop, h_ino, idx); ++out: ++ return inode; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++int au_test_ro(struct super_block *sb, aufs_bindex_t bindex, ++ struct inode *inode) ++{ ++ int err; ++ struct inode *hi; ++ ++ err = au_br_rdonly(au_sbr(sb, bindex)); ++ ++ /* pseudo-link after flushed may happen out of bounds */ ++ if (!err ++ && inode ++ && au_ibtop(inode) <= bindex ++ && bindex <= au_ibbot(inode)) { ++ /* ++ * permission check is unnecessary since vfsub routine ++ * will be called later ++ */ ++ hi = au_h_iptr(inode, bindex); ++ if (hi) ++ err = IS_IMMUTABLE(hi) ? -EROFS : 0; ++ } ++ ++ return err; ++} ++ ++int au_test_h_perm(struct inode *h_inode, int mask) ++{ ++ if (uid_eq(current_fsuid(), GLOBAL_ROOT_UID)) ++ return 0; ++ return inode_permission(h_inode, mask); ++} ++ ++int au_test_h_perm_sio(struct inode *h_inode, int mask) ++{ ++ if (au_test_nfs(h_inode->i_sb) ++ && (mask & MAY_WRITE) ++ && S_ISDIR(h_inode->i_mode)) ++ mask |= MAY_READ; /* force permission check */ ++ return au_test_h_perm(h_inode, mask); ++} +diff -Nurp linux-5.4/fs/aufs/inode.h linux-5.4-aufs/fs/aufs/inode.h +--- linux-5.4/fs/aufs/inode.h 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/inode.h 2019-11-28 01:25:59.066925618 +0200 +@@ -0,0 +1,685 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * inode operations ++ */ ++ ++#ifndef __AUFS_INODE_H__ ++#define __AUFS_INODE_H__ ++ ++#ifdef __KERNEL__ ++ ++#include ++#include "rwsem.h" ++ ++struct vfsmount; ++ ++struct au_hnotify { ++#ifdef CONFIG_AUFS_HNOTIFY ++#ifdef CONFIG_AUFS_HFSNOTIFY ++ /* never use fsnotify_add_vfsmount_mark() */ ++ struct fsnotify_mark hn_mark; ++#endif ++ struct inode *hn_aufs_inode; /* no get/put */ ++ struct rcu_head rcu; ++#endif ++} ____cacheline_aligned_in_smp; ++ ++struct au_hinode { ++ struct inode *hi_inode; ++ aufs_bindex_t hi_id; ++#ifdef CONFIG_AUFS_HNOTIFY ++ struct au_hnotify *hi_notify; ++#endif ++ ++ /* reference to the copied-up whiteout with get/put */ ++ struct dentry *hi_whdentry; ++}; ++ ++/* ig_flags */ ++#define AuIG_HALF_REFRESHED 1 ++#define au_ig_ftest(flags, name) ((flags) & AuIG_##name) ++#define au_ig_fset(flags, name) \ ++ do { (flags) |= AuIG_##name; } while (0) ++#define au_ig_fclr(flags, name) \ ++ do { (flags) &= ~AuIG_##name; } while (0) ++ ++struct au_iigen { ++ spinlock_t ig_spin; ++ __u32 ig_generation, ig_flags; ++}; ++ ++struct au_vdir; ++struct au_iinfo { ++ struct au_iigen ii_generation; ++ struct super_block *ii_hsb1; /* no get/put */ ++ ++ struct au_rwsem ii_rwsem; ++ aufs_bindex_t ii_btop, ii_bbot; ++ __u32 ii_higen; ++ struct au_hinode *ii_hinode; ++ struct au_vdir *ii_vdir; ++}; ++ ++struct au_icntnr { ++ struct au_iinfo iinfo; ++ struct inode vfs_inode; ++ struct hlist_bl_node plink; ++ struct rcu_head rcu; ++} ____cacheline_aligned_in_smp; ++ ++/* au_pin flags */ ++#define AuPin_DI_LOCKED 1 ++#define AuPin_MNT_WRITE (1 << 1) ++#define au_ftest_pin(flags, name) ((flags) & AuPin_##name) ++#define au_fset_pin(flags, name) \ ++ do { (flags) |= AuPin_##name; } while (0) ++#define au_fclr_pin(flags, name) \ ++ do { (flags) &= ~AuPin_##name; } while (0) ++ ++struct au_pin { ++ /* input */ ++ struct dentry *dentry; ++ unsigned int udba; ++ unsigned char lsc_di, lsc_hi, flags; ++ aufs_bindex_t bindex; ++ ++ /* output */ ++ struct dentry *parent; ++ struct au_hinode *hdir; ++ struct vfsmount *h_mnt; ++ ++ /* temporary unlock/relock for copyup */ ++ struct dentry *h_dentry, *h_parent; ++ struct au_branch *br; ++ struct task_struct *task; ++}; ++ ++void au_pin_hdir_unlock(struct au_pin *p); ++int au_pin_hdir_lock(struct au_pin *p); ++int au_pin_hdir_relock(struct au_pin *p); ++void au_pin_hdir_acquire_nest(struct au_pin *p); ++void au_pin_hdir_release(struct au_pin *p); ++ ++/* ---------------------------------------------------------------------- */ ++ ++static inline struct au_iinfo *au_ii(struct inode *inode) ++{ ++ BUG_ON(is_bad_inode(inode)); ++ return &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* inode.c */ ++struct inode *au_igrab(struct inode *inode); ++void au_refresh_iop(struct inode *inode, int force_getattr); ++int au_refresh_hinode_self(struct inode *inode); ++int au_refresh_hinode(struct inode *inode, struct dentry *dentry); ++int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, ++ unsigned int d_type, ino_t *ino); ++struct inode *au_new_inode(struct dentry *dentry, int must_new); ++int au_test_ro(struct super_block *sb, aufs_bindex_t bindex, ++ struct inode *inode); ++int au_test_h_perm(struct inode *h_inode, int mask); ++int au_test_h_perm_sio(struct inode *h_inode, int mask); ++ ++static inline int au_wh_ino(struct super_block *sb, aufs_bindex_t bindex, ++ ino_t h_ino, unsigned int d_type, ino_t *ino) ++{ ++#ifdef CONFIG_AUFS_SHWH ++ return au_ino(sb, bindex, h_ino, d_type, ino); ++#else ++ return 0; ++#endif ++} ++ ++/* i_op.c */ ++enum { ++ AuIop_SYMLINK, ++ AuIop_DIR, ++ AuIop_OTHER, ++ AuIop_Last ++}; ++extern struct inode_operations aufs_iop[AuIop_Last], ++ aufs_iop_nogetattr[AuIop_Last]; ++ ++/* au_wr_dir flags */ ++#define AuWrDir_ADD_ENTRY 1 ++#define AuWrDir_ISDIR (1 << 1) ++#define AuWrDir_TMPFILE (1 << 2) ++#define au_ftest_wrdir(flags, name) ((flags) & AuWrDir_##name) ++#define au_fset_wrdir(flags, name) \ ++ do { (flags) |= AuWrDir_##name; } while (0) ++#define au_fclr_wrdir(flags, name) \ ++ do { (flags) &= ~AuWrDir_##name; } while (0) ++ ++struct au_wr_dir_args { ++ aufs_bindex_t force_btgt; ++ unsigned char flags; ++}; ++int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry, ++ struct au_wr_dir_args *args); ++ ++struct dentry *au_pinned_h_parent(struct au_pin *pin); ++void au_pin_init(struct au_pin *pin, struct dentry *dentry, ++ aufs_bindex_t bindex, int lsc_di, int lsc_hi, ++ unsigned int udba, unsigned char flags); ++int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex, ++ unsigned int udba, unsigned char flags) __must_check; ++int au_do_pin(struct au_pin *pin) __must_check; ++void au_unpin(struct au_pin *pin); ++int au_reval_for_attr(struct dentry *dentry, unsigned int sigen); ++ ++#define AuIcpup_DID_CPUP 1 ++#define au_ftest_icpup(flags, name) ((flags) & AuIcpup_##name) ++#define au_fset_icpup(flags, name) \ ++ do { (flags) |= AuIcpup_##name; } while (0) ++#define au_fclr_icpup(flags, name) \ ++ do { (flags) &= ~AuIcpup_##name; } while (0) ++ ++struct au_icpup_args { ++ unsigned char flags; ++ unsigned char pin_flags; ++ aufs_bindex_t btgt; ++ unsigned int udba; ++ struct au_pin pin; ++ struct path h_path; ++ struct inode *h_inode; ++}; ++ ++int au_pin_and_icpup(struct dentry *dentry, struct iattr *ia, ++ struct au_icpup_args *a); ++ ++int au_h_path_getattr(struct dentry *dentry, int force, struct path *h_path, ++ int locked); ++ ++/* i_op_add.c */ ++int au_may_add(struct dentry *dentry, aufs_bindex_t bindex, ++ struct dentry *h_parent, int isdir); ++int aufs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, ++ dev_t dev); ++int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname); ++int aufs_create(struct inode *dir, struct dentry *dentry, umode_t mode, ++ bool want_excl); ++struct vfsub_aopen_args; ++int au_aopen_or_create(struct inode *dir, struct dentry *dentry, ++ struct vfsub_aopen_args *args); ++int aufs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode); ++int aufs_link(struct dentry *src_dentry, struct inode *dir, ++ struct dentry *dentry); ++int aufs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode); ++ ++/* i_op_del.c */ ++int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup); ++int au_may_del(struct dentry *dentry, aufs_bindex_t bindex, ++ struct dentry *h_parent, int isdir); ++int aufs_unlink(struct inode *dir, struct dentry *dentry); ++int aufs_rmdir(struct inode *dir, struct dentry *dentry); ++ ++/* i_op_ren.c */ ++int au_wbr(struct dentry *dentry, aufs_bindex_t btgt); ++int aufs_rename(struct inode *src_dir, struct dentry *src_dentry, ++ struct inode *dir, struct dentry *dentry, ++ unsigned int flags); ++ ++/* iinfo.c */ ++struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex); ++void au_hiput(struct au_hinode *hinode); ++void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex, ++ struct dentry *h_wh); ++unsigned int au_hi_flags(struct inode *inode, int isdir); ++ ++/* hinode flags */ ++#define AuHi_XINO 1 ++#define AuHi_HNOTIFY (1 << 1) ++#define au_ftest_hi(flags, name) ((flags) & AuHi_##name) ++#define au_fset_hi(flags, name) \ ++ do { (flags) |= AuHi_##name; } while (0) ++#define au_fclr_hi(flags, name) \ ++ do { (flags) &= ~AuHi_##name; } while (0) ++ ++#ifndef CONFIG_AUFS_HNOTIFY ++#undef AuHi_HNOTIFY ++#define AuHi_HNOTIFY 0 ++#endif ++ ++void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex, ++ struct inode *h_inode, unsigned int flags); ++ ++void au_update_iigen(struct inode *inode, int half); ++void au_update_ibrange(struct inode *inode, int do_put_zero); ++ ++void au_icntnr_init_once(void *_c); ++void au_hinode_init(struct au_hinode *hinode); ++int au_iinfo_init(struct inode *inode); ++void au_iinfo_fin(struct inode *inode); ++int au_hinode_realloc(struct au_iinfo *iinfo, int nbr, int may_shrink); ++ ++#ifdef CONFIG_PROC_FS ++/* plink.c */ ++int au_plink_maint(struct super_block *sb, int flags); ++struct au_sbinfo; ++void au_plink_maint_leave(struct au_sbinfo *sbinfo); ++int au_plink_maint_enter(struct super_block *sb); ++#ifdef CONFIG_AUFS_DEBUG ++void au_plink_list(struct super_block *sb); ++#else ++AuStubVoid(au_plink_list, struct super_block *sb) ++#endif ++int au_plink_test(struct inode *inode); ++struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex); ++void au_plink_append(struct inode *inode, aufs_bindex_t bindex, ++ struct dentry *h_dentry); ++void au_plink_put(struct super_block *sb, int verbose); ++void au_plink_clean(struct super_block *sb, int verbose); ++void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id); ++#else ++AuStubInt0(au_plink_maint, struct super_block *sb, int flags); ++AuStubVoid(au_plink_maint_leave, struct au_sbinfo *sbinfo); ++AuStubInt0(au_plink_maint_enter, struct super_block *sb); ++AuStubVoid(au_plink_list, struct super_block *sb); ++AuStubInt0(au_plink_test, struct inode *inode); ++AuStub(struct dentry *, au_plink_lkup, return NULL, ++ struct inode *inode, aufs_bindex_t bindex); ++AuStubVoid(au_plink_append, struct inode *inode, aufs_bindex_t bindex, ++ struct dentry *h_dentry); ++AuStubVoid(au_plink_put, struct super_block *sb, int verbose); ++AuStubVoid(au_plink_clean, struct super_block *sb, int verbose); ++AuStubVoid(au_plink_half_refresh, struct super_block *sb, aufs_bindex_t br_id); ++#endif /* CONFIG_PROC_FS */ ++ ++#ifdef CONFIG_AUFS_XATTR ++/* xattr.c */ ++int au_cpup_xattr(struct dentry *h_dst, struct dentry *h_src, int ignore_flags, ++ unsigned int verbose); ++ssize_t aufs_listxattr(struct dentry *dentry, char *list, size_t size); ++void au_xattr_init(struct super_block *sb); ++#else ++AuStubInt0(au_cpup_xattr, struct dentry *h_dst, struct dentry *h_src, ++ int ignore_flags, unsigned int verbose); ++AuStubVoid(au_xattr_init, struct super_block *sb); ++#endif ++ ++#ifdef CONFIG_FS_POSIX_ACL ++struct posix_acl *aufs_get_acl(struct inode *inode, int type); ++int aufs_set_acl(struct inode *inode, struct posix_acl *acl, int type); ++#endif ++ ++#if IS_ENABLED(CONFIG_AUFS_XATTR) || IS_ENABLED(CONFIG_FS_POSIX_ACL) ++enum { ++ AU_XATTR_SET, ++ AU_ACL_SET ++}; ++ ++struct au_sxattr { ++ int type; ++ union { ++ struct { ++ const char *name; ++ const void *value; ++ size_t size; ++ int flags; ++ } set; ++ struct { ++ struct posix_acl *acl; ++ int type; ++ } acl_set; ++ } u; ++}; ++ssize_t au_sxattr(struct dentry *dentry, struct inode *inode, ++ struct au_sxattr *arg); ++#endif ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* lock subclass for iinfo */ ++enum { ++ AuLsc_II_CHILD, /* child first */ ++ AuLsc_II_CHILD2, /* rename(2), link(2), and cpup at hnotify */ ++ AuLsc_II_CHILD3, /* copyup dirs */ ++ AuLsc_II_PARENT, /* see AuLsc_I_PARENT in vfsub.h */ ++ AuLsc_II_PARENT2, ++ AuLsc_II_PARENT3, /* copyup dirs */ ++ AuLsc_II_NEW_CHILD ++}; ++ ++/* ++ * ii_read_lock_child, ii_write_lock_child, ++ * ii_read_lock_child2, ii_write_lock_child2, ++ * ii_read_lock_child3, ii_write_lock_child3, ++ * ii_read_lock_parent, ii_write_lock_parent, ++ * ii_read_lock_parent2, ii_write_lock_parent2, ++ * ii_read_lock_parent3, ii_write_lock_parent3, ++ * ii_read_lock_new_child, ii_write_lock_new_child, ++ */ ++#define AuReadLockFunc(name, lsc) \ ++static inline void ii_read_lock_##name(struct inode *i) \ ++{ \ ++ au_rw_read_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \ ++} ++ ++#define AuWriteLockFunc(name, lsc) \ ++static inline void ii_write_lock_##name(struct inode *i) \ ++{ \ ++ au_rw_write_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \ ++} ++ ++#define AuRWLockFuncs(name, lsc) \ ++ AuReadLockFunc(name, lsc) \ ++ AuWriteLockFunc(name, lsc) ++ ++AuRWLockFuncs(child, CHILD); ++AuRWLockFuncs(child2, CHILD2); ++AuRWLockFuncs(child3, CHILD3); ++AuRWLockFuncs(parent, PARENT); ++AuRWLockFuncs(parent2, PARENT2); ++AuRWLockFuncs(parent3, PARENT3); ++AuRWLockFuncs(new_child, NEW_CHILD); ++ ++#undef AuReadLockFunc ++#undef AuWriteLockFunc ++#undef AuRWLockFuncs ++ ++#define ii_read_unlock(i) au_rw_read_unlock(&au_ii(i)->ii_rwsem) ++#define ii_write_unlock(i) au_rw_write_unlock(&au_ii(i)->ii_rwsem) ++#define ii_downgrade_lock(i) au_rw_dgrade_lock(&au_ii(i)->ii_rwsem) ++ ++#define IiMustNoWaiters(i) AuRwMustNoWaiters(&au_ii(i)->ii_rwsem) ++#define IiMustAnyLock(i) AuRwMustAnyLock(&au_ii(i)->ii_rwsem) ++#define IiMustWriteLock(i) AuRwMustWriteLock(&au_ii(i)->ii_rwsem) ++ ++/* ---------------------------------------------------------------------- */ ++ ++static inline void au_icntnr_init(struct au_icntnr *c) ++{ ++#ifdef CONFIG_AUFS_DEBUG ++ c->vfs_inode.i_mode = 0; ++#endif ++} ++ ++static inline unsigned int au_iigen(struct inode *inode, unsigned int *igflags) ++{ ++ unsigned int gen; ++ struct au_iinfo *iinfo; ++ struct au_iigen *iigen; ++ ++ iinfo = au_ii(inode); ++ iigen = &iinfo->ii_generation; ++ spin_lock(&iigen->ig_spin); ++ if (igflags) ++ *igflags = iigen->ig_flags; ++ gen = iigen->ig_generation; ++ spin_unlock(&iigen->ig_spin); ++ ++ return gen; ++} ++ ++/* tiny test for inode number */ ++/* tmpfs generation is too rough */ ++static inline int au_test_higen(struct inode *inode, struct inode *h_inode) ++{ ++ struct au_iinfo *iinfo; ++ ++ iinfo = au_ii(inode); ++ AuRwMustAnyLock(&iinfo->ii_rwsem); ++ return !(iinfo->ii_hsb1 == h_inode->i_sb ++ && iinfo->ii_higen == h_inode->i_generation); ++} ++ ++static inline void au_iigen_dec(struct inode *inode) ++{ ++ struct au_iinfo *iinfo; ++ struct au_iigen *iigen; ++ ++ iinfo = au_ii(inode); ++ iigen = &iinfo->ii_generation; ++ spin_lock(&iigen->ig_spin); ++ iigen->ig_generation--; ++ spin_unlock(&iigen->ig_spin); ++} ++ ++static inline int au_iigen_test(struct inode *inode, unsigned int sigen) ++{ ++ int err; ++ ++ err = 0; ++ if (unlikely(inode && au_iigen(inode, NULL) != sigen)) ++ err = -EIO; ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static inline struct au_hinode *au_hinode(struct au_iinfo *iinfo, ++ aufs_bindex_t bindex) ++{ ++ return iinfo->ii_hinode + bindex; ++} ++ ++static inline int au_is_bad_inode(struct inode *inode) ++{ ++ return !!(is_bad_inode(inode) || !au_hinode(au_ii(inode), 0)); ++} ++ ++static inline aufs_bindex_t au_ii_br_id(struct inode *inode, ++ aufs_bindex_t bindex) ++{ ++ IiMustAnyLock(inode); ++ return au_hinode(au_ii(inode), bindex)->hi_id; ++} ++ ++static inline aufs_bindex_t au_ibtop(struct inode *inode) ++{ ++ IiMustAnyLock(inode); ++ return au_ii(inode)->ii_btop; ++} ++ ++static inline aufs_bindex_t au_ibbot(struct inode *inode) ++{ ++ IiMustAnyLock(inode); ++ return au_ii(inode)->ii_bbot; ++} ++ ++static inline struct au_vdir *au_ivdir(struct inode *inode) ++{ ++ IiMustAnyLock(inode); ++ return au_ii(inode)->ii_vdir; ++} ++ ++static inline struct dentry *au_hi_wh(struct inode *inode, aufs_bindex_t bindex) ++{ ++ IiMustAnyLock(inode); ++ return au_hinode(au_ii(inode), bindex)->hi_whdentry; ++} ++ ++static inline void au_set_ibtop(struct inode *inode, aufs_bindex_t bindex) ++{ ++ IiMustWriteLock(inode); ++ au_ii(inode)->ii_btop = bindex; ++} ++ ++static inline void au_set_ibbot(struct inode *inode, aufs_bindex_t bindex) ++{ ++ IiMustWriteLock(inode); ++ au_ii(inode)->ii_bbot = bindex; ++} ++ ++static inline void au_set_ivdir(struct inode *inode, struct au_vdir *vdir) ++{ ++ IiMustWriteLock(inode); ++ au_ii(inode)->ii_vdir = vdir; ++} ++ ++static inline struct au_hinode *au_hi(struct inode *inode, aufs_bindex_t bindex) ++{ ++ IiMustAnyLock(inode); ++ return au_hinode(au_ii(inode), bindex); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static inline struct dentry *au_pinned_parent(struct au_pin *pin) ++{ ++ if (pin) ++ return pin->parent; ++ return NULL; ++} ++ ++static inline struct inode *au_pinned_h_dir(struct au_pin *pin) ++{ ++ if (pin && pin->hdir) ++ return pin->hdir->hi_inode; ++ return NULL; ++} ++ ++static inline struct au_hinode *au_pinned_hdir(struct au_pin *pin) ++{ ++ if (pin) ++ return pin->hdir; ++ return NULL; ++} ++ ++static inline void au_pin_set_dentry(struct au_pin *pin, struct dentry *dentry) ++{ ++ if (pin) ++ pin->dentry = dentry; ++} ++ ++static inline void au_pin_set_parent_lflag(struct au_pin *pin, ++ unsigned char lflag) ++{ ++ if (pin) { ++ if (lflag) ++ au_fset_pin(pin->flags, DI_LOCKED); ++ else ++ au_fclr_pin(pin->flags, DI_LOCKED); ++ } ++} ++ ++#if 0 /* reserved */ ++static inline void au_pin_set_parent(struct au_pin *pin, struct dentry *parent) ++{ ++ if (pin) { ++ dput(pin->parent); ++ pin->parent = dget(parent); ++ } ++} ++#endif ++ ++/* ---------------------------------------------------------------------- */ ++ ++struct au_branch; ++#ifdef CONFIG_AUFS_HNOTIFY ++struct au_hnotify_op { ++ void (*ctl)(struct au_hinode *hinode, int do_set); ++ int (*alloc)(struct au_hinode *hinode); ++ ++ /* ++ * if it returns true, the the caller should free hinode->hi_notify, ++ * otherwise ->free() frees it. ++ */ ++ int (*free)(struct au_hinode *hinode, ++ struct au_hnotify *hn) __must_check; ++ ++ void (*fin)(void); ++ int (*init)(void); ++ ++ int (*reset_br)(unsigned int udba, struct au_branch *br, int perm); ++ void (*fin_br)(struct au_branch *br); ++ int (*init_br)(struct au_branch *br, int perm); ++}; ++ ++/* hnotify.c */ ++int au_hn_alloc(struct au_hinode *hinode, struct inode *inode); ++void au_hn_free(struct au_hinode *hinode); ++void au_hn_ctl(struct au_hinode *hinode, int do_set); ++void au_hn_reset(struct inode *inode, unsigned int flags); ++int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask, ++ const struct qstr *h_child_qstr, struct inode *h_child_inode); ++int au_hnotify_reset_br(unsigned int udba, struct au_branch *br, int perm); ++int au_hnotify_init_br(struct au_branch *br, int perm); ++void au_hnotify_fin_br(struct au_branch *br); ++int __init au_hnotify_init(void); ++void au_hnotify_fin(void); ++ ++/* hfsnotify.c */ ++extern const struct au_hnotify_op au_hnotify_op; ++ ++static inline ++void au_hn_init(struct au_hinode *hinode) ++{ ++ hinode->hi_notify = NULL; ++} ++ ++static inline struct au_hnotify *au_hn(struct au_hinode *hinode) ++{ ++ return hinode->hi_notify; ++} ++ ++#else ++AuStub(int, au_hn_alloc, return -EOPNOTSUPP, ++ struct au_hinode *hinode __maybe_unused, ++ struct inode *inode __maybe_unused) ++AuStub(struct au_hnotify *, au_hn, return NULL, struct au_hinode *hinode) ++AuStubVoid(au_hn_free, struct au_hinode *hinode __maybe_unused) ++AuStubVoid(au_hn_ctl, struct au_hinode *hinode __maybe_unused, ++ int do_set __maybe_unused) ++AuStubVoid(au_hn_reset, struct inode *inode __maybe_unused, ++ unsigned int flags __maybe_unused) ++AuStubInt0(au_hnotify_reset_br, unsigned int udba __maybe_unused, ++ struct au_branch *br __maybe_unused, ++ int perm __maybe_unused) ++AuStubInt0(au_hnotify_init_br, struct au_branch *br __maybe_unused, ++ int perm __maybe_unused) ++AuStubVoid(au_hnotify_fin_br, struct au_branch *br __maybe_unused) ++AuStubInt0(__init au_hnotify_init, void) ++AuStubVoid(au_hnotify_fin, void) ++AuStubVoid(au_hn_init, struct au_hinode *hinode __maybe_unused) ++#endif /* CONFIG_AUFS_HNOTIFY */ ++ ++static inline void au_hn_suspend(struct au_hinode *hdir) ++{ ++ au_hn_ctl(hdir, /*do_set*/0); ++} ++ ++static inline void au_hn_resume(struct au_hinode *hdir) ++{ ++ au_hn_ctl(hdir, /*do_set*/1); ++} ++ ++static inline void au_hn_inode_lock(struct au_hinode *hdir) ++{ ++ inode_lock(hdir->hi_inode); ++ au_hn_suspend(hdir); ++} ++ ++static inline void au_hn_inode_lock_nested(struct au_hinode *hdir, ++ unsigned int sc __maybe_unused) ++{ ++ inode_lock_nested(hdir->hi_inode, sc); ++ au_hn_suspend(hdir); ++} ++ ++#if 0 /* unused */ ++#include "vfsub.h" ++static inline void au_hn_inode_lock_shared_nested(struct au_hinode *hdir, ++ unsigned int sc) ++{ ++ inode_lock_shared_nested(hdir->hi_inode, sc); ++ au_hn_suspend(hdir); ++} ++#endif ++ ++static inline void au_hn_inode_unlock(struct au_hinode *hdir) ++{ ++ au_hn_resume(hdir); ++ inode_unlock(hdir->hi_inode); ++} ++ ++#endif /* __KERNEL__ */ ++#endif /* __AUFS_INODE_H__ */ +diff -Nurp linux-5.4/fs/aufs/ioctl.c linux-5.4-aufs/fs/aufs/ioctl.c +--- linux-5.4/fs/aufs/ioctl.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/ioctl.c 2019-11-28 01:25:59.066925618 +0200 +@@ -0,0 +1,207 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * ioctl ++ * plink-management and readdir in userspace. ++ * assist the pathconf(3) wrapper library. ++ * move-down ++ * File-based Hierarchical Storage Management. ++ */ ++ ++#include ++#include ++#include "aufs.h" ++ ++static int au_wbr_fd(struct path *path, struct aufs_wbr_fd __user *arg) ++{ ++ int err, fd; ++ aufs_bindex_t wbi, bindex, bbot; ++ struct file *h_file; ++ struct super_block *sb; ++ struct dentry *root; ++ struct au_branch *br; ++ struct aufs_wbr_fd wbrfd = { ++ .oflags = au_dir_roflags, ++ .brid = -1 ++ }; ++ const int valid = O_RDONLY | O_NONBLOCK | O_LARGEFILE | O_DIRECTORY ++ | O_NOATIME | O_CLOEXEC; ++ ++ AuDebugOn(wbrfd.oflags & ~valid); ++ ++ if (arg) { ++ err = copy_from_user(&wbrfd, arg, sizeof(wbrfd)); ++ if (unlikely(err)) { ++ err = -EFAULT; ++ goto out; ++ } ++ ++ err = -EINVAL; ++ AuDbg("wbrfd{0%o, %d}\n", wbrfd.oflags, wbrfd.brid); ++ wbrfd.oflags |= au_dir_roflags; ++ AuDbg("0%o\n", wbrfd.oflags); ++ if (unlikely(wbrfd.oflags & ~valid)) ++ goto out; ++ } ++ ++ fd = get_unused_fd_flags(0); ++ err = fd; ++ if (unlikely(fd < 0)) ++ goto out; ++ ++ h_file = ERR_PTR(-EINVAL); ++ wbi = 0; ++ br = NULL; ++ sb = path->dentry->d_sb; ++ root = sb->s_root; ++ aufs_read_lock(root, AuLock_IR); ++ bbot = au_sbbot(sb); ++ if (wbrfd.brid >= 0) { ++ wbi = au_br_index(sb, wbrfd.brid); ++ if (unlikely(wbi < 0 || wbi > bbot)) ++ goto out_unlock; ++ } ++ ++ h_file = ERR_PTR(-ENOENT); ++ br = au_sbr(sb, wbi); ++ if (!au_br_writable(br->br_perm)) { ++ if (arg) ++ goto out_unlock; ++ ++ bindex = wbi + 1; ++ wbi = -1; ++ for (; bindex <= bbot; bindex++) { ++ br = au_sbr(sb, bindex); ++ if (au_br_writable(br->br_perm)) { ++ wbi = bindex; ++ br = au_sbr(sb, wbi); ++ break; ++ } ++ } ++ } ++ AuDbg("wbi %d\n", wbi); ++ if (wbi >= 0) ++ h_file = au_h_open(root, wbi, wbrfd.oflags, NULL, ++ /*force_wr*/0); ++ ++out_unlock: ++ aufs_read_unlock(root, AuLock_IR); ++ err = PTR_ERR(h_file); ++ if (IS_ERR(h_file)) ++ goto out_fd; ++ ++ au_lcnt_dec(&br->br_nfiles); /* cf. au_h_open() */ ++ fd_install(fd, h_file); ++ err = fd; ++ goto out; /* success */ ++ ++out_fd: ++ put_unused_fd(fd); ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg) ++{ ++ long err; ++ struct dentry *dentry; ++ ++ switch (cmd) { ++ case AUFS_CTL_RDU: ++ case AUFS_CTL_RDU_INO: ++ err = au_rdu_ioctl(file, cmd, arg); ++ break; ++ ++ case AUFS_CTL_WBR_FD: ++ err = au_wbr_fd(&file->f_path, (void __user *)arg); ++ break; ++ ++ case AUFS_CTL_IBUSY: ++ err = au_ibusy_ioctl(file, arg); ++ break; ++ ++ case AUFS_CTL_BRINFO: ++ err = au_brinfo_ioctl(file, arg); ++ break; ++ ++ case AUFS_CTL_FHSM_FD: ++ dentry = file->f_path.dentry; ++ if (IS_ROOT(dentry)) ++ err = au_fhsm_fd(dentry->d_sb, arg); ++ else ++ err = -ENOTTY; ++ break; ++ ++ default: ++ /* do not call the lower */ ++ AuDbg("0x%x\n", cmd); ++ err = -ENOTTY; ++ } ++ ++ AuTraceErr(err); ++ return err; ++} ++ ++long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg) ++{ ++ long err; ++ ++ switch (cmd) { ++ case AUFS_CTL_MVDOWN: ++ err = au_mvdown(file->f_path.dentry, (void __user *)arg); ++ break; ++ ++ case AUFS_CTL_WBR_FD: ++ err = au_wbr_fd(&file->f_path, (void __user *)arg); ++ break; ++ ++ default: ++ /* do not call the lower */ ++ AuDbg("0x%x\n", cmd); ++ err = -ENOTTY; ++ } ++ ++ AuTraceErr(err); ++ return err; ++} ++ ++#ifdef CONFIG_COMPAT ++long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd, ++ unsigned long arg) ++{ ++ long err; ++ ++ switch (cmd) { ++ case AUFS_CTL_RDU: ++ case AUFS_CTL_RDU_INO: ++ err = au_rdu_compat_ioctl(file, cmd, arg); ++ break; ++ ++ case AUFS_CTL_IBUSY: ++ err = au_ibusy_compat_ioctl(file, arg); ++ break; ++ ++ case AUFS_CTL_BRINFO: ++ err = au_brinfo_compat_ioctl(file, arg); ++ break; ++ ++ default: ++ err = aufs_ioctl_dir(file, cmd, arg); ++ } ++ ++ AuTraceErr(err); ++ return err; ++} ++ ++long aufs_compat_ioctl_nondir(struct file *file, unsigned int cmd, ++ unsigned long arg) ++{ ++ return aufs_ioctl_nondir(file, cmd, (unsigned long)compat_ptr(arg)); ++} ++#endif +diff -Nurp linux-5.4/fs/aufs/i_op_add.c linux-5.4-aufs/fs/aufs/i_op_add.c +--- linux-5.4/fs/aufs/i_op_add.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/i_op_add.c 2019-11-28 01:25:59.065925618 +0200 +@@ -0,0 +1,923 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * inode operations (add entry) ++ */ ++ ++#include ++#include "aufs.h" ++ ++/* ++ * final procedure of adding a new entry, except link(2). ++ * remove whiteout, instantiate, copyup the parent dir's times and size ++ * and update version. ++ * if it failed, re-create the removed whiteout. ++ */ ++static int epilog(struct inode *dir, aufs_bindex_t bindex, ++ struct dentry *wh_dentry, struct dentry *dentry) ++{ ++ int err, rerr; ++ aufs_bindex_t bwh; ++ struct path h_path; ++ struct super_block *sb; ++ struct inode *inode, *h_dir; ++ struct dentry *wh; ++ ++ bwh = -1; ++ sb = dir->i_sb; ++ if (wh_dentry) { ++ h_dir = d_inode(wh_dentry->d_parent); /* dir inode is locked */ ++ IMustLock(h_dir); ++ AuDebugOn(au_h_iptr(dir, bindex) != h_dir); ++ bwh = au_dbwh(dentry); ++ h_path.dentry = wh_dentry; ++ h_path.mnt = au_sbr_mnt(sb, bindex); ++ err = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path, ++ dentry); ++ if (unlikely(err)) ++ goto out; ++ } ++ ++ inode = au_new_inode(dentry, /*must_new*/1); ++ if (!IS_ERR(inode)) { ++ d_instantiate(dentry, inode); ++ dir = d_inode(dentry->d_parent); /* dir inode is locked */ ++ IMustLock(dir); ++ au_dir_ts(dir, bindex); ++ inode_inc_iversion(dir); ++ au_fhsm_wrote(sb, bindex, /*force*/0); ++ return 0; /* success */ ++ } ++ ++ err = PTR_ERR(inode); ++ if (!wh_dentry) ++ goto out; ++ ++ /* revert */ ++ /* dir inode is locked */ ++ wh = au_wh_create(dentry, bwh, wh_dentry->d_parent); ++ rerr = PTR_ERR(wh); ++ if (IS_ERR(wh)) { ++ AuIOErr("%pd reverting whiteout failed(%d, %d)\n", ++ dentry, err, rerr); ++ err = -EIO; ++ } else ++ dput(wh); ++ ++out: ++ return err; ++} ++ ++static int au_d_may_add(struct dentry *dentry) ++{ ++ int err; ++ ++ err = 0; ++ if (unlikely(d_unhashed(dentry))) ++ err = -ENOENT; ++ if (unlikely(d_really_is_positive(dentry))) ++ err = -EEXIST; ++ return err; ++} ++ ++/* ++ * simple tests for the adding inode operations. ++ * following the checks in vfs, plus the parent-child relationship. ++ */ ++int au_may_add(struct dentry *dentry, aufs_bindex_t bindex, ++ struct dentry *h_parent, int isdir) ++{ ++ int err; ++ umode_t h_mode; ++ struct dentry *h_dentry; ++ struct inode *h_inode; ++ ++ err = -ENAMETOOLONG; ++ if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN)) ++ goto out; ++ ++ h_dentry = au_h_dptr(dentry, bindex); ++ if (d_really_is_negative(dentry)) { ++ err = -EEXIST; ++ if (unlikely(d_is_positive(h_dentry))) ++ goto out; ++ } else { ++ /* rename(2) case */ ++ err = -EIO; ++ if (unlikely(d_is_negative(h_dentry))) ++ goto out; ++ h_inode = d_inode(h_dentry); ++ if (unlikely(!h_inode->i_nlink)) ++ goto out; ++ ++ h_mode = h_inode->i_mode; ++ if (!isdir) { ++ err = -EISDIR; ++ if (unlikely(S_ISDIR(h_mode))) ++ goto out; ++ } else if (unlikely(!S_ISDIR(h_mode))) { ++ err = -ENOTDIR; ++ goto out; ++ } ++ } ++ ++ err = 0; ++ /* expected parent dir is locked */ ++ if (unlikely(h_parent != h_dentry->d_parent)) ++ err = -EIO; ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++/* ++ * initial procedure of adding a new entry. ++ * prepare writable branch and the parent dir, lock it, ++ * and lookup whiteout for the new entry. ++ */ ++static struct dentry* ++lock_hdir_lkup_wh(struct dentry *dentry, struct au_dtime *dt, ++ struct dentry *src_dentry, struct au_pin *pin, ++ struct au_wr_dir_args *wr_dir_args) ++{ ++ struct dentry *wh_dentry, *h_parent; ++ struct super_block *sb; ++ struct au_branch *br; ++ int err; ++ unsigned int udba; ++ aufs_bindex_t bcpup; ++ ++ AuDbg("%pd\n", dentry); ++ ++ err = au_wr_dir(dentry, src_dentry, wr_dir_args); ++ bcpup = err; ++ wh_dentry = ERR_PTR(err); ++ if (unlikely(err < 0)) ++ goto out; ++ ++ sb = dentry->d_sb; ++ udba = au_opt_udba(sb); ++ err = au_pin(pin, dentry, bcpup, udba, ++ AuPin_DI_LOCKED | AuPin_MNT_WRITE); ++ wh_dentry = ERR_PTR(err); ++ if (unlikely(err)) ++ goto out; ++ ++ h_parent = au_pinned_h_parent(pin); ++ if (udba != AuOpt_UDBA_NONE ++ && au_dbtop(dentry) == bcpup) ++ err = au_may_add(dentry, bcpup, h_parent, ++ au_ftest_wrdir(wr_dir_args->flags, ISDIR)); ++ else if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN)) ++ err = -ENAMETOOLONG; ++ wh_dentry = ERR_PTR(err); ++ if (unlikely(err)) ++ goto out_unpin; ++ ++ br = au_sbr(sb, bcpup); ++ if (dt) { ++ struct path tmp = { ++ .dentry = h_parent, ++ .mnt = au_br_mnt(br) ++ }; ++ au_dtime_store(dt, au_pinned_parent(pin), &tmp); ++ } ++ ++ wh_dentry = NULL; ++ if (bcpup != au_dbwh(dentry)) ++ goto out; /* success */ ++ ++ /* ++ * ENAMETOOLONG here means that if we allowed create such name, then it ++ * would not be able to removed in the future. So we don't allow such ++ * name here and we don't handle ENAMETOOLONG differently here. ++ */ ++ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, br); ++ ++out_unpin: ++ if (IS_ERR(wh_dentry)) ++ au_unpin(pin); ++out: ++ return wh_dentry; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++enum { Mknod, Symlink, Creat }; ++struct simple_arg { ++ int type; ++ union { ++ struct { ++ umode_t mode; ++ bool want_excl; ++ bool try_aopen; ++ struct vfsub_aopen_args *aopen; ++ } c; ++ struct { ++ const char *symname; ++ } s; ++ struct { ++ umode_t mode; ++ dev_t dev; ++ } m; ++ } u; ++}; ++ ++static int add_simple(struct inode *dir, struct dentry *dentry, ++ struct simple_arg *arg) ++{ ++ int err, rerr; ++ aufs_bindex_t btop; ++ unsigned char created; ++ const unsigned char try_aopen ++ = (arg->type == Creat && arg->u.c.try_aopen); ++ struct vfsub_aopen_args *aopen = arg->u.c.aopen; ++ struct dentry *wh_dentry, *parent; ++ struct inode *h_dir; ++ struct super_block *sb; ++ struct au_branch *br; ++ /* to reduce stack size */ ++ struct { ++ struct au_dtime dt; ++ struct au_pin pin; ++ struct path h_path; ++ struct au_wr_dir_args wr_dir_args; ++ } *a; ++ ++ AuDbg("%pd\n", dentry); ++ IMustLock(dir); ++ ++ err = -ENOMEM; ++ a = kmalloc(sizeof(*a), GFP_NOFS); ++ if (unlikely(!a)) ++ goto out; ++ a->wr_dir_args.force_btgt = -1; ++ a->wr_dir_args.flags = AuWrDir_ADD_ENTRY; ++ ++ parent = dentry->d_parent; /* dir inode is locked */ ++ if (!try_aopen) { ++ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN); ++ if (unlikely(err)) ++ goto out_free; ++ } ++ err = au_d_may_add(dentry); ++ if (unlikely(err)) ++ goto out_unlock; ++ if (!try_aopen) ++ di_write_lock_parent(parent); ++ wh_dentry = lock_hdir_lkup_wh(dentry, &a->dt, /*src_dentry*/NULL, ++ &a->pin, &a->wr_dir_args); ++ err = PTR_ERR(wh_dentry); ++ if (IS_ERR(wh_dentry)) ++ goto out_parent; ++ ++ btop = au_dbtop(dentry); ++ sb = dentry->d_sb; ++ br = au_sbr(sb, btop); ++ a->h_path.dentry = au_h_dptr(dentry, btop); ++ a->h_path.mnt = au_br_mnt(br); ++ h_dir = au_pinned_h_dir(&a->pin); ++ switch (arg->type) { ++ case Creat: ++ if (!try_aopen || !h_dir->i_op->atomic_open) { ++ err = vfsub_create(h_dir, &a->h_path, arg->u.c.mode, ++ arg->u.c.want_excl); ++ created = !err; ++ if (!err && try_aopen) ++ aopen->file->f_mode |= FMODE_CREATED; ++ } else { ++ aopen->br = br; ++ err = vfsub_atomic_open(h_dir, a->h_path.dentry, aopen); ++ AuDbg("err %d\n", err); ++ AuDbgFile(aopen->file); ++ created = err >= 0 ++ && !!(aopen->file->f_mode & FMODE_CREATED); ++ } ++ break; ++ case Symlink: ++ err = vfsub_symlink(h_dir, &a->h_path, arg->u.s.symname); ++ created = !err; ++ break; ++ case Mknod: ++ err = vfsub_mknod(h_dir, &a->h_path, arg->u.m.mode, ++ arg->u.m.dev); ++ created = !err; ++ break; ++ default: ++ BUG(); ++ } ++ if (unlikely(err < 0)) ++ goto out_unpin; ++ ++ err = epilog(dir, btop, wh_dentry, dentry); ++ if (!err) ++ goto out_unpin; /* success */ ++ ++ /* revert */ ++ if (created /* && d_is_positive(a->h_path.dentry) */) { ++ /* no delegation since it is just created */ ++ rerr = vfsub_unlink(h_dir, &a->h_path, /*delegated*/NULL, ++ /*force*/0); ++ if (rerr) { ++ AuIOErr("%pd revert failure(%d, %d)\n", ++ dentry, err, rerr); ++ err = -EIO; ++ } ++ au_dtime_revert(&a->dt); ++ } ++ if (try_aopen && h_dir->i_op->atomic_open ++ && (aopen->file->f_mode & FMODE_OPENED)) ++ /* aopen->file is still opened */ ++ au_lcnt_dec(&aopen->br->br_nfiles); ++ ++out_unpin: ++ au_unpin(&a->pin); ++ dput(wh_dentry); ++out_parent: ++ if (!try_aopen) ++ di_write_unlock(parent); ++out_unlock: ++ if (unlikely(err)) { ++ au_update_dbtop(dentry); ++ d_drop(dentry); ++ } ++ if (!try_aopen) ++ aufs_read_unlock(dentry, AuLock_DW); ++out_free: ++ au_kfree_rcu(a); ++out: ++ return err; ++} ++ ++int aufs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, ++ dev_t dev) ++{ ++ struct simple_arg arg = { ++ .type = Mknod, ++ .u.m = { ++ .mode = mode, ++ .dev = dev ++ } ++ }; ++ return add_simple(dir, dentry, &arg); ++} ++ ++int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) ++{ ++ struct simple_arg arg = { ++ .type = Symlink, ++ .u.s.symname = symname ++ }; ++ return add_simple(dir, dentry, &arg); ++} ++ ++int aufs_create(struct inode *dir, struct dentry *dentry, umode_t mode, ++ bool want_excl) ++{ ++ struct simple_arg arg = { ++ .type = Creat, ++ .u.c = { ++ .mode = mode, ++ .want_excl = want_excl ++ } ++ }; ++ return add_simple(dir, dentry, &arg); ++} ++ ++int au_aopen_or_create(struct inode *dir, struct dentry *dentry, ++ struct vfsub_aopen_args *aopen_args) ++{ ++ struct simple_arg arg = { ++ .type = Creat, ++ .u.c = { ++ .mode = aopen_args->create_mode, ++ .want_excl = aopen_args->open_flag & O_EXCL, ++ .try_aopen = true, ++ .aopen = aopen_args ++ } ++ }; ++ return add_simple(dir, dentry, &arg); ++} ++ ++int aufs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode) ++{ ++ int err; ++ aufs_bindex_t bindex; ++ struct super_block *sb; ++ struct dentry *parent, *h_parent, *h_dentry; ++ struct inode *h_dir, *inode; ++ struct vfsmount *h_mnt; ++ struct au_wr_dir_args wr_dir_args = { ++ .force_btgt = -1, ++ .flags = AuWrDir_TMPFILE ++ }; ++ ++ /* copy-up may happen */ ++ inode_lock(dir); ++ ++ sb = dir->i_sb; ++ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM); ++ if (unlikely(err)) ++ goto out; ++ ++ err = au_di_init(dentry); ++ if (unlikely(err)) ++ goto out_si; ++ ++ err = -EBUSY; ++ parent = d_find_any_alias(dir); ++ AuDebugOn(!parent); ++ di_write_lock_parent(parent); ++ if (unlikely(d_inode(parent) != dir)) ++ goto out_parent; ++ ++ err = au_digen_test(parent, au_sigen(sb)); ++ if (unlikely(err)) ++ goto out_parent; ++ ++ bindex = au_dbtop(parent); ++ au_set_dbtop(dentry, bindex); ++ au_set_dbbot(dentry, bindex); ++ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args); ++ bindex = err; ++ if (unlikely(err < 0)) ++ goto out_parent; ++ ++ err = -EOPNOTSUPP; ++ h_dir = au_h_iptr(dir, bindex); ++ if (unlikely(!h_dir->i_op->tmpfile)) ++ goto out_parent; ++ ++ h_mnt = au_sbr_mnt(sb, bindex); ++ err = vfsub_mnt_want_write(h_mnt); ++ if (unlikely(err)) ++ goto out_parent; ++ ++ h_parent = au_h_dptr(parent, bindex); ++ h_dentry = vfs_tmpfile(h_parent, mode, /*open_flag*/0); ++ if (IS_ERR(h_dentry)) { ++ err = PTR_ERR(h_dentry); ++ goto out_mnt; ++ } ++ ++ au_set_dbtop(dentry, bindex); ++ au_set_dbbot(dentry, bindex); ++ au_set_h_dptr(dentry, bindex, dget(h_dentry)); ++ inode = au_new_inode(dentry, /*must_new*/1); ++ if (IS_ERR(inode)) { ++ err = PTR_ERR(inode); ++ au_set_h_dptr(dentry, bindex, NULL); ++ au_set_dbtop(dentry, -1); ++ au_set_dbbot(dentry, -1); ++ } else { ++ if (!inode->i_nlink) ++ set_nlink(inode, 1); ++ d_tmpfile(dentry, inode); ++ au_di(dentry)->di_tmpfile = 1; ++ ++ /* update without i_mutex */ ++ if (au_ibtop(dir) == au_dbtop(dentry)) ++ au_cpup_attr_timesizes(dir); ++ } ++ dput(h_dentry); ++ ++out_mnt: ++ vfsub_mnt_drop_write(h_mnt); ++out_parent: ++ di_write_unlock(parent); ++ dput(parent); ++ di_write_unlock(dentry); ++ if (unlikely(err)) { ++ au_di_fin(dentry); ++ dentry->d_fsdata = NULL; ++ } ++out_si: ++ si_read_unlock(sb); ++out: ++ inode_unlock(dir); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++struct au_link_args { ++ aufs_bindex_t bdst, bsrc; ++ struct au_pin pin; ++ struct path h_path; ++ struct dentry *src_parent, *parent; ++}; ++ ++static int au_cpup_before_link(struct dentry *src_dentry, ++ struct au_link_args *a) ++{ ++ int err; ++ struct dentry *h_src_dentry; ++ struct au_cp_generic cpg = { ++ .dentry = src_dentry, ++ .bdst = a->bdst, ++ .bsrc = a->bsrc, ++ .len = -1, ++ .pin = &a->pin, ++ .flags = AuCpup_DTIME | AuCpup_HOPEN /* | AuCpup_KEEPLINO */ ++ }; ++ ++ di_read_lock_parent(a->src_parent, AuLock_IR); ++ err = au_test_and_cpup_dirs(src_dentry, a->bdst); ++ if (unlikely(err)) ++ goto out; ++ ++ h_src_dentry = au_h_dptr(src_dentry, a->bsrc); ++ err = au_pin(&a->pin, src_dentry, a->bdst, ++ au_opt_udba(src_dentry->d_sb), ++ AuPin_DI_LOCKED | AuPin_MNT_WRITE); ++ if (unlikely(err)) ++ goto out; ++ ++ err = au_sio_cpup_simple(&cpg); ++ au_unpin(&a->pin); ++ ++out: ++ di_read_unlock(a->src_parent, AuLock_IR); ++ return err; ++} ++ ++static int au_cpup_or_link(struct dentry *src_dentry, struct dentry *dentry, ++ struct au_link_args *a) ++{ ++ int err; ++ unsigned char plink; ++ aufs_bindex_t bbot; ++ struct dentry *h_src_dentry; ++ struct inode *h_inode, *inode, *delegated; ++ struct super_block *sb; ++ struct file *h_file; ++ ++ plink = 0; ++ h_inode = NULL; ++ sb = src_dentry->d_sb; ++ inode = d_inode(src_dentry); ++ if (au_ibtop(inode) <= a->bdst) ++ h_inode = au_h_iptr(inode, a->bdst); ++ if (!h_inode || !h_inode->i_nlink) { ++ /* copyup src_dentry as the name of dentry. */ ++ bbot = au_dbbot(dentry); ++ if (bbot < a->bsrc) ++ au_set_dbbot(dentry, a->bsrc); ++ au_set_h_dptr(dentry, a->bsrc, ++ dget(au_h_dptr(src_dentry, a->bsrc))); ++ dget(a->h_path.dentry); ++ au_set_h_dptr(dentry, a->bdst, NULL); ++ AuDbg("temporary d_inode...\n"); ++ spin_lock(&dentry->d_lock); ++ dentry->d_inode = d_inode(src_dentry); /* tmp */ ++ spin_unlock(&dentry->d_lock); ++ h_file = au_h_open_pre(dentry, a->bsrc, /*force_wr*/0); ++ if (IS_ERR(h_file)) ++ err = PTR_ERR(h_file); ++ else { ++ struct au_cp_generic cpg = { ++ .dentry = dentry, ++ .bdst = a->bdst, ++ .bsrc = -1, ++ .len = -1, ++ .pin = &a->pin, ++ .flags = AuCpup_KEEPLINO ++ }; ++ err = au_sio_cpup_simple(&cpg); ++ au_h_open_post(dentry, a->bsrc, h_file); ++ if (!err) { ++ dput(a->h_path.dentry); ++ a->h_path.dentry = au_h_dptr(dentry, a->bdst); ++ } else ++ au_set_h_dptr(dentry, a->bdst, ++ a->h_path.dentry); ++ } ++ spin_lock(&dentry->d_lock); ++ dentry->d_inode = NULL; /* restore */ ++ spin_unlock(&dentry->d_lock); ++ AuDbg("temporary d_inode...done\n"); ++ au_set_h_dptr(dentry, a->bsrc, NULL); ++ au_set_dbbot(dentry, bbot); ++ } else { ++ /* the inode of src_dentry already exists on a.bdst branch */ ++ h_src_dentry = d_find_alias(h_inode); ++ if (!h_src_dentry && au_plink_test(inode)) { ++ plink = 1; ++ h_src_dentry = au_plink_lkup(inode, a->bdst); ++ err = PTR_ERR(h_src_dentry); ++ if (IS_ERR(h_src_dentry)) ++ goto out; ++ ++ if (unlikely(d_is_negative(h_src_dentry))) { ++ dput(h_src_dentry); ++ h_src_dentry = NULL; ++ } ++ ++ } ++ if (h_src_dentry) { ++ delegated = NULL; ++ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin), ++ &a->h_path, &delegated); ++ if (unlikely(err == -EWOULDBLOCK)) { ++ pr_warn("cannot retry for NFSv4 delegation" ++ " for an internal link\n"); ++ iput(delegated); ++ } ++ dput(h_src_dentry); ++ } else { ++ AuIOErr("no dentry found for hi%lu on b%d\n", ++ h_inode->i_ino, a->bdst); ++ err = -EIO; ++ } ++ } ++ ++ if (!err && !plink) ++ au_plink_append(inode, a->bdst, a->h_path.dentry); ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++int aufs_link(struct dentry *src_dentry, struct inode *dir, ++ struct dentry *dentry) ++{ ++ int err, rerr; ++ struct au_dtime dt; ++ struct au_link_args *a; ++ struct dentry *wh_dentry, *h_src_dentry; ++ struct inode *inode, *delegated; ++ struct super_block *sb; ++ struct au_wr_dir_args wr_dir_args = { ++ /* .force_btgt = -1, */ ++ .flags = AuWrDir_ADD_ENTRY ++ }; ++ ++ IMustLock(dir); ++ inode = d_inode(src_dentry); ++ IMustLock(inode); ++ ++ err = -ENOMEM; ++ a = kzalloc(sizeof(*a), GFP_NOFS); ++ if (unlikely(!a)) ++ goto out; ++ ++ a->parent = dentry->d_parent; /* dir inode is locked */ ++ err = aufs_read_and_write_lock2(dentry, src_dentry, ++ AuLock_NOPLM | AuLock_GEN); ++ if (unlikely(err)) ++ goto out_kfree; ++ err = au_d_linkable(src_dentry); ++ if (unlikely(err)) ++ goto out_unlock; ++ err = au_d_may_add(dentry); ++ if (unlikely(err)) ++ goto out_unlock; ++ ++ a->src_parent = dget_parent(src_dentry); ++ wr_dir_args.force_btgt = au_ibtop(inode); ++ ++ di_write_lock_parent(a->parent); ++ wr_dir_args.force_btgt = au_wbr(dentry, wr_dir_args.force_btgt); ++ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, src_dentry, &a->pin, ++ &wr_dir_args); ++ err = PTR_ERR(wh_dentry); ++ if (IS_ERR(wh_dentry)) ++ goto out_parent; ++ ++ err = 0; ++ sb = dentry->d_sb; ++ a->bdst = au_dbtop(dentry); ++ a->h_path.dentry = au_h_dptr(dentry, a->bdst); ++ a->h_path.mnt = au_sbr_mnt(sb, a->bdst); ++ a->bsrc = au_ibtop(inode); ++ h_src_dentry = au_h_d_alias(src_dentry, a->bsrc); ++ if (!h_src_dentry && au_di(src_dentry)->di_tmpfile) ++ h_src_dentry = dget(au_hi_wh(inode, a->bsrc)); ++ if (!h_src_dentry) { ++ a->bsrc = au_dbtop(src_dentry); ++ h_src_dentry = au_h_d_alias(src_dentry, a->bsrc); ++ AuDebugOn(!h_src_dentry); ++ } else if (IS_ERR(h_src_dentry)) { ++ err = PTR_ERR(h_src_dentry); ++ goto out_parent; ++ } ++ ++ /* ++ * aufs doesn't touch the credential so ++ * security_dentry_create_files_as() is unnecessary. ++ */ ++ if (au_opt_test(au_mntflags(sb), PLINK)) { ++ if (a->bdst < a->bsrc ++ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */) ++ err = au_cpup_or_link(src_dentry, dentry, a); ++ else { ++ delegated = NULL; ++ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin), ++ &a->h_path, &delegated); ++ if (unlikely(err == -EWOULDBLOCK)) { ++ pr_warn("cannot retry for NFSv4 delegation" ++ " for an internal link\n"); ++ iput(delegated); ++ } ++ } ++ dput(h_src_dentry); ++ } else { ++ /* ++ * copyup src_dentry to the branch we process, ++ * and then link(2) to it. ++ */ ++ dput(h_src_dentry); ++ if (a->bdst < a->bsrc ++ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */) { ++ au_unpin(&a->pin); ++ di_write_unlock(a->parent); ++ err = au_cpup_before_link(src_dentry, a); ++ di_write_lock_parent(a->parent); ++ if (!err) ++ err = au_pin(&a->pin, dentry, a->bdst, ++ au_opt_udba(sb), ++ AuPin_DI_LOCKED | AuPin_MNT_WRITE); ++ if (unlikely(err)) ++ goto out_wh; ++ } ++ if (!err) { ++ h_src_dentry = au_h_dptr(src_dentry, a->bdst); ++ err = -ENOENT; ++ if (h_src_dentry && d_is_positive(h_src_dentry)) { ++ delegated = NULL; ++ err = vfsub_link(h_src_dentry, ++ au_pinned_h_dir(&a->pin), ++ &a->h_path, &delegated); ++ if (unlikely(err == -EWOULDBLOCK)) { ++ pr_warn("cannot retry" ++ " for NFSv4 delegation" ++ " for an internal link\n"); ++ iput(delegated); ++ } ++ } ++ } ++ } ++ if (unlikely(err)) ++ goto out_unpin; ++ ++ if (wh_dentry) { ++ a->h_path.dentry = wh_dentry; ++ err = au_wh_unlink_dentry(au_pinned_h_dir(&a->pin), &a->h_path, ++ dentry); ++ if (unlikely(err)) ++ goto out_revert; ++ } ++ ++ au_dir_ts(dir, a->bdst); ++ inode_inc_iversion(dir); ++ inc_nlink(inode); ++ inode->i_ctime = dir->i_ctime; ++ d_instantiate(dentry, au_igrab(inode)); ++ if (d_unhashed(a->h_path.dentry)) ++ /* some filesystem calls d_drop() */ ++ d_drop(dentry); ++ /* some filesystems consume an inode even hardlink */ ++ au_fhsm_wrote(sb, a->bdst, /*force*/0); ++ goto out_unpin; /* success */ ++ ++out_revert: ++ /* no delegation since it is just created */ ++ rerr = vfsub_unlink(au_pinned_h_dir(&a->pin), &a->h_path, ++ /*delegated*/NULL, /*force*/0); ++ if (unlikely(rerr)) { ++ AuIOErr("%pd reverting failed(%d, %d)\n", dentry, err, rerr); ++ err = -EIO; ++ } ++ au_dtime_revert(&dt); ++out_unpin: ++ au_unpin(&a->pin); ++out_wh: ++ dput(wh_dentry); ++out_parent: ++ di_write_unlock(a->parent); ++ dput(a->src_parent); ++out_unlock: ++ if (unlikely(err)) { ++ au_update_dbtop(dentry); ++ d_drop(dentry); ++ } ++ aufs_read_and_write_unlock2(dentry, src_dentry); ++out_kfree: ++ au_kfree_rcu(a); ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++int aufs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) ++{ ++ int err, rerr; ++ aufs_bindex_t bindex; ++ unsigned char diropq; ++ struct path h_path; ++ struct dentry *wh_dentry, *parent, *opq_dentry; ++ struct inode *h_inode; ++ struct super_block *sb; ++ struct { ++ struct au_pin pin; ++ struct au_dtime dt; ++ } *a; /* reduce the stack usage */ ++ struct au_wr_dir_args wr_dir_args = { ++ .force_btgt = -1, ++ .flags = AuWrDir_ADD_ENTRY | AuWrDir_ISDIR ++ }; ++ ++ IMustLock(dir); ++ ++ err = -ENOMEM; ++ a = kmalloc(sizeof(*a), GFP_NOFS); ++ if (unlikely(!a)) ++ goto out; ++ ++ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN); ++ if (unlikely(err)) ++ goto out_free; ++ err = au_d_may_add(dentry); ++ if (unlikely(err)) ++ goto out_unlock; ++ ++ parent = dentry->d_parent; /* dir inode is locked */ ++ di_write_lock_parent(parent); ++ wh_dentry = lock_hdir_lkup_wh(dentry, &a->dt, /*src_dentry*/NULL, ++ &a->pin, &wr_dir_args); ++ err = PTR_ERR(wh_dentry); ++ if (IS_ERR(wh_dentry)) ++ goto out_parent; ++ ++ sb = dentry->d_sb; ++ bindex = au_dbtop(dentry); ++ h_path.dentry = au_h_dptr(dentry, bindex); ++ h_path.mnt = au_sbr_mnt(sb, bindex); ++ err = vfsub_mkdir(au_pinned_h_dir(&a->pin), &h_path, mode); ++ if (unlikely(err)) ++ goto out_unpin; ++ ++ /* make the dir opaque */ ++ diropq = 0; ++ h_inode = d_inode(h_path.dentry); ++ if (wh_dentry ++ || au_opt_test(au_mntflags(sb), ALWAYS_DIROPQ)) { ++ inode_lock_nested(h_inode, AuLsc_I_CHILD); ++ opq_dentry = au_diropq_create(dentry, bindex); ++ inode_unlock(h_inode); ++ err = PTR_ERR(opq_dentry); ++ if (IS_ERR(opq_dentry)) ++ goto out_dir; ++ dput(opq_dentry); ++ diropq = 1; ++ } ++ ++ err = epilog(dir, bindex, wh_dentry, dentry); ++ if (!err) { ++ inc_nlink(dir); ++ goto out_unpin; /* success */ ++ } ++ ++ /* revert */ ++ if (diropq) { ++ AuLabel(revert opq); ++ inode_lock_nested(h_inode, AuLsc_I_CHILD); ++ rerr = au_diropq_remove(dentry, bindex); ++ inode_unlock(h_inode); ++ if (rerr) { ++ AuIOErr("%pd reverting diropq failed(%d, %d)\n", ++ dentry, err, rerr); ++ err = -EIO; ++ } ++ } ++ ++out_dir: ++ AuLabel(revert dir); ++ rerr = vfsub_rmdir(au_pinned_h_dir(&a->pin), &h_path); ++ if (rerr) { ++ AuIOErr("%pd reverting dir failed(%d, %d)\n", ++ dentry, err, rerr); ++ err = -EIO; ++ } ++ au_dtime_revert(&a->dt); ++out_unpin: ++ au_unpin(&a->pin); ++ dput(wh_dentry); ++out_parent: ++ di_write_unlock(parent); ++out_unlock: ++ if (unlikely(err)) { ++ au_update_dbtop(dentry); ++ d_drop(dentry); ++ } ++ aufs_read_unlock(dentry, AuLock_DW); ++out_free: ++ au_kfree_rcu(a); ++out: ++ return err; ++} +diff -Nurp linux-5.4/fs/aufs/i_op.c linux-5.4-aufs/fs/aufs/i_op.c +--- linux-5.4/fs/aufs/i_op.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/i_op.c 2019-11-28 01:25:59.065925618 +0200 +@@ -0,0 +1,1492 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * inode operations (except add/del/rename) ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include "aufs.h" ++ ++static int h_permission(struct inode *h_inode, int mask, ++ struct path *h_path, int brperm) ++{ ++ int err; ++ const unsigned char write_mask = !!(mask & (MAY_WRITE | MAY_APPEND)); ++ ++ err = -EPERM; ++ if (write_mask && IS_IMMUTABLE(h_inode)) ++ goto out; ++ ++ err = -EACCES; ++ if (((mask & MAY_EXEC) ++ && S_ISREG(h_inode->i_mode) ++ && (path_noexec(h_path) ++ || !(h_inode->i_mode & 0111)))) ++ goto out; ++ ++ /* ++ * - skip the lower fs test in the case of write to ro branch. ++ * - nfs dir permission write check is optimized, but a policy for ++ * link/rename requires a real check. ++ * - nfs always sets SB_POSIXACL regardless its mount option 'noacl.' ++ * in this case, generic_permission() returns -EOPNOTSUPP. ++ */ ++ if ((write_mask && !au_br_writable(brperm)) ++ || (au_test_nfs(h_inode->i_sb) && S_ISDIR(h_inode->i_mode) ++ && write_mask && !(mask & MAY_READ)) ++ || !h_inode->i_op->permission) { ++ /* AuLabel(generic_permission); */ ++ /* AuDbg("get_acl %ps\n", h_inode->i_op->get_acl); */ ++ err = generic_permission(h_inode, mask); ++ if (err == -EOPNOTSUPP && au_test_nfs_noacl(h_inode)) ++ err = h_inode->i_op->permission(h_inode, mask); ++ AuTraceErr(err); ++ } else { ++ /* AuLabel(h_inode->permission); */ ++ err = h_inode->i_op->permission(h_inode, mask); ++ AuTraceErr(err); ++ } ++ ++ if (!err) ++ err = devcgroup_inode_permission(h_inode, mask); ++ if (!err) ++ err = security_inode_permission(h_inode, mask); ++ ++#if 0 ++ if (!err) { ++ /* todo: do we need to call ima_path_check()? */ ++ struct path h_path = { ++ .dentry = ++ .mnt = h_mnt ++ }; ++ err = ima_path_check(&h_path, ++ mask & (MAY_READ | MAY_WRITE | MAY_EXEC), ++ IMA_COUNT_LEAVE); ++ } ++#endif ++ ++out: ++ return err; ++} ++ ++static int aufs_permission(struct inode *inode, int mask) ++{ ++ int err; ++ aufs_bindex_t bindex, bbot; ++ const unsigned char isdir = !!S_ISDIR(inode->i_mode), ++ write_mask = !!(mask & (MAY_WRITE | MAY_APPEND)); ++ struct inode *h_inode; ++ struct super_block *sb; ++ struct au_branch *br; ++ ++ /* todo: support rcu-walk? */ ++ if (mask & MAY_NOT_BLOCK) ++ return -ECHILD; ++ ++ sb = inode->i_sb; ++ si_read_lock(sb, AuLock_FLUSH); ++ ii_read_lock_child(inode); ++#if 0 ++ err = au_iigen_test(inode, au_sigen(sb)); ++ if (unlikely(err)) ++ goto out; ++#endif ++ ++ if (!isdir ++ || write_mask ++ || au_opt_test(au_mntflags(sb), DIRPERM1)) { ++ err = au_busy_or_stale(); ++ h_inode = au_h_iptr(inode, au_ibtop(inode)); ++ if (unlikely(!h_inode ++ || (h_inode->i_mode & S_IFMT) ++ != (inode->i_mode & S_IFMT))) ++ goto out; ++ ++ err = 0; ++ bindex = au_ibtop(inode); ++ br = au_sbr(sb, bindex); ++ err = h_permission(h_inode, mask, &br->br_path, br->br_perm); ++ if (write_mask ++ && !err ++ && !special_file(h_inode->i_mode)) { ++ /* test whether the upper writable branch exists */ ++ err = -EROFS; ++ for (; bindex >= 0; bindex--) ++ if (!au_br_rdonly(au_sbr(sb, bindex))) { ++ err = 0; ++ break; ++ } ++ } ++ goto out; ++ } ++ ++ /* non-write to dir */ ++ err = 0; ++ bbot = au_ibbot(inode); ++ for (bindex = au_ibtop(inode); !err && bindex <= bbot; bindex++) { ++ h_inode = au_h_iptr(inode, bindex); ++ if (h_inode) { ++ err = au_busy_or_stale(); ++ if (unlikely(!S_ISDIR(h_inode->i_mode))) ++ break; ++ ++ br = au_sbr(sb, bindex); ++ err = h_permission(h_inode, mask, &br->br_path, ++ br->br_perm); ++ } ++ } ++ ++out: ++ ii_read_unlock(inode); ++ si_read_unlock(sb); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static struct dentry *aufs_lookup(struct inode *dir, struct dentry *dentry, ++ unsigned int flags) ++{ ++ struct dentry *ret, *parent; ++ struct inode *inode; ++ struct super_block *sb; ++ int err, npositive; ++ ++ IMustLock(dir); ++ ++ /* todo: support rcu-walk? */ ++ ret = ERR_PTR(-ECHILD); ++ if (flags & LOOKUP_RCU) ++ goto out; ++ ++ ret = ERR_PTR(-ENAMETOOLONG); ++ if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN)) ++ goto out; ++ ++ sb = dir->i_sb; ++ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM); ++ ret = ERR_PTR(err); ++ if (unlikely(err)) ++ goto out; ++ ++ err = au_di_init(dentry); ++ ret = ERR_PTR(err); ++ if (unlikely(err)) ++ goto out_si; ++ ++ inode = NULL; ++ npositive = 0; /* suppress a warning */ ++ parent = dentry->d_parent; /* dir inode is locked */ ++ di_read_lock_parent(parent, AuLock_IR); ++ err = au_alive_dir(parent); ++ if (!err) ++ err = au_digen_test(parent, au_sigen(sb)); ++ if (!err) { ++ /* regardless LOOKUP_CREATE, always ALLOW_NEG */ ++ npositive = au_lkup_dentry(dentry, au_dbtop(parent), ++ AuLkup_ALLOW_NEG); ++ err = npositive; ++ } ++ di_read_unlock(parent, AuLock_IR); ++ ret = ERR_PTR(err); ++ if (unlikely(err < 0)) ++ goto out_unlock; ++ ++ if (npositive) { ++ inode = au_new_inode(dentry, /*must_new*/0); ++ if (IS_ERR(inode)) { ++ ret = (void *)inode; ++ inode = NULL; ++ goto out_unlock; ++ } ++ } ++ ++ if (inode) ++ atomic_inc(&inode->i_count); ++ ret = d_splice_alias(inode, dentry); ++#if 0 ++ if (unlikely(d_need_lookup(dentry))) { ++ spin_lock(&dentry->d_lock); ++ dentry->d_flags &= ~DCACHE_NEED_LOOKUP; ++ spin_unlock(&dentry->d_lock); ++ } else ++#endif ++ if (inode) { ++ if (!IS_ERR(ret)) { ++ iput(inode); ++ if (ret && ret != dentry) ++ ii_write_unlock(inode); ++ } else { ++ ii_write_unlock(inode); ++ iput(inode); ++ inode = NULL; ++ } ++ } ++ ++out_unlock: ++ di_write_unlock(dentry); ++out_si: ++ si_read_unlock(sb); ++out: ++ return ret; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * very dirty and complicated aufs ->atomic_open(). ++ * aufs_atomic_open() ++ * + au_aopen_or_create() ++ * + add_simple() ++ * + vfsub_atomic_open() ++ * + branch fs ->atomic_open() ++ * may call the actual 'open' for h_file ++ * + inc br_nfiles only if opened ++ * + au_aopen_no_open() or au_aopen_do_open() ++ * ++ * au_aopen_do_open() ++ * + finish_open() ++ * + au_do_aopen() ++ * + au_do_open() the body of all 'open' ++ * + au_do_open_nondir() ++ * set the passed h_file ++ * ++ * au_aopen_no_open() ++ * + finish_no_open() ++ */ ++ ++struct aopen_node { ++ struct hlist_bl_node hblist; ++ struct file *file, *h_file; ++}; ++ ++static int au_do_aopen(struct inode *inode, struct file *file) ++{ ++ struct hlist_bl_head *aopen; ++ struct hlist_bl_node *pos; ++ struct aopen_node *node; ++ struct au_do_open_args args = { ++ .aopen = 1, ++ .open = au_do_open_nondir ++ }; ++ ++ aopen = &au_sbi(inode->i_sb)->si_aopen; ++ hlist_bl_lock(aopen); ++ hlist_bl_for_each_entry(node, pos, aopen, hblist) ++ if (node->file == file) { ++ args.h_file = node->h_file; ++ break; ++ } ++ hlist_bl_unlock(aopen); ++ /* AuDebugOn(!args.h_file); */ ++ ++ return au_do_open(file, &args); ++} ++ ++static int au_aopen_do_open(struct file *file, struct dentry *dentry, ++ struct aopen_node *aopen_node) ++{ ++ int err; ++ struct hlist_bl_head *aopen; ++ ++ AuLabel(here); ++ aopen = &au_sbi(dentry->d_sb)->si_aopen; ++ au_hbl_add(&aopen_node->hblist, aopen); ++ err = finish_open(file, dentry, au_do_aopen); ++ au_hbl_del(&aopen_node->hblist, aopen); ++ /* AuDbgFile(file); */ ++ AuDbg("%pd%s%s\n", dentry, ++ (file->f_mode & FMODE_CREATED) ? " created" : "", ++ (file->f_mode & FMODE_OPENED) ? " opened" : ""); ++ ++ AuTraceErr(err); ++ return err; ++} ++ ++static int au_aopen_no_open(struct file *file, struct dentry *dentry) ++{ ++ int err; ++ ++ AuLabel(here); ++ dget(dentry); ++ err = finish_no_open(file, dentry); ++ ++ AuTraceErr(err); ++ return err; ++} ++ ++static int aufs_atomic_open(struct inode *dir, struct dentry *dentry, ++ struct file *file, unsigned int open_flag, ++ umode_t create_mode) ++{ ++ int err, did_open; ++ unsigned int lkup_flags; ++ aufs_bindex_t bindex; ++ struct super_block *sb; ++ struct dentry *parent, *d; ++ struct vfsub_aopen_args args = { ++ .open_flag = open_flag, ++ .create_mode = create_mode ++ }; ++ struct aopen_node aopen_node = { ++ .file = file ++ }; ++ ++ IMustLock(dir); ++ AuDbg("open_flag 0%o\n", open_flag); ++ AuDbgDentry(dentry); ++ ++ err = 0; ++ if (!au_di(dentry)) { ++ lkup_flags = LOOKUP_OPEN; ++ if (open_flag & O_CREAT) ++ lkup_flags |= LOOKUP_CREATE; ++ d = aufs_lookup(dir, dentry, lkup_flags); ++ if (IS_ERR(d)) { ++ err = PTR_ERR(d); ++ AuTraceErr(err); ++ goto out; ++ } else if (d) { ++ /* ++ * obsoleted dentry found. ++ * another error will be returned later. ++ */ ++ d_drop(d); ++ AuDbgDentry(d); ++ dput(d); ++ } ++ AuDbgDentry(dentry); ++ } ++ ++ if (d_is_positive(dentry) ++ || d_unhashed(dentry) ++ || d_unlinked(dentry) ++ || !(open_flag & O_CREAT)) { ++ err = au_aopen_no_open(file, dentry); ++ goto out; /* success */ ++ } ++ ++ err = aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH | AuLock_GEN); ++ if (unlikely(err)) ++ goto out; ++ ++ sb = dentry->d_sb; ++ parent = dentry->d_parent; /* dir is locked */ ++ di_write_lock_parent(parent); ++ err = au_lkup_dentry(dentry, /*btop*/0, AuLkup_ALLOW_NEG); ++ if (unlikely(err < 0)) ++ goto out_parent; ++ ++ AuDbgDentry(dentry); ++ if (d_is_positive(dentry)) { ++ err = au_aopen_no_open(file, dentry); ++ goto out_parent; /* success */ ++ } ++ ++ args.file = alloc_empty_file(file->f_flags, current_cred()); ++ err = PTR_ERR(args.file); ++ if (IS_ERR(args.file)) ++ goto out_parent; ++ ++ bindex = au_dbtop(dentry); ++ err = au_aopen_or_create(dir, dentry, &args); ++ AuTraceErr(err); ++ AuDbgFile(args.file); ++ file->f_mode = args.file->f_mode & ~FMODE_OPENED; ++ did_open = !!(args.file->f_mode & FMODE_OPENED); ++ if (!did_open) { ++ fput(args.file); ++ args.file = NULL; ++ } ++ di_write_unlock(parent); ++ di_write_unlock(dentry); ++ if (unlikely(err < 0)) { ++ if (args.file) ++ fput(args.file); ++ goto out_sb; ++ } ++ ++ if (!did_open) ++ err = au_aopen_no_open(file, dentry); ++ else { ++ aopen_node.h_file = args.file; ++ err = au_aopen_do_open(file, dentry, &aopen_node); ++ } ++ if (unlikely(err < 0)) { ++ if (args.file) ++ fput(args.file); ++ if (did_open) ++ au_lcnt_dec(&args.br->br_nfiles); ++ } ++ goto out_sb; /* success */ ++ ++out_parent: ++ di_write_unlock(parent); ++ di_write_unlock(dentry); ++out_sb: ++ si_read_unlock(sb); ++out: ++ AuTraceErr(err); ++ AuDbgFile(file); ++ return err; ++} ++ ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int au_wr_dir_cpup(struct dentry *dentry, struct dentry *parent, ++ const unsigned char add_entry, aufs_bindex_t bcpup, ++ aufs_bindex_t btop) ++{ ++ int err; ++ struct dentry *h_parent; ++ struct inode *h_dir; ++ ++ if (add_entry) ++ IMustLock(d_inode(parent)); ++ else ++ di_write_lock_parent(parent); ++ ++ err = 0; ++ if (!au_h_dptr(parent, bcpup)) { ++ if (btop > bcpup) ++ err = au_cpup_dirs(dentry, bcpup); ++ else if (btop < bcpup) ++ err = au_cpdown_dirs(dentry, bcpup); ++ else ++ BUG(); ++ } ++ if (!err && add_entry && !au_ftest_wrdir(add_entry, TMPFILE)) { ++ h_parent = au_h_dptr(parent, bcpup); ++ h_dir = d_inode(h_parent); ++ inode_lock_shared_nested(h_dir, AuLsc_I_PARENT); ++ err = au_lkup_neg(dentry, bcpup, /*wh*/0); ++ /* todo: no unlock here */ ++ inode_unlock_shared(h_dir); ++ ++ AuDbg("bcpup %d\n", bcpup); ++ if (!err) { ++ if (d_really_is_negative(dentry)) ++ au_set_h_dptr(dentry, btop, NULL); ++ au_update_dbrange(dentry, /*do_put_zero*/0); ++ } ++ } ++ ++ if (!add_entry) ++ di_write_unlock(parent); ++ if (!err) ++ err = bcpup; /* success */ ++ ++ AuTraceErr(err); ++ return err; ++} ++ ++/* ++ * decide the branch and the parent dir where we will create a new entry. ++ * returns new bindex or an error. ++ * copyup the parent dir if needed. ++ */ ++int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry, ++ struct au_wr_dir_args *args) ++{ ++ int err; ++ unsigned int flags; ++ aufs_bindex_t bcpup, btop, src_btop; ++ const unsigned char add_entry ++ = au_ftest_wrdir(args->flags, ADD_ENTRY) ++ | au_ftest_wrdir(args->flags, TMPFILE); ++ struct super_block *sb; ++ struct dentry *parent; ++ struct au_sbinfo *sbinfo; ++ ++ sb = dentry->d_sb; ++ sbinfo = au_sbi(sb); ++ parent = dget_parent(dentry); ++ btop = au_dbtop(dentry); ++ bcpup = btop; ++ if (args->force_btgt < 0) { ++ if (src_dentry) { ++ src_btop = au_dbtop(src_dentry); ++ if (src_btop < btop) ++ bcpup = src_btop; ++ } else if (add_entry) { ++ flags = 0; ++ if (au_ftest_wrdir(args->flags, ISDIR)) ++ au_fset_wbr(flags, DIR); ++ err = AuWbrCreate(sbinfo, dentry, flags); ++ bcpup = err; ++ } ++ ++ if (bcpup < 0 || au_test_ro(sb, bcpup, d_inode(dentry))) { ++ if (add_entry) ++ err = AuWbrCopyup(sbinfo, dentry); ++ else { ++ if (!IS_ROOT(dentry)) { ++ di_read_lock_parent(parent, !AuLock_IR); ++ err = AuWbrCopyup(sbinfo, dentry); ++ di_read_unlock(parent, !AuLock_IR); ++ } else ++ err = AuWbrCopyup(sbinfo, dentry); ++ } ++ bcpup = err; ++ if (unlikely(err < 0)) ++ goto out; ++ } ++ } else { ++ bcpup = args->force_btgt; ++ AuDebugOn(au_test_ro(sb, bcpup, d_inode(dentry))); ++ } ++ ++ AuDbg("btop %d, bcpup %d\n", btop, bcpup); ++ err = bcpup; ++ if (bcpup == btop) ++ goto out; /* success */ ++ ++ /* copyup the new parent into the branch we process */ ++ err = au_wr_dir_cpup(dentry, parent, add_entry, bcpup, btop); ++ if (err >= 0) { ++ if (d_really_is_negative(dentry)) { ++ au_set_h_dptr(dentry, btop, NULL); ++ au_set_dbtop(dentry, bcpup); ++ au_set_dbbot(dentry, bcpup); ++ } ++ AuDebugOn(add_entry ++ && !au_ftest_wrdir(args->flags, TMPFILE) ++ && !au_h_dptr(dentry, bcpup)); ++ } ++ ++out: ++ dput(parent); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++void au_pin_hdir_unlock(struct au_pin *p) ++{ ++ if (p->hdir) ++ au_hn_inode_unlock(p->hdir); ++} ++ ++int au_pin_hdir_lock(struct au_pin *p) ++{ ++ int err; ++ ++ err = 0; ++ if (!p->hdir) ++ goto out; ++ ++ /* even if an error happens later, keep this lock */ ++ au_hn_inode_lock_nested(p->hdir, p->lsc_hi); ++ ++ err = -EBUSY; ++ if (unlikely(p->hdir->hi_inode != d_inode(p->h_parent))) ++ goto out; ++ ++ err = 0; ++ if (p->h_dentry) ++ err = au_h_verify(p->h_dentry, p->udba, p->hdir->hi_inode, ++ p->h_parent, p->br); ++ ++out: ++ return err; ++} ++ ++int au_pin_hdir_relock(struct au_pin *p) ++{ ++ int err, i; ++ struct inode *h_i; ++ struct dentry *h_d[] = { ++ p->h_dentry, ++ p->h_parent ++ }; ++ ++ err = au_pin_hdir_lock(p); ++ if (unlikely(err)) ++ goto out; ++ ++ for (i = 0; !err && i < sizeof(h_d)/sizeof(*h_d); i++) { ++ if (!h_d[i]) ++ continue; ++ if (d_is_positive(h_d[i])) { ++ h_i = d_inode(h_d[i]); ++ err = !h_i->i_nlink; ++ } ++ } ++ ++out: ++ return err; ++} ++ ++static void au_pin_hdir_set_owner(struct au_pin *p, struct task_struct *task) ++{ ++ atomic_long_set(&p->hdir->hi_inode->i_rwsem.owner, (long)task); ++} ++ ++void au_pin_hdir_acquire_nest(struct au_pin *p) ++{ ++ if (p->hdir) { ++ rwsem_acquire_nest(&p->hdir->hi_inode->i_rwsem.dep_map, ++ p->lsc_hi, 0, NULL, _RET_IP_); ++ au_pin_hdir_set_owner(p, current); ++ } ++} ++ ++void au_pin_hdir_release(struct au_pin *p) ++{ ++ if (p->hdir) { ++ au_pin_hdir_set_owner(p, p->task); ++ rwsem_release(&p->hdir->hi_inode->i_rwsem.dep_map, 1, _RET_IP_); ++ } ++} ++ ++struct dentry *au_pinned_h_parent(struct au_pin *pin) ++{ ++ if (pin && pin->parent) ++ return au_h_dptr(pin->parent, pin->bindex); ++ return NULL; ++} ++ ++void au_unpin(struct au_pin *p) ++{ ++ if (p->hdir) ++ au_pin_hdir_unlock(p); ++ if (p->h_mnt && au_ftest_pin(p->flags, MNT_WRITE)) ++ vfsub_mnt_drop_write(p->h_mnt); ++ if (!p->hdir) ++ return; ++ ++ if (!au_ftest_pin(p->flags, DI_LOCKED)) ++ di_read_unlock(p->parent, AuLock_IR); ++ iput(p->hdir->hi_inode); ++ dput(p->parent); ++ p->parent = NULL; ++ p->hdir = NULL; ++ p->h_mnt = NULL; ++ /* do not clear p->task */ ++} ++ ++int au_do_pin(struct au_pin *p) ++{ ++ int err; ++ struct super_block *sb; ++ struct inode *h_dir; ++ ++ err = 0; ++ sb = p->dentry->d_sb; ++ p->br = au_sbr(sb, p->bindex); ++ if (IS_ROOT(p->dentry)) { ++ if (au_ftest_pin(p->flags, MNT_WRITE)) { ++ p->h_mnt = au_br_mnt(p->br); ++ err = vfsub_mnt_want_write(p->h_mnt); ++ if (unlikely(err)) { ++ au_fclr_pin(p->flags, MNT_WRITE); ++ goto out_err; ++ } ++ } ++ goto out; ++ } ++ ++ p->h_dentry = NULL; ++ if (p->bindex <= au_dbbot(p->dentry)) ++ p->h_dentry = au_h_dptr(p->dentry, p->bindex); ++ ++ p->parent = dget_parent(p->dentry); ++ if (!au_ftest_pin(p->flags, DI_LOCKED)) ++ di_read_lock(p->parent, AuLock_IR, p->lsc_di); ++ ++ h_dir = NULL; ++ p->h_parent = au_h_dptr(p->parent, p->bindex); ++ p->hdir = au_hi(d_inode(p->parent), p->bindex); ++ if (p->hdir) ++ h_dir = p->hdir->hi_inode; ++ ++ /* ++ * udba case, or ++ * if DI_LOCKED is not set, then p->parent may be different ++ * and h_parent can be NULL. ++ */ ++ if (unlikely(!p->hdir || !h_dir || !p->h_parent)) { ++ err = -EBUSY; ++ if (!au_ftest_pin(p->flags, DI_LOCKED)) ++ di_read_unlock(p->parent, AuLock_IR); ++ dput(p->parent); ++ p->parent = NULL; ++ goto out_err; ++ } ++ ++ if (au_ftest_pin(p->flags, MNT_WRITE)) { ++ p->h_mnt = au_br_mnt(p->br); ++ err = vfsub_mnt_want_write(p->h_mnt); ++ if (unlikely(err)) { ++ au_fclr_pin(p->flags, MNT_WRITE); ++ if (!au_ftest_pin(p->flags, DI_LOCKED)) ++ di_read_unlock(p->parent, AuLock_IR); ++ dput(p->parent); ++ p->parent = NULL; ++ goto out_err; ++ } ++ } ++ ++ au_igrab(h_dir); ++ err = au_pin_hdir_lock(p); ++ if (!err) ++ goto out; /* success */ ++ ++ au_unpin(p); ++ ++out_err: ++ pr_err("err %d\n", err); ++ err = au_busy_or_stale(); ++out: ++ return err; ++} ++ ++void au_pin_init(struct au_pin *p, struct dentry *dentry, ++ aufs_bindex_t bindex, int lsc_di, int lsc_hi, ++ unsigned int udba, unsigned char flags) ++{ ++ p->dentry = dentry; ++ p->udba = udba; ++ p->lsc_di = lsc_di; ++ p->lsc_hi = lsc_hi; ++ p->flags = flags; ++ p->bindex = bindex; ++ ++ p->parent = NULL; ++ p->hdir = NULL; ++ p->h_mnt = NULL; ++ ++ p->h_dentry = NULL; ++ p->h_parent = NULL; ++ p->br = NULL; ++ p->task = current; ++} ++ ++int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex, ++ unsigned int udba, unsigned char flags) ++{ ++ au_pin_init(pin, dentry, bindex, AuLsc_DI_PARENT, AuLsc_I_PARENT2, ++ udba, flags); ++ return au_do_pin(pin); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * ->setattr() and ->getattr() are called in various cases. ++ * chmod, stat: dentry is revalidated. ++ * fchmod, fstat: file and dentry are not revalidated, additionally they may be ++ * unhashed. ++ * for ->setattr(), ia->ia_file is passed from ftruncate only. ++ */ ++/* todo: consolidate with do_refresh() and simple_reval_dpath() */ ++int au_reval_for_attr(struct dentry *dentry, unsigned int sigen) ++{ ++ int err; ++ struct dentry *parent; ++ ++ err = 0; ++ if (au_digen_test(dentry, sigen)) { ++ parent = dget_parent(dentry); ++ di_read_lock_parent(parent, AuLock_IR); ++ err = au_refresh_dentry(dentry, parent); ++ di_read_unlock(parent, AuLock_IR); ++ dput(parent); ++ } ++ ++ AuTraceErr(err); ++ return err; ++} ++ ++int au_pin_and_icpup(struct dentry *dentry, struct iattr *ia, ++ struct au_icpup_args *a) ++{ ++ int err; ++ loff_t sz; ++ aufs_bindex_t btop, ibtop; ++ struct dentry *hi_wh, *parent; ++ struct inode *inode; ++ struct au_wr_dir_args wr_dir_args = { ++ .force_btgt = -1, ++ .flags = 0 ++ }; ++ ++ if (d_is_dir(dentry)) ++ au_fset_wrdir(wr_dir_args.flags, ISDIR); ++ /* plink or hi_wh() case */ ++ btop = au_dbtop(dentry); ++ inode = d_inode(dentry); ++ ibtop = au_ibtop(inode); ++ if (btop != ibtop && !au_test_ro(inode->i_sb, ibtop, inode)) ++ wr_dir_args.force_btgt = ibtop; ++ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args); ++ if (unlikely(err < 0)) ++ goto out; ++ a->btgt = err; ++ if (err != btop) ++ au_fset_icpup(a->flags, DID_CPUP); ++ ++ err = 0; ++ a->pin_flags = AuPin_MNT_WRITE; ++ parent = NULL; ++ if (!IS_ROOT(dentry)) { ++ au_fset_pin(a->pin_flags, DI_LOCKED); ++ parent = dget_parent(dentry); ++ di_write_lock_parent(parent); ++ } ++ ++ err = au_pin(&a->pin, dentry, a->btgt, a->udba, a->pin_flags); ++ if (unlikely(err)) ++ goto out_parent; ++ ++ sz = -1; ++ a->h_path.dentry = au_h_dptr(dentry, btop); ++ a->h_inode = d_inode(a->h_path.dentry); ++ if (ia && (ia->ia_valid & ATTR_SIZE)) { ++ inode_lock_shared_nested(a->h_inode, AuLsc_I_CHILD); ++ if (ia->ia_size < i_size_read(a->h_inode)) ++ sz = ia->ia_size; ++ inode_unlock_shared(a->h_inode); ++ } ++ ++ hi_wh = NULL; ++ if (au_ftest_icpup(a->flags, DID_CPUP) && d_unlinked(dentry)) { ++ hi_wh = au_hi_wh(inode, a->btgt); ++ if (!hi_wh) { ++ struct au_cp_generic cpg = { ++ .dentry = dentry, ++ .bdst = a->btgt, ++ .bsrc = -1, ++ .len = sz, ++ .pin = &a->pin ++ }; ++ err = au_sio_cpup_wh(&cpg, /*file*/NULL); ++ if (unlikely(err)) ++ goto out_unlock; ++ hi_wh = au_hi_wh(inode, a->btgt); ++ /* todo: revalidate hi_wh? */ ++ } ++ } ++ ++ if (parent) { ++ au_pin_set_parent_lflag(&a->pin, /*lflag*/0); ++ di_downgrade_lock(parent, AuLock_IR); ++ dput(parent); ++ parent = NULL; ++ } ++ if (!au_ftest_icpup(a->flags, DID_CPUP)) ++ goto out; /* success */ ++ ++ if (!d_unhashed(dentry)) { ++ struct au_cp_generic cpg = { ++ .dentry = dentry, ++ .bdst = a->btgt, ++ .bsrc = btop, ++ .len = sz, ++ .pin = &a->pin, ++ .flags = AuCpup_DTIME | AuCpup_HOPEN ++ }; ++ err = au_sio_cpup_simple(&cpg); ++ if (!err) ++ a->h_path.dentry = au_h_dptr(dentry, a->btgt); ++ } else if (!hi_wh) ++ a->h_path.dentry = au_h_dptr(dentry, a->btgt); ++ else ++ a->h_path.dentry = hi_wh; /* do not dget here */ ++ ++out_unlock: ++ a->h_inode = d_inode(a->h_path.dentry); ++ if (!err) ++ goto out; /* success */ ++ au_unpin(&a->pin); ++out_parent: ++ if (parent) { ++ di_write_unlock(parent); ++ dput(parent); ++ } ++out: ++ if (!err) ++ inode_lock_nested(a->h_inode, AuLsc_I_CHILD); ++ return err; ++} ++ ++static int aufs_setattr(struct dentry *dentry, struct iattr *ia) ++{ ++ int err; ++ struct inode *inode, *delegated; ++ struct super_block *sb; ++ struct file *file; ++ struct au_icpup_args *a; ++ ++ inode = d_inode(dentry); ++ IMustLock(inode); ++ ++ err = setattr_prepare(dentry, ia); ++ if (unlikely(err)) ++ goto out; ++ ++ err = -ENOMEM; ++ a = kzalloc(sizeof(*a), GFP_NOFS); ++ if (unlikely(!a)) ++ goto out; ++ ++ if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID)) ++ ia->ia_valid &= ~ATTR_MODE; ++ ++ file = NULL; ++ sb = dentry->d_sb; ++ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM); ++ if (unlikely(err)) ++ goto out_kfree; ++ ++ if (ia->ia_valid & ATTR_FILE) { ++ /* currently ftruncate(2) only */ ++ AuDebugOn(!d_is_reg(dentry)); ++ file = ia->ia_file; ++ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1, ++ /*fi_lsc*/0); ++ if (unlikely(err)) ++ goto out_si; ++ ia->ia_file = au_hf_top(file); ++ a->udba = AuOpt_UDBA_NONE; ++ } else { ++ /* fchmod() doesn't pass ia_file */ ++ a->udba = au_opt_udba(sb); ++ di_write_lock_child(dentry); ++ /* no d_unlinked(), to set UDBA_NONE for root */ ++ if (d_unhashed(dentry)) ++ a->udba = AuOpt_UDBA_NONE; ++ if (a->udba != AuOpt_UDBA_NONE) { ++ AuDebugOn(IS_ROOT(dentry)); ++ err = au_reval_for_attr(dentry, au_sigen(sb)); ++ if (unlikely(err)) ++ goto out_dentry; ++ } ++ } ++ ++ err = au_pin_and_icpup(dentry, ia, a); ++ if (unlikely(err < 0)) ++ goto out_dentry; ++ if (au_ftest_icpup(a->flags, DID_CPUP)) { ++ ia->ia_file = NULL; ++ ia->ia_valid &= ~ATTR_FILE; ++ } ++ ++ a->h_path.mnt = au_sbr_mnt(sb, a->btgt); ++ if ((ia->ia_valid & (ATTR_MODE | ATTR_CTIME)) ++ == (ATTR_MODE | ATTR_CTIME)) { ++ err = security_path_chmod(&a->h_path, ia->ia_mode); ++ if (unlikely(err)) ++ goto out_unlock; ++ } else if ((ia->ia_valid & (ATTR_UID | ATTR_GID)) ++ && (ia->ia_valid & ATTR_CTIME)) { ++ err = security_path_chown(&a->h_path, ia->ia_uid, ia->ia_gid); ++ if (unlikely(err)) ++ goto out_unlock; ++ } ++ ++ if (ia->ia_valid & ATTR_SIZE) { ++ struct file *f; ++ ++ if (ia->ia_size < i_size_read(inode)) ++ /* unmap only */ ++ truncate_setsize(inode, ia->ia_size); ++ ++ f = NULL; ++ if (ia->ia_valid & ATTR_FILE) ++ f = ia->ia_file; ++ inode_unlock(a->h_inode); ++ err = vfsub_trunc(&a->h_path, ia->ia_size, ia->ia_valid, f); ++ inode_lock_nested(a->h_inode, AuLsc_I_CHILD); ++ } else { ++ delegated = NULL; ++ while (1) { ++ err = vfsub_notify_change(&a->h_path, ia, &delegated); ++ if (delegated) { ++ err = break_deleg_wait(&delegated); ++ if (!err) ++ continue; ++ } ++ break; ++ } ++ } ++ /* ++ * regardless aufs 'acl' option setting. ++ * why don't all acl-aware fs call this func from their ->setattr()? ++ */ ++ if (!err && (ia->ia_valid & ATTR_MODE)) ++ err = vfsub_acl_chmod(a->h_inode, ia->ia_mode); ++ if (!err) ++ au_cpup_attr_changeable(inode); ++ ++out_unlock: ++ inode_unlock(a->h_inode); ++ au_unpin(&a->pin); ++ if (unlikely(err)) ++ au_update_dbtop(dentry); ++out_dentry: ++ di_write_unlock(dentry); ++ if (file) { ++ fi_write_unlock(file); ++ ia->ia_file = file; ++ ia->ia_valid |= ATTR_FILE; ++ } ++out_si: ++ si_read_unlock(sb); ++out_kfree: ++ au_kfree_rcu(a); ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++#if IS_ENABLED(CONFIG_AUFS_XATTR) || IS_ENABLED(CONFIG_FS_POSIX_ACL) ++static int au_h_path_to_set_attr(struct dentry *dentry, ++ struct au_icpup_args *a, struct path *h_path) ++{ ++ int err; ++ struct super_block *sb; ++ ++ sb = dentry->d_sb; ++ a->udba = au_opt_udba(sb); ++ /* no d_unlinked(), to set UDBA_NONE for root */ ++ if (d_unhashed(dentry)) ++ a->udba = AuOpt_UDBA_NONE; ++ if (a->udba != AuOpt_UDBA_NONE) { ++ AuDebugOn(IS_ROOT(dentry)); ++ err = au_reval_for_attr(dentry, au_sigen(sb)); ++ if (unlikely(err)) ++ goto out; ++ } ++ err = au_pin_and_icpup(dentry, /*ia*/NULL, a); ++ if (unlikely(err < 0)) ++ goto out; ++ ++ h_path->dentry = a->h_path.dentry; ++ h_path->mnt = au_sbr_mnt(sb, a->btgt); ++ ++out: ++ return err; ++} ++ ++ssize_t au_sxattr(struct dentry *dentry, struct inode *inode, ++ struct au_sxattr *arg) ++{ ++ int err; ++ struct path h_path; ++ struct super_block *sb; ++ struct au_icpup_args *a; ++ struct inode *h_inode; ++ ++ IMustLock(inode); ++ ++ err = -ENOMEM; ++ a = kzalloc(sizeof(*a), GFP_NOFS); ++ if (unlikely(!a)) ++ goto out; ++ ++ sb = dentry->d_sb; ++ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM); ++ if (unlikely(err)) ++ goto out_kfree; ++ ++ h_path.dentry = NULL; /* silence gcc */ ++ di_write_lock_child(dentry); ++ err = au_h_path_to_set_attr(dentry, a, &h_path); ++ if (unlikely(err)) ++ goto out_di; ++ ++ inode_unlock(a->h_inode); ++ switch (arg->type) { ++ case AU_XATTR_SET: ++ AuDebugOn(d_is_negative(h_path.dentry)); ++ err = vfsub_setxattr(h_path.dentry, ++ arg->u.set.name, arg->u.set.value, ++ arg->u.set.size, arg->u.set.flags); ++ break; ++ case AU_ACL_SET: ++ err = -EOPNOTSUPP; ++ h_inode = d_inode(h_path.dentry); ++ if (h_inode->i_op->set_acl) ++ /* this will call posix_acl_update_mode */ ++ err = h_inode->i_op->set_acl(h_inode, ++ arg->u.acl_set.acl, ++ arg->u.acl_set.type); ++ break; ++ } ++ if (!err) ++ au_cpup_attr_timesizes(inode); ++ ++ au_unpin(&a->pin); ++ if (unlikely(err)) ++ au_update_dbtop(dentry); ++ ++out_di: ++ di_write_unlock(dentry); ++ si_read_unlock(sb); ++out_kfree: ++ au_kfree_rcu(a); ++out: ++ AuTraceErr(err); ++ return err; ++} ++#endif ++ ++static void au_refresh_iattr(struct inode *inode, struct kstat *st, ++ unsigned int nlink) ++{ ++ unsigned int n; ++ ++ inode->i_mode = st->mode; ++ /* don't i_[ug]id_write() here */ ++ inode->i_uid = st->uid; ++ inode->i_gid = st->gid; ++ inode->i_atime = st->atime; ++ inode->i_mtime = st->mtime; ++ inode->i_ctime = st->ctime; ++ ++ au_cpup_attr_nlink(inode, /*force*/0); ++ if (S_ISDIR(inode->i_mode)) { ++ n = inode->i_nlink; ++ n -= nlink; ++ n += st->nlink; ++ smp_mb(); /* for i_nlink */ ++ /* 0 can happen */ ++ set_nlink(inode, n); ++ } ++ ++ spin_lock(&inode->i_lock); ++ inode->i_blocks = st->blocks; ++ i_size_write(inode, st->size); ++ spin_unlock(&inode->i_lock); ++} ++ ++/* ++ * common routine for aufs_getattr() and au_getxattr(). ++ * returns zero or negative (an error). ++ * @dentry will be read-locked in success. ++ */ ++int au_h_path_getattr(struct dentry *dentry, int force, struct path *h_path, ++ int locked) ++{ ++ int err; ++ unsigned int mnt_flags, sigen; ++ unsigned char udba_none; ++ aufs_bindex_t bindex; ++ struct super_block *sb, *h_sb; ++ struct inode *inode; ++ ++ h_path->mnt = NULL; ++ h_path->dentry = NULL; ++ ++ err = 0; ++ sb = dentry->d_sb; ++ mnt_flags = au_mntflags(sb); ++ udba_none = !!au_opt_test(mnt_flags, UDBA_NONE); ++ ++ if (unlikely(locked)) ++ goto body; /* skip locking dinfo */ ++ ++ /* support fstat(2) */ ++ if (!d_unlinked(dentry) && !udba_none) { ++ sigen = au_sigen(sb); ++ err = au_digen_test(dentry, sigen); ++ if (!err) { ++ di_read_lock_child(dentry, AuLock_IR); ++ err = au_dbrange_test(dentry); ++ if (unlikely(err)) { ++ di_read_unlock(dentry, AuLock_IR); ++ goto out; ++ } ++ } else { ++ AuDebugOn(IS_ROOT(dentry)); ++ di_write_lock_child(dentry); ++ err = au_dbrange_test(dentry); ++ if (!err) ++ err = au_reval_for_attr(dentry, sigen); ++ if (!err) ++ di_downgrade_lock(dentry, AuLock_IR); ++ else { ++ di_write_unlock(dentry); ++ goto out; ++ } ++ } ++ } else ++ di_read_lock_child(dentry, AuLock_IR); ++ ++body: ++ inode = d_inode(dentry); ++ bindex = au_ibtop(inode); ++ h_path->mnt = au_sbr_mnt(sb, bindex); ++ h_sb = h_path->mnt->mnt_sb; ++ if (!force ++ && !au_test_fs_bad_iattr(h_sb) ++ && udba_none) ++ goto out; /* success */ ++ ++ if (au_dbtop(dentry) == bindex) ++ h_path->dentry = au_h_dptr(dentry, bindex); ++ else if (au_opt_test(mnt_flags, PLINK) && au_plink_test(inode)) { ++ h_path->dentry = au_plink_lkup(inode, bindex); ++ if (IS_ERR(h_path->dentry)) ++ /* pretending success */ ++ h_path->dentry = NULL; ++ else ++ dput(h_path->dentry); ++ } ++ ++out: ++ return err; ++} ++ ++static int aufs_getattr(const struct path *path, struct kstat *st, ++ u32 request, unsigned int query) ++{ ++ int err; ++ unsigned char positive; ++ struct path h_path; ++ struct dentry *dentry; ++ struct inode *inode; ++ struct super_block *sb; ++ ++ dentry = path->dentry; ++ inode = d_inode(dentry); ++ sb = dentry->d_sb; ++ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM); ++ if (unlikely(err)) ++ goto out; ++ err = au_h_path_getattr(dentry, /*force*/0, &h_path, /*locked*/0); ++ if (unlikely(err)) ++ goto out_si; ++ if (unlikely(!h_path.dentry)) ++ /* illegally overlapped or something */ ++ goto out_fill; /* pretending success */ ++ ++ positive = d_is_positive(h_path.dentry); ++ if (positive) ++ /* no vfsub version */ ++ err = vfs_getattr(&h_path, st, request, query); ++ if (!err) { ++ if (positive) ++ au_refresh_iattr(inode, st, ++ d_inode(h_path.dentry)->i_nlink); ++ goto out_fill; /* success */ ++ } ++ AuTraceErr(err); ++ goto out_di; ++ ++out_fill: ++ generic_fillattr(inode, st); ++out_di: ++ di_read_unlock(dentry, AuLock_IR); ++out_si: ++ si_read_unlock(sb); ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static const char *aufs_get_link(struct dentry *dentry, struct inode *inode, ++ struct delayed_call *done) ++{ ++ const char *ret; ++ struct dentry *h_dentry; ++ struct inode *h_inode; ++ int err; ++ aufs_bindex_t bindex; ++ ++ ret = NULL; /* suppress a warning */ ++ err = -ECHILD; ++ if (!dentry) ++ goto out; ++ ++ err = aufs_read_lock(dentry, AuLock_IR | AuLock_GEN); ++ if (unlikely(err)) ++ goto out; ++ ++ err = au_d_hashed_positive(dentry); ++ if (unlikely(err)) ++ goto out_unlock; ++ ++ err = -EINVAL; ++ inode = d_inode(dentry); ++ bindex = au_ibtop(inode); ++ h_inode = au_h_iptr(inode, bindex); ++ if (unlikely(!h_inode->i_op->get_link)) ++ goto out_unlock; ++ ++ err = -EBUSY; ++ h_dentry = NULL; ++ if (au_dbtop(dentry) <= bindex) { ++ h_dentry = au_h_dptr(dentry, bindex); ++ if (h_dentry) ++ dget(h_dentry); ++ } ++ if (!h_dentry) { ++ h_dentry = d_find_any_alias(h_inode); ++ if (IS_ERR(h_dentry)) { ++ err = PTR_ERR(h_dentry); ++ goto out_unlock; ++ } ++ } ++ if (unlikely(!h_dentry)) ++ goto out_unlock; ++ ++ err = 0; ++ AuDbg("%ps\n", h_inode->i_op->get_link); ++ AuDbgDentry(h_dentry); ++ ret = vfs_get_link(h_dentry, done); ++ dput(h_dentry); ++ if (IS_ERR(ret)) ++ err = PTR_ERR(ret); ++ ++out_unlock: ++ aufs_read_unlock(dentry, AuLock_IR); ++out: ++ if (unlikely(err)) ++ ret = ERR_PTR(err); ++ AuTraceErrPtr(ret); ++ return ret; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int au_is_special(struct inode *inode) ++{ ++ return (inode->i_mode & (S_IFBLK | S_IFCHR | S_IFIFO | S_IFSOCK)); ++} ++ ++static int aufs_update_time(struct inode *inode, struct timespec64 *ts, ++ int flags) ++{ ++ int err; ++ aufs_bindex_t bindex; ++ struct super_block *sb; ++ struct inode *h_inode; ++ struct vfsmount *h_mnt; ++ ++ sb = inode->i_sb; ++ WARN_ONCE((flags & S_ATIME) && !IS_NOATIME(inode), ++ "unexpected s_flags 0x%lx", sb->s_flags); ++ ++ /* mmap_sem might be acquired already, cf. aufs_mmap() */ ++ lockdep_off(); ++ si_read_lock(sb, AuLock_FLUSH); ++ ii_write_lock_child(inode); ++ ++ err = 0; ++ bindex = au_ibtop(inode); ++ h_inode = au_h_iptr(inode, bindex); ++ if (!au_test_ro(sb, bindex, inode)) { ++ h_mnt = au_sbr_mnt(sb, bindex); ++ err = vfsub_mnt_want_write(h_mnt); ++ if (!err) { ++ err = vfsub_update_time(h_inode, ts, flags); ++ vfsub_mnt_drop_write(h_mnt); ++ } ++ } else if (au_is_special(h_inode)) { ++ /* ++ * Never copy-up here. ++ * These special files may already be opened and used for ++ * communicating. If we copied it up, then the communication ++ * would be corrupted. ++ */ ++ AuWarn1("timestamps for i%lu are ignored " ++ "since it is on readonly branch (hi%lu).\n", ++ inode->i_ino, h_inode->i_ino); ++ } else if (flags & ~S_ATIME) { ++ err = -EIO; ++ AuIOErr1("unexpected flags 0x%x\n", flags); ++ AuDebugOn(1); ++ } ++ ++ if (!err) ++ au_cpup_attr_timesizes(inode); ++ ii_write_unlock(inode); ++ si_read_unlock(sb); ++ lockdep_on(); ++ ++ if (!err && (flags & S_VERSION)) ++ inode_inc_iversion(inode); ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* no getattr version will be set by module.c:aufs_init() */ ++struct inode_operations aufs_iop_nogetattr[AuIop_Last], ++ aufs_iop[] = { ++ [AuIop_SYMLINK] = { ++ .permission = aufs_permission, ++#ifdef CONFIG_FS_POSIX_ACL ++ .get_acl = aufs_get_acl, ++ .set_acl = aufs_set_acl, /* unsupport for symlink? */ ++#endif ++ ++ .setattr = aufs_setattr, ++ .getattr = aufs_getattr, ++ ++#ifdef CONFIG_AUFS_XATTR ++ .listxattr = aufs_listxattr, ++#endif ++ ++ .get_link = aufs_get_link, ++ ++ /* .update_time = aufs_update_time */ ++ }, ++ [AuIop_DIR] = { ++ .create = aufs_create, ++ .lookup = aufs_lookup, ++ .link = aufs_link, ++ .unlink = aufs_unlink, ++ .symlink = aufs_symlink, ++ .mkdir = aufs_mkdir, ++ .rmdir = aufs_rmdir, ++ .mknod = aufs_mknod, ++ .rename = aufs_rename, ++ ++ .permission = aufs_permission, ++#ifdef CONFIG_FS_POSIX_ACL ++ .get_acl = aufs_get_acl, ++ .set_acl = aufs_set_acl, ++#endif ++ ++ .setattr = aufs_setattr, ++ .getattr = aufs_getattr, ++ ++#ifdef CONFIG_AUFS_XATTR ++ .listxattr = aufs_listxattr, ++#endif ++ ++ .update_time = aufs_update_time, ++ .atomic_open = aufs_atomic_open, ++ .tmpfile = aufs_tmpfile ++ }, ++ [AuIop_OTHER] = { ++ .permission = aufs_permission, ++#ifdef CONFIG_FS_POSIX_ACL ++ .get_acl = aufs_get_acl, ++ .set_acl = aufs_set_acl, ++#endif ++ ++ .setattr = aufs_setattr, ++ .getattr = aufs_getattr, ++ ++#ifdef CONFIG_AUFS_XATTR ++ .listxattr = aufs_listxattr, ++#endif ++ ++ .update_time = aufs_update_time ++ } ++}; +diff -Nurp linux-5.4/fs/aufs/i_op_del.c linux-5.4-aufs/fs/aufs/i_op_del.c +--- linux-5.4/fs/aufs/i_op_del.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/i_op_del.c 2019-11-28 01:25:59.066925618 +0200 +@@ -0,0 +1,500 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * inode operations (del entry) ++ */ ++ ++#include ++#include "aufs.h" ++ ++/* ++ * decide if a new whiteout for @dentry is necessary or not. ++ * when it is necessary, prepare the parent dir for the upper branch whose ++ * branch index is @bcpup for creation. the actual creation of the whiteout will ++ * be done by caller. ++ * return value: ++ * 0: wh is unnecessary ++ * plus: wh is necessary ++ * minus: error ++ */ ++int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup) ++{ ++ int need_wh, err; ++ aufs_bindex_t btop; ++ struct super_block *sb; ++ ++ sb = dentry->d_sb; ++ btop = au_dbtop(dentry); ++ if (*bcpup < 0) { ++ *bcpup = btop; ++ if (au_test_ro(sb, btop, d_inode(dentry))) { ++ err = AuWbrCopyup(au_sbi(sb), dentry); ++ *bcpup = err; ++ if (unlikely(err < 0)) ++ goto out; ++ } ++ } else ++ AuDebugOn(btop < *bcpup ++ || au_test_ro(sb, *bcpup, d_inode(dentry))); ++ AuDbg("bcpup %d, btop %d\n", *bcpup, btop); ++ ++ if (*bcpup != btop) { ++ err = au_cpup_dirs(dentry, *bcpup); ++ if (unlikely(err)) ++ goto out; ++ need_wh = 1; ++ } else { ++ struct au_dinfo *dinfo, *tmp; ++ ++ need_wh = -ENOMEM; ++ dinfo = au_di(dentry); ++ tmp = au_di_alloc(sb, AuLsc_DI_TMP); ++ if (tmp) { ++ au_di_cp(tmp, dinfo); ++ au_di_swap(tmp, dinfo); ++ /* returns the number of positive dentries */ ++ need_wh = au_lkup_dentry(dentry, btop + 1, ++ /* AuLkup_IGNORE_PERM */ 0); ++ au_di_swap(tmp, dinfo); ++ au_rw_write_unlock(&tmp->di_rwsem); ++ au_di_free(tmp); ++ } ++ } ++ AuDbg("need_wh %d\n", need_wh); ++ err = need_wh; ++ ++out: ++ return err; ++} ++ ++/* ++ * simple tests for the del-entry operations. ++ * following the checks in vfs, plus the parent-child relationship. ++ */ ++int au_may_del(struct dentry *dentry, aufs_bindex_t bindex, ++ struct dentry *h_parent, int isdir) ++{ ++ int err; ++ umode_t h_mode; ++ struct dentry *h_dentry, *h_latest; ++ struct inode *h_inode; ++ ++ h_dentry = au_h_dptr(dentry, bindex); ++ if (d_really_is_positive(dentry)) { ++ err = -ENOENT; ++ if (unlikely(d_is_negative(h_dentry))) ++ goto out; ++ h_inode = d_inode(h_dentry); ++ if (unlikely(!h_inode->i_nlink)) ++ goto out; ++ ++ h_mode = h_inode->i_mode; ++ if (!isdir) { ++ err = -EISDIR; ++ if (unlikely(S_ISDIR(h_mode))) ++ goto out; ++ } else if (unlikely(!S_ISDIR(h_mode))) { ++ err = -ENOTDIR; ++ goto out; ++ } ++ } else { ++ /* rename(2) case */ ++ err = -EIO; ++ if (unlikely(d_is_positive(h_dentry))) ++ goto out; ++ } ++ ++ err = -ENOENT; ++ /* expected parent dir is locked */ ++ if (unlikely(h_parent != h_dentry->d_parent)) ++ goto out; ++ err = 0; ++ ++ /* ++ * rmdir a dir may break the consistency on some filesystem. ++ * let's try heavy test. ++ */ ++ err = -EACCES; ++ if (unlikely(!au_opt_test(au_mntflags(dentry->d_sb), DIRPERM1) ++ && au_test_h_perm(d_inode(h_parent), ++ MAY_EXEC | MAY_WRITE))) ++ goto out; ++ ++ h_latest = au_sio_lkup_one(&dentry->d_name, h_parent); ++ err = -EIO; ++ if (IS_ERR(h_latest)) ++ goto out; ++ if (h_latest == h_dentry) ++ err = 0; ++ dput(h_latest); ++ ++out: ++ return err; ++} ++ ++/* ++ * decide the branch where we operate for @dentry. the branch index will be set ++ * @rbcpup. after deciding it, 'pin' it and store the timestamps of the parent ++ * dir for reverting. ++ * when a new whiteout is necessary, create it. ++ */ ++static struct dentry* ++lock_hdir_create_wh(struct dentry *dentry, int isdir, aufs_bindex_t *rbcpup, ++ struct au_dtime *dt, struct au_pin *pin) ++{ ++ struct dentry *wh_dentry; ++ struct super_block *sb; ++ struct path h_path; ++ int err, need_wh; ++ unsigned int udba; ++ aufs_bindex_t bcpup; ++ ++ need_wh = au_wr_dir_need_wh(dentry, isdir, rbcpup); ++ wh_dentry = ERR_PTR(need_wh); ++ if (unlikely(need_wh < 0)) ++ goto out; ++ ++ sb = dentry->d_sb; ++ udba = au_opt_udba(sb); ++ bcpup = *rbcpup; ++ err = au_pin(pin, dentry, bcpup, udba, ++ AuPin_DI_LOCKED | AuPin_MNT_WRITE); ++ wh_dentry = ERR_PTR(err); ++ if (unlikely(err)) ++ goto out; ++ ++ h_path.dentry = au_pinned_h_parent(pin); ++ if (udba != AuOpt_UDBA_NONE ++ && au_dbtop(dentry) == bcpup) { ++ err = au_may_del(dentry, bcpup, h_path.dentry, isdir); ++ wh_dentry = ERR_PTR(err); ++ if (unlikely(err)) ++ goto out_unpin; ++ } ++ ++ h_path.mnt = au_sbr_mnt(sb, bcpup); ++ au_dtime_store(dt, au_pinned_parent(pin), &h_path); ++ wh_dentry = NULL; ++ if (!need_wh) ++ goto out; /* success, no need to create whiteout */ ++ ++ wh_dentry = au_wh_create(dentry, bcpup, h_path.dentry); ++ if (IS_ERR(wh_dentry)) ++ goto out_unpin; ++ ++ /* returns with the parent is locked and wh_dentry is dget-ed */ ++ goto out; /* success */ ++ ++out_unpin: ++ au_unpin(pin); ++out: ++ return wh_dentry; ++} ++ ++/* ++ * when removing a dir, rename it to a unique temporary whiteout-ed name first ++ * in order to be revertible and save time for removing many child whiteouts ++ * under the dir. ++ * returns 1 when there are too many child whiteout and caller should remove ++ * them asynchronously. returns 0 when the number of children is enough small to ++ * remove now or the branch fs is a remote fs. ++ * otherwise return an error. ++ */ ++static int renwh_and_rmdir(struct dentry *dentry, aufs_bindex_t bindex, ++ struct au_nhash *whlist, struct inode *dir) ++{ ++ int rmdir_later, err, dirwh; ++ struct dentry *h_dentry; ++ struct super_block *sb; ++ struct inode *inode; ++ ++ sb = dentry->d_sb; ++ SiMustAnyLock(sb); ++ h_dentry = au_h_dptr(dentry, bindex); ++ err = au_whtmp_ren(h_dentry, au_sbr(sb, bindex)); ++ if (unlikely(err)) ++ goto out; ++ ++ /* stop monitoring */ ++ inode = d_inode(dentry); ++ au_hn_free(au_hi(inode, bindex)); ++ ++ if (!au_test_fs_remote(h_dentry->d_sb)) { ++ dirwh = au_sbi(sb)->si_dirwh; ++ rmdir_later = (dirwh <= 1); ++ if (!rmdir_later) ++ rmdir_later = au_nhash_test_longer_wh(whlist, bindex, ++ dirwh); ++ if (rmdir_later) ++ return rmdir_later; ++ } ++ ++ err = au_whtmp_rmdir(dir, bindex, h_dentry, whlist); ++ if (unlikely(err)) { ++ AuIOErr("rmdir %pd, b%d failed, %d. ignored\n", ++ h_dentry, bindex, err); ++ err = 0; ++ } ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++/* ++ * final procedure for deleting a entry. ++ * maintain dentry and iattr. ++ */ ++static void epilog(struct inode *dir, struct dentry *dentry, ++ aufs_bindex_t bindex) ++{ ++ struct inode *inode; ++ ++ inode = d_inode(dentry); ++ d_drop(dentry); ++ inode->i_ctime = dir->i_ctime; ++ ++ au_dir_ts(dir, bindex); ++ inode_inc_iversion(dir); ++} ++ ++/* ++ * when an error happened, remove the created whiteout and revert everything. ++ */ ++static int do_revert(int err, struct inode *dir, aufs_bindex_t bindex, ++ aufs_bindex_t bwh, struct dentry *wh_dentry, ++ struct dentry *dentry, struct au_dtime *dt) ++{ ++ int rerr; ++ struct path h_path = { ++ .dentry = wh_dentry, ++ .mnt = au_sbr_mnt(dir->i_sb, bindex) ++ }; ++ ++ rerr = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path, dentry); ++ if (!rerr) { ++ au_set_dbwh(dentry, bwh); ++ au_dtime_revert(dt); ++ return 0; ++ } ++ ++ AuIOErr("%pd reverting whiteout failed(%d, %d)\n", dentry, err, rerr); ++ return -EIO; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++int aufs_unlink(struct inode *dir, struct dentry *dentry) ++{ ++ int err; ++ aufs_bindex_t bwh, bindex, btop; ++ struct inode *inode, *h_dir, *delegated; ++ struct dentry *parent, *wh_dentry; ++ /* to reduce stack size */ ++ struct { ++ struct au_dtime dt; ++ struct au_pin pin; ++ struct path h_path; ++ } *a; ++ ++ IMustLock(dir); ++ ++ err = -ENOMEM; ++ a = kmalloc(sizeof(*a), GFP_NOFS); ++ if (unlikely(!a)) ++ goto out; ++ ++ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN); ++ if (unlikely(err)) ++ goto out_free; ++ err = au_d_hashed_positive(dentry); ++ if (unlikely(err)) ++ goto out_unlock; ++ inode = d_inode(dentry); ++ IMustLock(inode); ++ err = -EISDIR; ++ if (unlikely(d_is_dir(dentry))) ++ goto out_unlock; /* possible? */ ++ ++ btop = au_dbtop(dentry); ++ bwh = au_dbwh(dentry); ++ bindex = -1; ++ parent = dentry->d_parent; /* dir inode is locked */ ++ di_write_lock_parent(parent); ++ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/0, &bindex, &a->dt, ++ &a->pin); ++ err = PTR_ERR(wh_dentry); ++ if (IS_ERR(wh_dentry)) ++ goto out_parent; ++ ++ a->h_path.mnt = au_sbr_mnt(dentry->d_sb, btop); ++ a->h_path.dentry = au_h_dptr(dentry, btop); ++ dget(a->h_path.dentry); ++ if (bindex == btop) { ++ h_dir = au_pinned_h_dir(&a->pin); ++ delegated = NULL; ++ err = vfsub_unlink(h_dir, &a->h_path, &delegated, /*force*/0); ++ if (unlikely(err == -EWOULDBLOCK)) { ++ pr_warn("cannot retry for NFSv4 delegation" ++ " for an internal unlink\n"); ++ iput(delegated); ++ } ++ } else { ++ /* dir inode is locked */ ++ h_dir = d_inode(wh_dentry->d_parent); ++ IMustLock(h_dir); ++ err = 0; ++ } ++ ++ if (!err) { ++ vfsub_drop_nlink(inode); ++ epilog(dir, dentry, bindex); ++ ++ /* update target timestamps */ ++ if (bindex == btop) { ++ vfsub_update_h_iattr(&a->h_path, /*did*/NULL); ++ /*ignore*/ ++ inode->i_ctime = d_inode(a->h_path.dentry)->i_ctime; ++ } else ++ /* todo: this timestamp may be reverted later */ ++ inode->i_ctime = h_dir->i_ctime; ++ goto out_unpin; /* success */ ++ } ++ ++ /* revert */ ++ if (wh_dentry) { ++ int rerr; ++ ++ rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry, ++ &a->dt); ++ if (rerr) ++ err = rerr; ++ } ++ ++out_unpin: ++ au_unpin(&a->pin); ++ dput(wh_dentry); ++ dput(a->h_path.dentry); ++out_parent: ++ di_write_unlock(parent); ++out_unlock: ++ aufs_read_unlock(dentry, AuLock_DW); ++out_free: ++ au_kfree_rcu(a); ++out: ++ return err; ++} ++ ++int aufs_rmdir(struct inode *dir, struct dentry *dentry) ++{ ++ int err, rmdir_later; ++ aufs_bindex_t bwh, bindex, btop; ++ struct inode *inode; ++ struct dentry *parent, *wh_dentry, *h_dentry; ++ struct au_whtmp_rmdir *args; ++ /* to reduce stack size */ ++ struct { ++ struct au_dtime dt; ++ struct au_pin pin; ++ } *a; ++ ++ IMustLock(dir); ++ ++ err = -ENOMEM; ++ a = kmalloc(sizeof(*a), GFP_NOFS); ++ if (unlikely(!a)) ++ goto out; ++ ++ err = aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH | AuLock_GEN); ++ if (unlikely(err)) ++ goto out_free; ++ err = au_alive_dir(dentry); ++ if (unlikely(err)) ++ goto out_unlock; ++ inode = d_inode(dentry); ++ IMustLock(inode); ++ err = -ENOTDIR; ++ if (unlikely(!d_is_dir(dentry))) ++ goto out_unlock; /* possible? */ ++ ++ err = -ENOMEM; ++ args = au_whtmp_rmdir_alloc(dir->i_sb, GFP_NOFS); ++ if (unlikely(!args)) ++ goto out_unlock; ++ ++ parent = dentry->d_parent; /* dir inode is locked */ ++ di_write_lock_parent(parent); ++ err = au_test_empty(dentry, &args->whlist); ++ if (unlikely(err)) ++ goto out_parent; ++ ++ btop = au_dbtop(dentry); ++ bwh = au_dbwh(dentry); ++ bindex = -1; ++ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/1, &bindex, &a->dt, ++ &a->pin); ++ err = PTR_ERR(wh_dentry); ++ if (IS_ERR(wh_dentry)) ++ goto out_parent; ++ ++ h_dentry = au_h_dptr(dentry, btop); ++ dget(h_dentry); ++ rmdir_later = 0; ++ if (bindex == btop) { ++ err = renwh_and_rmdir(dentry, btop, &args->whlist, dir); ++ if (err > 0) { ++ rmdir_later = err; ++ err = 0; ++ } ++ } else { ++ /* stop monitoring */ ++ au_hn_free(au_hi(inode, btop)); ++ ++ /* dir inode is locked */ ++ IMustLock(d_inode(wh_dentry->d_parent)); ++ err = 0; ++ } ++ ++ if (!err) { ++ vfsub_dead_dir(inode); ++ au_set_dbdiropq(dentry, -1); ++ epilog(dir, dentry, bindex); ++ ++ if (rmdir_later) { ++ au_whtmp_kick_rmdir(dir, btop, h_dentry, args); ++ args = NULL; ++ } ++ ++ goto out_unpin; /* success */ ++ } ++ ++ /* revert */ ++ AuLabel(revert); ++ if (wh_dentry) { ++ int rerr; ++ ++ rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry, ++ &a->dt); ++ if (rerr) ++ err = rerr; ++ } ++ ++out_unpin: ++ au_unpin(&a->pin); ++ dput(wh_dentry); ++ dput(h_dentry); ++out_parent: ++ di_write_unlock(parent); ++ if (args) ++ au_whtmp_rmdir_free(args); ++out_unlock: ++ aufs_read_unlock(dentry, AuLock_DW); ++out_free: ++ au_kfree_rcu(a); ++out: ++ AuTraceErr(err); ++ return err; ++} +diff -Nurp linux-5.4/fs/aufs/i_op_ren.c linux-5.4-aufs/fs/aufs/i_op_ren.c +--- linux-5.4/fs/aufs/i_op_ren.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/i_op_ren.c 2019-11-28 01:25:59.066925618 +0200 +@@ -0,0 +1,1237 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * inode operation (rename entry) ++ * todo: this is crazy monster ++ */ ++ ++#include ++#include "aufs.h" ++ ++enum { AuSRC, AuDST, AuSrcDst }; ++enum { AuPARENT, AuCHILD, AuParentChild }; ++ ++#define AuRen_ISDIR_SRC 1 ++#define AuRen_ISDIR_DST (1 << 1) ++#define AuRen_ISSAMEDIR (1 << 2) ++#define AuRen_WHSRC (1 << 3) ++#define AuRen_WHDST (1 << 4) ++#define AuRen_MNT_WRITE (1 << 5) ++#define AuRen_DT_DSTDIR (1 << 6) ++#define AuRen_DIROPQ_SRC (1 << 7) ++#define AuRen_DIROPQ_DST (1 << 8) ++#define AuRen_DIRREN (1 << 9) ++#define AuRen_DROPPED_SRC (1 << 10) ++#define AuRen_DROPPED_DST (1 << 11) ++#define au_ftest_ren(flags, name) ((flags) & AuRen_##name) ++#define au_fset_ren(flags, name) \ ++ do { (flags) |= AuRen_##name; } while (0) ++#define au_fclr_ren(flags, name) \ ++ do { (flags) &= ~AuRen_##name; } while (0) ++ ++#ifndef CONFIG_AUFS_DIRREN ++#undef AuRen_DIRREN ++#define AuRen_DIRREN 0 ++#endif ++ ++struct au_ren_args { ++ struct { ++ struct dentry *dentry, *h_dentry, *parent, *h_parent, ++ *wh_dentry; ++ struct inode *dir, *inode; ++ struct au_hinode *hdir, *hinode; ++ struct au_dtime dt[AuParentChild]; ++ aufs_bindex_t btop, bdiropq; ++ } sd[AuSrcDst]; ++ ++#define src_dentry sd[AuSRC].dentry ++#define src_dir sd[AuSRC].dir ++#define src_inode sd[AuSRC].inode ++#define src_h_dentry sd[AuSRC].h_dentry ++#define src_parent sd[AuSRC].parent ++#define src_h_parent sd[AuSRC].h_parent ++#define src_wh_dentry sd[AuSRC].wh_dentry ++#define src_hdir sd[AuSRC].hdir ++#define src_hinode sd[AuSRC].hinode ++#define src_h_dir sd[AuSRC].hdir->hi_inode ++#define src_dt sd[AuSRC].dt ++#define src_btop sd[AuSRC].btop ++#define src_bdiropq sd[AuSRC].bdiropq ++ ++#define dst_dentry sd[AuDST].dentry ++#define dst_dir sd[AuDST].dir ++#define dst_inode sd[AuDST].inode ++#define dst_h_dentry sd[AuDST].h_dentry ++#define dst_parent sd[AuDST].parent ++#define dst_h_parent sd[AuDST].h_parent ++#define dst_wh_dentry sd[AuDST].wh_dentry ++#define dst_hdir sd[AuDST].hdir ++#define dst_hinode sd[AuDST].hinode ++#define dst_h_dir sd[AuDST].hdir->hi_inode ++#define dst_dt sd[AuDST].dt ++#define dst_btop sd[AuDST].btop ++#define dst_bdiropq sd[AuDST].bdiropq ++ ++ struct dentry *h_trap; ++ struct au_branch *br; ++ struct path h_path; ++ struct au_nhash whlist; ++ aufs_bindex_t btgt, src_bwh; ++ ++ struct { ++ unsigned short auren_flags; ++ unsigned char flags; /* syscall parameter */ ++ unsigned char exchange; ++ } __packed; ++ ++ struct au_whtmp_rmdir *thargs; ++ struct dentry *h_dst; ++ struct au_hinode *h_root; ++}; ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * functions for reverting. ++ * when an error happened in a single rename systemcall, we should revert ++ * everything as if nothing happened. ++ * we don't need to revert the copied-up/down the parent dir since they are ++ * harmless. ++ */ ++ ++#define RevertFailure(fmt, ...) do { \ ++ AuIOErr("revert failure: " fmt " (%d, %d)\n", \ ++ ##__VA_ARGS__, err, rerr); \ ++ err = -EIO; \ ++} while (0) ++ ++static void au_ren_do_rev_diropq(int err, struct au_ren_args *a, int idx) ++{ ++ int rerr; ++ struct dentry *d; ++#define src_or_dst(member) a->sd[idx].member ++ ++ d = src_or_dst(dentry); /* {src,dst}_dentry */ ++ au_hn_inode_lock_nested(src_or_dst(hinode), AuLsc_I_CHILD); ++ rerr = au_diropq_remove(d, a->btgt); ++ au_hn_inode_unlock(src_or_dst(hinode)); ++ au_set_dbdiropq(d, src_or_dst(bdiropq)); ++ if (rerr) ++ RevertFailure("remove diropq %pd", d); ++ ++#undef src_or_dst_ ++} ++ ++static void au_ren_rev_diropq(int err, struct au_ren_args *a) ++{ ++ if (au_ftest_ren(a->auren_flags, DIROPQ_SRC)) ++ au_ren_do_rev_diropq(err, a, AuSRC); ++ if (au_ftest_ren(a->auren_flags, DIROPQ_DST)) ++ au_ren_do_rev_diropq(err, a, AuDST); ++} ++ ++static void au_ren_rev_rename(int err, struct au_ren_args *a) ++{ ++ int rerr; ++ struct inode *delegated; ++ ++ a->h_path.dentry = vfsub_lkup_one(&a->src_dentry->d_name, ++ a->src_h_parent); ++ rerr = PTR_ERR(a->h_path.dentry); ++ if (IS_ERR(a->h_path.dentry)) { ++ RevertFailure("lkup one %pd", a->src_dentry); ++ return; ++ } ++ ++ delegated = NULL; ++ rerr = vfsub_rename(a->dst_h_dir, ++ au_h_dptr(a->src_dentry, a->btgt), ++ a->src_h_dir, &a->h_path, &delegated, a->flags); ++ if (unlikely(rerr == -EWOULDBLOCK)) { ++ pr_warn("cannot retry for NFSv4 delegation" ++ " for an internal rename\n"); ++ iput(delegated); ++ } ++ d_drop(a->h_path.dentry); ++ dput(a->h_path.dentry); ++ /* au_set_h_dptr(a->src_dentry, a->btgt, NULL); */ ++ if (rerr) ++ RevertFailure("rename %pd", a->src_dentry); ++} ++ ++static void au_ren_rev_whtmp(int err, struct au_ren_args *a) ++{ ++ int rerr; ++ struct inode *delegated; ++ ++ a->h_path.dentry = vfsub_lkup_one(&a->dst_dentry->d_name, ++ a->dst_h_parent); ++ rerr = PTR_ERR(a->h_path.dentry); ++ if (IS_ERR(a->h_path.dentry)) { ++ RevertFailure("lkup one %pd", a->dst_dentry); ++ return; ++ } ++ if (d_is_positive(a->h_path.dentry)) { ++ d_drop(a->h_path.dentry); ++ dput(a->h_path.dentry); ++ return; ++ } ++ ++ delegated = NULL; ++ rerr = vfsub_rename(a->dst_h_dir, a->h_dst, a->dst_h_dir, &a->h_path, ++ &delegated, a->flags); ++ if (unlikely(rerr == -EWOULDBLOCK)) { ++ pr_warn("cannot retry for NFSv4 delegation" ++ " for an internal rename\n"); ++ iput(delegated); ++ } ++ d_drop(a->h_path.dentry); ++ dput(a->h_path.dentry); ++ if (!rerr) ++ au_set_h_dptr(a->dst_dentry, a->btgt, dget(a->h_dst)); ++ else ++ RevertFailure("rename %pd", a->h_dst); ++} ++ ++static void au_ren_rev_whsrc(int err, struct au_ren_args *a) ++{ ++ int rerr; ++ ++ a->h_path.dentry = a->src_wh_dentry; ++ rerr = au_wh_unlink_dentry(a->src_h_dir, &a->h_path, a->src_dentry); ++ au_set_dbwh(a->src_dentry, a->src_bwh); ++ if (rerr) ++ RevertFailure("unlink %pd", a->src_wh_dentry); ++} ++#undef RevertFailure ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * when we have to copyup the renaming entry, do it with the rename-target name ++ * in order to minimize the cost (the later actual rename is unnecessary). ++ * otherwise rename it on the target branch. ++ */ ++static int au_ren_or_cpup(struct au_ren_args *a) ++{ ++ int err; ++ struct dentry *d; ++ struct inode *delegated; ++ ++ d = a->src_dentry; ++ if (au_dbtop(d) == a->btgt) { ++ a->h_path.dentry = a->dst_h_dentry; ++ AuDebugOn(au_dbtop(d) != a->btgt); ++ delegated = NULL; ++ err = vfsub_rename(a->src_h_dir, au_h_dptr(d, a->btgt), ++ a->dst_h_dir, &a->h_path, &delegated, ++ a->flags); ++ if (unlikely(err == -EWOULDBLOCK)) { ++ pr_warn("cannot retry for NFSv4 delegation" ++ " for an internal rename\n"); ++ iput(delegated); ++ } ++ } else ++ BUG(); ++ ++ if (!err && a->h_dst) ++ /* it will be set to dinfo later */ ++ dget(a->h_dst); ++ ++ return err; ++} ++ ++/* cf. aufs_rmdir() */ ++static int au_ren_del_whtmp(struct au_ren_args *a) ++{ ++ int err; ++ struct inode *dir; ++ ++ dir = a->dst_dir; ++ SiMustAnyLock(dir->i_sb); ++ if (!au_nhash_test_longer_wh(&a->whlist, a->btgt, ++ au_sbi(dir->i_sb)->si_dirwh) ++ || au_test_fs_remote(a->h_dst->d_sb)) { ++ err = au_whtmp_rmdir(dir, a->btgt, a->h_dst, &a->whlist); ++ if (unlikely(err)) ++ pr_warn("failed removing whtmp dir %pd (%d), " ++ "ignored.\n", a->h_dst, err); ++ } else { ++ au_nhash_wh_free(&a->thargs->whlist); ++ a->thargs->whlist = a->whlist; ++ a->whlist.nh_num = 0; ++ au_whtmp_kick_rmdir(dir, a->btgt, a->h_dst, a->thargs); ++ dput(a->h_dst); ++ a->thargs = NULL; ++ } ++ ++ return 0; ++} ++ ++/* make it 'opaque' dir. */ ++static int au_ren_do_diropq(struct au_ren_args *a, int idx) ++{ ++ int err; ++ struct dentry *d, *diropq; ++#define src_or_dst(member) a->sd[idx].member ++ ++ err = 0; ++ d = src_or_dst(dentry); /* {src,dst}_dentry */ ++ src_or_dst(bdiropq) = au_dbdiropq(d); ++ src_or_dst(hinode) = au_hi(src_or_dst(inode), a->btgt); ++ au_hn_inode_lock_nested(src_or_dst(hinode), AuLsc_I_CHILD); ++ diropq = au_diropq_create(d, a->btgt); ++ au_hn_inode_unlock(src_or_dst(hinode)); ++ if (IS_ERR(diropq)) ++ err = PTR_ERR(diropq); ++ else ++ dput(diropq); ++ ++#undef src_or_dst_ ++ return err; ++} ++ ++static int au_ren_diropq(struct au_ren_args *a) ++{ ++ int err; ++ unsigned char always; ++ struct dentry *d; ++ ++ err = 0; ++ d = a->dst_dentry; /* already renamed on the branch */ ++ always = !!au_opt_test(au_mntflags(d->d_sb), ALWAYS_DIROPQ); ++ if (au_ftest_ren(a->auren_flags, ISDIR_SRC) ++ && !au_ftest_ren(a->auren_flags, DIRREN) ++ && a->btgt != au_dbdiropq(a->src_dentry) ++ && (a->dst_wh_dentry ++ || a->btgt <= au_dbdiropq(d) ++ /* hide the lower to keep xino */ ++ /* the lowers may not be a dir, but we hide them anyway */ ++ || a->btgt < au_dbbot(d) ++ || always)) { ++ AuDbg("here\n"); ++ err = au_ren_do_diropq(a, AuSRC); ++ if (unlikely(err)) ++ goto out; ++ au_fset_ren(a->auren_flags, DIROPQ_SRC); ++ } ++ if (!a->exchange) ++ goto out; /* success */ ++ ++ d = a->src_dentry; /* already renamed on the branch */ ++ if (au_ftest_ren(a->auren_flags, ISDIR_DST) ++ && a->btgt != au_dbdiropq(a->dst_dentry) ++ && (a->btgt < au_dbdiropq(d) ++ || a->btgt < au_dbbot(d) ++ || always)) { ++ AuDbgDentry(a->src_dentry); ++ AuDbgDentry(a->dst_dentry); ++ err = au_ren_do_diropq(a, AuDST); ++ if (unlikely(err)) ++ goto out_rev_src; ++ au_fset_ren(a->auren_flags, DIROPQ_DST); ++ } ++ goto out; /* success */ ++ ++out_rev_src: ++ AuDbg("err %d, reverting src\n", err); ++ au_ren_rev_diropq(err, a); ++out: ++ return err; ++} ++ ++static int do_rename(struct au_ren_args *a) ++{ ++ int err; ++ struct dentry *d, *h_d; ++ ++ if (!a->exchange) { ++ /* prepare workqueue args for asynchronous rmdir */ ++ h_d = a->dst_h_dentry; ++ if (au_ftest_ren(a->auren_flags, ISDIR_DST) ++ /* && !au_ftest_ren(a->auren_flags, DIRREN) */ ++ && d_is_positive(h_d)) { ++ err = -ENOMEM; ++ a->thargs = au_whtmp_rmdir_alloc(a->src_dentry->d_sb, ++ GFP_NOFS); ++ if (unlikely(!a->thargs)) ++ goto out; ++ a->h_dst = dget(h_d); ++ } ++ ++ /* create whiteout for src_dentry */ ++ if (au_ftest_ren(a->auren_flags, WHSRC)) { ++ a->src_bwh = au_dbwh(a->src_dentry); ++ AuDebugOn(a->src_bwh >= 0); ++ a->src_wh_dentry = au_wh_create(a->src_dentry, a->btgt, ++ a->src_h_parent); ++ err = PTR_ERR(a->src_wh_dentry); ++ if (IS_ERR(a->src_wh_dentry)) ++ goto out_thargs; ++ } ++ ++ /* lookup whiteout for dentry */ ++ if (au_ftest_ren(a->auren_flags, WHDST)) { ++ h_d = au_wh_lkup(a->dst_h_parent, ++ &a->dst_dentry->d_name, a->br); ++ err = PTR_ERR(h_d); ++ if (IS_ERR(h_d)) ++ goto out_whsrc; ++ if (d_is_negative(h_d)) ++ dput(h_d); ++ else ++ a->dst_wh_dentry = h_d; ++ } ++ ++ /* rename dentry to tmpwh */ ++ if (a->thargs) { ++ err = au_whtmp_ren(a->dst_h_dentry, a->br); ++ if (unlikely(err)) ++ goto out_whdst; ++ ++ d = a->dst_dentry; ++ au_set_h_dptr(d, a->btgt, NULL); ++ err = au_lkup_neg(d, a->btgt, /*wh*/0); ++ if (unlikely(err)) ++ goto out_whtmp; ++ a->dst_h_dentry = au_h_dptr(d, a->btgt); ++ } ++ } ++ ++ BUG_ON(d_is_positive(a->dst_h_dentry) && a->src_btop != a->btgt); ++#if 0 ++ BUG_ON(!au_ftest_ren(a->auren_flags, DIRREN) ++ && d_is_positive(a->dst_h_dentry) ++ && a->src_btop != a->btgt); ++#endif ++ ++ /* rename by vfs_rename or cpup */ ++ err = au_ren_or_cpup(a); ++ if (unlikely(err)) ++ /* leave the copied-up one */ ++ goto out_whtmp; ++ ++ /* make dir opaque */ ++ err = au_ren_diropq(a); ++ if (unlikely(err)) ++ goto out_rename; ++ ++ /* update target timestamps */ ++ if (a->exchange) { ++ AuDebugOn(au_dbtop(a->dst_dentry) != a->btgt); ++ a->h_path.dentry = au_h_dptr(a->dst_dentry, a->btgt); ++ vfsub_update_h_iattr(&a->h_path, /*did*/NULL); /*ignore*/ ++ a->dst_inode->i_ctime = d_inode(a->h_path.dentry)->i_ctime; ++ } ++ AuDebugOn(au_dbtop(a->src_dentry) != a->btgt); ++ a->h_path.dentry = au_h_dptr(a->src_dentry, a->btgt); ++ vfsub_update_h_iattr(&a->h_path, /*did*/NULL); /*ignore*/ ++ a->src_inode->i_ctime = d_inode(a->h_path.dentry)->i_ctime; ++ ++ if (!a->exchange) { ++ /* remove whiteout for dentry */ ++ if (a->dst_wh_dentry) { ++ a->h_path.dentry = a->dst_wh_dentry; ++ err = au_wh_unlink_dentry(a->dst_h_dir, &a->h_path, ++ a->dst_dentry); ++ if (unlikely(err)) ++ goto out_diropq; ++ } ++ ++ /* remove whtmp */ ++ if (a->thargs) ++ au_ren_del_whtmp(a); /* ignore this error */ ++ ++ au_fhsm_wrote(a->src_dentry->d_sb, a->btgt, /*force*/0); ++ } ++ err = 0; ++ goto out_success; ++ ++out_diropq: ++ au_ren_rev_diropq(err, a); ++out_rename: ++ au_ren_rev_rename(err, a); ++ dput(a->h_dst); ++out_whtmp: ++ if (a->thargs) ++ au_ren_rev_whtmp(err, a); ++out_whdst: ++ dput(a->dst_wh_dentry); ++ a->dst_wh_dentry = NULL; ++out_whsrc: ++ if (a->src_wh_dentry) ++ au_ren_rev_whsrc(err, a); ++out_success: ++ dput(a->src_wh_dentry); ++ dput(a->dst_wh_dentry); ++out_thargs: ++ if (a->thargs) { ++ dput(a->h_dst); ++ au_whtmp_rmdir_free(a->thargs); ++ a->thargs = NULL; ++ } ++out: ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * test if @dentry dir can be rename destination or not. ++ * success means, it is a logically empty dir. ++ */ ++static int may_rename_dstdir(struct dentry *dentry, struct au_nhash *whlist) ++{ ++ return au_test_empty(dentry, whlist); ++} ++ ++/* ++ * test if @a->src_dentry dir can be rename source or not. ++ * if it can, return 0. ++ * success means, ++ * - it is a logically empty dir. ++ * - or, it exists on writable branch and has no children including whiteouts ++ * on the lower branch unless DIRREN is on. ++ */ ++static int may_rename_srcdir(struct au_ren_args *a) ++{ ++ int err; ++ unsigned int rdhash; ++ aufs_bindex_t btop, btgt; ++ struct dentry *dentry; ++ struct super_block *sb; ++ struct au_sbinfo *sbinfo; ++ ++ dentry = a->src_dentry; ++ sb = dentry->d_sb; ++ sbinfo = au_sbi(sb); ++ if (au_opt_test(sbinfo->si_mntflags, DIRREN)) ++ au_fset_ren(a->auren_flags, DIRREN); ++ ++ btgt = a->btgt; ++ btop = au_dbtop(dentry); ++ if (btop != btgt) { ++ struct au_nhash whlist; ++ ++ SiMustAnyLock(sb); ++ rdhash = sbinfo->si_rdhash; ++ if (!rdhash) ++ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, ++ dentry)); ++ err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS); ++ if (unlikely(err)) ++ goto out; ++ err = au_test_empty(dentry, &whlist); ++ au_nhash_wh_free(&whlist); ++ goto out; ++ } ++ ++ if (btop == au_dbtaildir(dentry)) ++ return 0; /* success */ ++ ++ err = au_test_empty_lower(dentry); ++ ++out: ++ if (err == -ENOTEMPTY) { ++ if (au_ftest_ren(a->auren_flags, DIRREN)) { ++ err = 0; ++ } else { ++ AuWarn1("renaming dir who has child(ren) on multiple " ++ "branches, is not supported\n"); ++ err = -EXDEV; ++ } ++ } ++ return err; ++} ++ ++/* side effect: sets whlist and h_dentry */ ++static int au_ren_may_dir(struct au_ren_args *a) ++{ ++ int err; ++ unsigned int rdhash; ++ struct dentry *d; ++ ++ d = a->dst_dentry; ++ SiMustAnyLock(d->d_sb); ++ ++ err = 0; ++ if (au_ftest_ren(a->auren_flags, ISDIR_DST) && a->dst_inode) { ++ rdhash = au_sbi(d->d_sb)->si_rdhash; ++ if (!rdhash) ++ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, d)); ++ err = au_nhash_alloc(&a->whlist, rdhash, GFP_NOFS); ++ if (unlikely(err)) ++ goto out; ++ ++ if (!a->exchange) { ++ au_set_dbtop(d, a->dst_btop); ++ err = may_rename_dstdir(d, &a->whlist); ++ au_set_dbtop(d, a->btgt); ++ } else ++ err = may_rename_srcdir(a); ++ } ++ a->dst_h_dentry = au_h_dptr(d, au_dbtop(d)); ++ if (unlikely(err)) ++ goto out; ++ ++ d = a->src_dentry; ++ a->src_h_dentry = au_h_dptr(d, au_dbtop(d)); ++ if (au_ftest_ren(a->auren_flags, ISDIR_SRC)) { ++ err = may_rename_srcdir(a); ++ if (unlikely(err)) { ++ au_nhash_wh_free(&a->whlist); ++ a->whlist.nh_num = 0; ++ } ++ } ++out: ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * simple tests for rename. ++ * following the checks in vfs, plus the parent-child relationship. ++ */ ++static int au_may_ren(struct au_ren_args *a) ++{ ++ int err, isdir; ++ struct inode *h_inode; ++ ++ if (a->src_btop == a->btgt) { ++ err = au_may_del(a->src_dentry, a->btgt, a->src_h_parent, ++ au_ftest_ren(a->auren_flags, ISDIR_SRC)); ++ if (unlikely(err)) ++ goto out; ++ err = -EINVAL; ++ if (unlikely(a->src_h_dentry == a->h_trap)) ++ goto out; ++ } ++ ++ err = 0; ++ if (a->dst_btop != a->btgt) ++ goto out; ++ ++ err = -ENOTEMPTY; ++ if (unlikely(a->dst_h_dentry == a->h_trap)) ++ goto out; ++ ++ err = -EIO; ++ isdir = !!au_ftest_ren(a->auren_flags, ISDIR_DST); ++ if (d_really_is_negative(a->dst_dentry)) { ++ if (d_is_negative(a->dst_h_dentry)) ++ err = au_may_add(a->dst_dentry, a->btgt, ++ a->dst_h_parent, isdir); ++ } else { ++ if (unlikely(d_is_negative(a->dst_h_dentry))) ++ goto out; ++ h_inode = d_inode(a->dst_h_dentry); ++ if (h_inode->i_nlink) ++ err = au_may_del(a->dst_dentry, a->btgt, ++ a->dst_h_parent, isdir); ++ } ++ ++out: ++ if (unlikely(err == -ENOENT || err == -EEXIST)) ++ err = -EIO; ++ AuTraceErr(err); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * locking order ++ * (VFS) ++ * - src_dir and dir by lock_rename() ++ * - inode if exists ++ * (aufs) ++ * - lock all ++ * + src_dentry and dentry by aufs_read_and_write_lock2() which calls, ++ * + si_read_lock ++ * + di_write_lock2_child() ++ * + di_write_lock_child() ++ * + ii_write_lock_child() ++ * + di_write_lock_child2() ++ * + ii_write_lock_child2() ++ * + src_parent and parent ++ * + di_write_lock_parent() ++ * + ii_write_lock_parent() ++ * + di_write_lock_parent2() ++ * + ii_write_lock_parent2() ++ * + lower src_dir and dir by vfsub_lock_rename() ++ * + verify the every relationships between child and parent. if any ++ * of them failed, unlock all and return -EBUSY. ++ */ ++static void au_ren_unlock(struct au_ren_args *a) ++{ ++ vfsub_unlock_rename(a->src_h_parent, a->src_hdir, ++ a->dst_h_parent, a->dst_hdir); ++ if (au_ftest_ren(a->auren_flags, DIRREN) ++ && a->h_root) ++ au_hn_inode_unlock(a->h_root); ++ if (au_ftest_ren(a->auren_flags, MNT_WRITE)) ++ vfsub_mnt_drop_write(au_br_mnt(a->br)); ++} ++ ++static int au_ren_lock(struct au_ren_args *a) ++{ ++ int err; ++ unsigned int udba; ++ ++ err = 0; ++ a->src_h_parent = au_h_dptr(a->src_parent, a->btgt); ++ a->src_hdir = au_hi(a->src_dir, a->btgt); ++ a->dst_h_parent = au_h_dptr(a->dst_parent, a->btgt); ++ a->dst_hdir = au_hi(a->dst_dir, a->btgt); ++ ++ err = vfsub_mnt_want_write(au_br_mnt(a->br)); ++ if (unlikely(err)) ++ goto out; ++ au_fset_ren(a->auren_flags, MNT_WRITE); ++ if (au_ftest_ren(a->auren_flags, DIRREN)) { ++ struct dentry *root; ++ struct inode *dir; ++ ++ /* ++ * sbinfo is already locked, so this ii_read_lock is ++ * unnecessary. but our debugging feature checks it. ++ */ ++ root = a->src_inode->i_sb->s_root; ++ if (root != a->src_parent && root != a->dst_parent) { ++ dir = d_inode(root); ++ ii_read_lock_parent3(dir); ++ a->h_root = au_hi(dir, a->btgt); ++ ii_read_unlock(dir); ++ au_hn_inode_lock_nested(a->h_root, AuLsc_I_PARENT3); ++ } ++ } ++ a->h_trap = vfsub_lock_rename(a->src_h_parent, a->src_hdir, ++ a->dst_h_parent, a->dst_hdir); ++ udba = au_opt_udba(a->src_dentry->d_sb); ++ if (unlikely(a->src_hdir->hi_inode != d_inode(a->src_h_parent) ++ || a->dst_hdir->hi_inode != d_inode(a->dst_h_parent))) ++ err = au_busy_or_stale(); ++ if (!err && au_dbtop(a->src_dentry) == a->btgt) ++ err = au_h_verify(a->src_h_dentry, udba, ++ d_inode(a->src_h_parent), a->src_h_parent, ++ a->br); ++ if (!err && au_dbtop(a->dst_dentry) == a->btgt) ++ err = au_h_verify(a->dst_h_dentry, udba, ++ d_inode(a->dst_h_parent), a->dst_h_parent, ++ a->br); ++ if (!err) ++ goto out; /* success */ ++ ++ err = au_busy_or_stale(); ++ au_ren_unlock(a); ++ ++out: ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static void au_ren_refresh_dir(struct au_ren_args *a) ++{ ++ struct inode *dir; ++ ++ dir = a->dst_dir; ++ inode_inc_iversion(dir); ++ if (au_ftest_ren(a->auren_flags, ISDIR_SRC)) { ++ /* is this updating defined in POSIX? */ ++ au_cpup_attr_timesizes(a->src_inode); ++ au_cpup_attr_nlink(dir, /*force*/1); ++ } ++ au_dir_ts(dir, a->btgt); ++ ++ if (a->exchange) { ++ dir = a->src_dir; ++ inode_inc_iversion(dir); ++ if (au_ftest_ren(a->auren_flags, ISDIR_DST)) { ++ /* is this updating defined in POSIX? */ ++ au_cpup_attr_timesizes(a->dst_inode); ++ au_cpup_attr_nlink(dir, /*force*/1); ++ } ++ au_dir_ts(dir, a->btgt); ++ } ++ ++ if (au_ftest_ren(a->auren_flags, ISSAMEDIR)) ++ return; ++ ++ dir = a->src_dir; ++ inode_inc_iversion(dir); ++ if (au_ftest_ren(a->auren_flags, ISDIR_SRC)) ++ au_cpup_attr_nlink(dir, /*force*/1); ++ au_dir_ts(dir, a->btgt); ++} ++ ++static void au_ren_refresh(struct au_ren_args *a) ++{ ++ aufs_bindex_t bbot, bindex; ++ struct dentry *d, *h_d; ++ struct inode *i, *h_i; ++ struct super_block *sb; ++ ++ d = a->dst_dentry; ++ d_drop(d); ++ if (a->h_dst) ++ /* already dget-ed by au_ren_or_cpup() */ ++ au_set_h_dptr(d, a->btgt, a->h_dst); ++ ++ i = a->dst_inode; ++ if (i) { ++ if (!a->exchange) { ++ if (!au_ftest_ren(a->auren_flags, ISDIR_DST)) ++ vfsub_drop_nlink(i); ++ else { ++ vfsub_dead_dir(i); ++ au_cpup_attr_timesizes(i); ++ } ++ au_update_dbrange(d, /*do_put_zero*/1); ++ } else ++ au_cpup_attr_nlink(i, /*force*/1); ++ } else { ++ bbot = a->btgt; ++ for (bindex = au_dbtop(d); bindex < bbot; bindex++) ++ au_set_h_dptr(d, bindex, NULL); ++ bbot = au_dbbot(d); ++ for (bindex = a->btgt + 1; bindex <= bbot; bindex++) ++ au_set_h_dptr(d, bindex, NULL); ++ au_update_dbrange(d, /*do_put_zero*/0); ++ } ++ ++ if (a->exchange ++ || au_ftest_ren(a->auren_flags, DIRREN)) { ++ d_drop(a->src_dentry); ++ if (au_ftest_ren(a->auren_flags, DIRREN)) ++ au_set_dbwh(a->src_dentry, -1); ++ return; ++ } ++ ++ d = a->src_dentry; ++ au_set_dbwh(d, -1); ++ bbot = au_dbbot(d); ++ for (bindex = a->btgt + 1; bindex <= bbot; bindex++) { ++ h_d = au_h_dptr(d, bindex); ++ if (h_d) ++ au_set_h_dptr(d, bindex, NULL); ++ } ++ au_set_dbbot(d, a->btgt); ++ ++ sb = d->d_sb; ++ i = a->src_inode; ++ if (au_opt_test(au_mntflags(sb), PLINK) && au_plink_test(i)) ++ return; /* success */ ++ ++ bbot = au_ibbot(i); ++ for (bindex = a->btgt + 1; bindex <= bbot; bindex++) { ++ h_i = au_h_iptr(i, bindex); ++ if (h_i) { ++ au_xino_write(sb, bindex, h_i->i_ino, /*ino*/0); ++ /* ignore this error */ ++ au_set_h_iptr(i, bindex, NULL, 0); ++ } ++ } ++ au_set_ibbot(i, a->btgt); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* mainly for link(2) and rename(2) */ ++int au_wbr(struct dentry *dentry, aufs_bindex_t btgt) ++{ ++ aufs_bindex_t bdiropq, bwh; ++ struct dentry *parent; ++ struct au_branch *br; ++ ++ parent = dentry->d_parent; ++ IMustLock(d_inode(parent)); /* dir is locked */ ++ ++ bdiropq = au_dbdiropq(parent); ++ bwh = au_dbwh(dentry); ++ br = au_sbr(dentry->d_sb, btgt); ++ if (au_br_rdonly(br) ++ || (0 <= bdiropq && bdiropq < btgt) ++ || (0 <= bwh && bwh < btgt)) ++ btgt = -1; ++ ++ AuDbg("btgt %d\n", btgt); ++ return btgt; ++} ++ ++/* sets src_btop, dst_btop and btgt */ ++static int au_ren_wbr(struct au_ren_args *a) ++{ ++ int err; ++ struct au_wr_dir_args wr_dir_args = { ++ /* .force_btgt = -1, */ ++ .flags = AuWrDir_ADD_ENTRY ++ }; ++ ++ a->src_btop = au_dbtop(a->src_dentry); ++ a->dst_btop = au_dbtop(a->dst_dentry); ++ if (au_ftest_ren(a->auren_flags, ISDIR_SRC) ++ || au_ftest_ren(a->auren_flags, ISDIR_DST)) ++ au_fset_wrdir(wr_dir_args.flags, ISDIR); ++ wr_dir_args.force_btgt = a->src_btop; ++ if (a->dst_inode && a->dst_btop < a->src_btop) ++ wr_dir_args.force_btgt = a->dst_btop; ++ wr_dir_args.force_btgt = au_wbr(a->dst_dentry, wr_dir_args.force_btgt); ++ err = au_wr_dir(a->dst_dentry, a->src_dentry, &wr_dir_args); ++ a->btgt = err; ++ if (a->exchange) ++ au_update_dbtop(a->dst_dentry); ++ ++ return err; ++} ++ ++static void au_ren_dt(struct au_ren_args *a) ++{ ++ a->h_path.dentry = a->src_h_parent; ++ au_dtime_store(a->src_dt + AuPARENT, a->src_parent, &a->h_path); ++ if (!au_ftest_ren(a->auren_flags, ISSAMEDIR)) { ++ a->h_path.dentry = a->dst_h_parent; ++ au_dtime_store(a->dst_dt + AuPARENT, a->dst_parent, &a->h_path); ++ } ++ ++ au_fclr_ren(a->auren_flags, DT_DSTDIR); ++ if (!au_ftest_ren(a->auren_flags, ISDIR_SRC) ++ && !a->exchange) ++ return; ++ ++ a->h_path.dentry = a->src_h_dentry; ++ au_dtime_store(a->src_dt + AuCHILD, a->src_dentry, &a->h_path); ++ if (d_is_positive(a->dst_h_dentry)) { ++ au_fset_ren(a->auren_flags, DT_DSTDIR); ++ a->h_path.dentry = a->dst_h_dentry; ++ au_dtime_store(a->dst_dt + AuCHILD, a->dst_dentry, &a->h_path); ++ } ++} ++ ++static void au_ren_rev_dt(int err, struct au_ren_args *a) ++{ ++ struct dentry *h_d; ++ struct inode *h_inode; ++ ++ au_dtime_revert(a->src_dt + AuPARENT); ++ if (!au_ftest_ren(a->auren_flags, ISSAMEDIR)) ++ au_dtime_revert(a->dst_dt + AuPARENT); ++ ++ if (au_ftest_ren(a->auren_flags, ISDIR_SRC) && err != -EIO) { ++ h_d = a->src_dt[AuCHILD].dt_h_path.dentry; ++ h_inode = d_inode(h_d); ++ inode_lock_nested(h_inode, AuLsc_I_CHILD); ++ au_dtime_revert(a->src_dt + AuCHILD); ++ inode_unlock(h_inode); ++ ++ if (au_ftest_ren(a->auren_flags, DT_DSTDIR)) { ++ h_d = a->dst_dt[AuCHILD].dt_h_path.dentry; ++ h_inode = d_inode(h_d); ++ inode_lock_nested(h_inode, AuLsc_I_CHILD); ++ au_dtime_revert(a->dst_dt + AuCHILD); ++ inode_unlock(h_inode); ++ } ++ } ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++int aufs_rename(struct inode *_src_dir, struct dentry *_src_dentry, ++ struct inode *_dst_dir, struct dentry *_dst_dentry, ++ unsigned int _flags) ++{ ++ int err, lock_flags; ++ void *rev; ++ /* reduce stack space */ ++ struct au_ren_args *a; ++ struct au_pin pin; ++ ++ AuDbg("%pd, %pd, 0x%x\n", _src_dentry, _dst_dentry, _flags); ++ IMustLock(_src_dir); ++ IMustLock(_dst_dir); ++ ++ err = -EINVAL; ++ if (unlikely(_flags & RENAME_WHITEOUT)) ++ goto out; ++ ++ err = -ENOMEM; ++ BUILD_BUG_ON(sizeof(*a) > PAGE_SIZE); ++ a = kzalloc(sizeof(*a), GFP_NOFS); ++ if (unlikely(!a)) ++ goto out; ++ ++ a->flags = _flags; ++ BUILD_BUG_ON(sizeof(a->exchange) == sizeof(u8) ++ && RENAME_EXCHANGE > U8_MAX); ++ a->exchange = _flags & RENAME_EXCHANGE; ++ a->src_dir = _src_dir; ++ a->src_dentry = _src_dentry; ++ a->src_inode = NULL; ++ if (d_really_is_positive(a->src_dentry)) ++ a->src_inode = d_inode(a->src_dentry); ++ a->src_parent = a->src_dentry->d_parent; /* dir inode is locked */ ++ a->dst_dir = _dst_dir; ++ a->dst_dentry = _dst_dentry; ++ a->dst_inode = NULL; ++ if (d_really_is_positive(a->dst_dentry)) ++ a->dst_inode = d_inode(a->dst_dentry); ++ a->dst_parent = a->dst_dentry->d_parent; /* dir inode is locked */ ++ if (a->dst_inode) { ++ /* ++ * if EXCHANGE && src is non-dir && dst is dir, ++ * dst is not locked. ++ */ ++ /* IMustLock(a->dst_inode); */ ++ au_igrab(a->dst_inode); ++ } ++ ++ err = -ENOTDIR; ++ lock_flags = AuLock_FLUSH | AuLock_NOPLM | AuLock_GEN; ++ if (d_is_dir(a->src_dentry)) { ++ au_fset_ren(a->auren_flags, ISDIR_SRC); ++ if (unlikely(!a->exchange ++ && d_really_is_positive(a->dst_dentry) ++ && !d_is_dir(a->dst_dentry))) ++ goto out_free; ++ lock_flags |= AuLock_DIRS; ++ } ++ if (a->dst_inode && d_is_dir(a->dst_dentry)) { ++ au_fset_ren(a->auren_flags, ISDIR_DST); ++ if (unlikely(!a->exchange ++ && d_really_is_positive(a->src_dentry) ++ && !d_is_dir(a->src_dentry))) ++ goto out_free; ++ lock_flags |= AuLock_DIRS; ++ } ++ err = aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry, ++ lock_flags); ++ if (unlikely(err)) ++ goto out_free; ++ ++ err = au_d_hashed_positive(a->src_dentry); ++ if (unlikely(err)) ++ goto out_unlock; ++ err = -ENOENT; ++ if (a->dst_inode) { ++ /* ++ * If it is a dir, VFS unhash it before this ++ * function. It means we cannot rely upon d_unhashed(). ++ */ ++ if (unlikely(!a->dst_inode->i_nlink)) ++ goto out_unlock; ++ if (!au_ftest_ren(a->auren_flags, ISDIR_DST)) { ++ err = au_d_hashed_positive(a->dst_dentry); ++ if (unlikely(err && !a->exchange)) ++ goto out_unlock; ++ } else if (unlikely(IS_DEADDIR(a->dst_inode))) ++ goto out_unlock; ++ } else if (unlikely(d_unhashed(a->dst_dentry))) ++ goto out_unlock; ++ ++ /* ++ * is it possible? ++ * yes, it happened (in linux-3.3-rcN) but I don't know why. ++ * there may exist a problem somewhere else. ++ */ ++ err = -EINVAL; ++ if (unlikely(d_inode(a->dst_parent) == d_inode(a->src_dentry))) ++ goto out_unlock; ++ ++ au_fset_ren(a->auren_flags, ISSAMEDIR); /* temporary */ ++ di_write_lock_parent(a->dst_parent); ++ ++ /* which branch we process */ ++ err = au_ren_wbr(a); ++ if (unlikely(err < 0)) ++ goto out_parent; ++ a->br = au_sbr(a->dst_dentry->d_sb, a->btgt); ++ a->h_path.mnt = au_br_mnt(a->br); ++ ++ /* are they available to be renamed */ ++ err = au_ren_may_dir(a); ++ if (unlikely(err)) ++ goto out_children; ++ ++ /* prepare the writable parent dir on the same branch */ ++ if (a->dst_btop == a->btgt) { ++ au_fset_ren(a->auren_flags, WHDST); ++ } else { ++ err = au_cpup_dirs(a->dst_dentry, a->btgt); ++ if (unlikely(err)) ++ goto out_children; ++ } ++ ++ err = 0; ++ if (!a->exchange) { ++ if (a->src_dir != a->dst_dir) { ++ /* ++ * this temporary unlock is safe, ++ * because both dir->i_mutex are locked. ++ */ ++ di_write_unlock(a->dst_parent); ++ di_write_lock_parent(a->src_parent); ++ err = au_wr_dir_need_wh(a->src_dentry, ++ au_ftest_ren(a->auren_flags, ++ ISDIR_SRC), ++ &a->btgt); ++ di_write_unlock(a->src_parent); ++ di_write_lock2_parent(a->src_parent, a->dst_parent, ++ /*isdir*/1); ++ au_fclr_ren(a->auren_flags, ISSAMEDIR); ++ } else ++ err = au_wr_dir_need_wh(a->src_dentry, ++ au_ftest_ren(a->auren_flags, ++ ISDIR_SRC), ++ &a->btgt); ++ } ++ if (unlikely(err < 0)) ++ goto out_children; ++ if (err) ++ au_fset_ren(a->auren_flags, WHSRC); ++ ++ /* cpup src */ ++ if (a->src_btop != a->btgt) { ++ err = au_pin(&pin, a->src_dentry, a->btgt, ++ au_opt_udba(a->src_dentry->d_sb), ++ AuPin_DI_LOCKED | AuPin_MNT_WRITE); ++ if (!err) { ++ struct au_cp_generic cpg = { ++ .dentry = a->src_dentry, ++ .bdst = a->btgt, ++ .bsrc = a->src_btop, ++ .len = -1, ++ .pin = &pin, ++ .flags = AuCpup_DTIME | AuCpup_HOPEN ++ }; ++ AuDebugOn(au_dbtop(a->src_dentry) != a->src_btop); ++ err = au_sio_cpup_simple(&cpg); ++ au_unpin(&pin); ++ } ++ if (unlikely(err)) ++ goto out_children; ++ a->src_btop = a->btgt; ++ a->src_h_dentry = au_h_dptr(a->src_dentry, a->btgt); ++ if (!a->exchange) ++ au_fset_ren(a->auren_flags, WHSRC); ++ } ++ ++ /* cpup dst */ ++ if (a->exchange && a->dst_inode ++ && a->dst_btop != a->btgt) { ++ err = au_pin(&pin, a->dst_dentry, a->btgt, ++ au_opt_udba(a->dst_dentry->d_sb), ++ AuPin_DI_LOCKED | AuPin_MNT_WRITE); ++ if (!err) { ++ struct au_cp_generic cpg = { ++ .dentry = a->dst_dentry, ++ .bdst = a->btgt, ++ .bsrc = a->dst_btop, ++ .len = -1, ++ .pin = &pin, ++ .flags = AuCpup_DTIME | AuCpup_HOPEN ++ }; ++ err = au_sio_cpup_simple(&cpg); ++ au_unpin(&pin); ++ } ++ if (unlikely(err)) ++ goto out_children; ++ a->dst_btop = a->btgt; ++ a->dst_h_dentry = au_h_dptr(a->dst_dentry, a->btgt); ++ } ++ ++ /* lock them all */ ++ err = au_ren_lock(a); ++ if (unlikely(err)) ++ /* leave the copied-up one */ ++ goto out_children; ++ ++ if (!a->exchange) { ++ if (!au_opt_test(au_mntflags(a->dst_dir->i_sb), UDBA_NONE)) ++ err = au_may_ren(a); ++ else if (unlikely(a->dst_dentry->d_name.len > AUFS_MAX_NAMELEN)) ++ err = -ENAMETOOLONG; ++ if (unlikely(err)) ++ goto out_hdir; ++ } ++ ++ /* store timestamps to be revertible */ ++ au_ren_dt(a); ++ ++ /* store dirren info */ ++ if (au_ftest_ren(a->auren_flags, DIRREN)) { ++ err = au_dr_rename(a->src_dentry, a->btgt, ++ &a->dst_dentry->d_name, &rev); ++ AuTraceErr(err); ++ if (unlikely(err)) ++ goto out_dt; ++ } ++ ++ /* here we go */ ++ err = do_rename(a); ++ if (unlikely(err)) ++ goto out_dirren; ++ ++ if (au_ftest_ren(a->auren_flags, DIRREN)) ++ au_dr_rename_fin(a->src_dentry, a->btgt, rev); ++ ++ /* update dir attributes */ ++ au_ren_refresh_dir(a); ++ ++ /* dput/iput all lower dentries */ ++ au_ren_refresh(a); ++ ++ goto out_hdir; /* success */ ++ ++out_dirren: ++ if (au_ftest_ren(a->auren_flags, DIRREN)) ++ au_dr_rename_rev(a->src_dentry, a->btgt, rev); ++out_dt: ++ au_ren_rev_dt(err, a); ++out_hdir: ++ au_ren_unlock(a); ++out_children: ++ au_nhash_wh_free(&a->whlist); ++ if (err && a->dst_inode && a->dst_btop != a->btgt) { ++ AuDbg("btop %d, btgt %d\n", a->dst_btop, a->btgt); ++ au_set_h_dptr(a->dst_dentry, a->btgt, NULL); ++ au_set_dbtop(a->dst_dentry, a->dst_btop); ++ } ++out_parent: ++ if (!err) { ++ if (d_unhashed(a->src_dentry)) ++ au_fset_ren(a->auren_flags, DROPPED_SRC); ++ if (d_unhashed(a->dst_dentry)) ++ au_fset_ren(a->auren_flags, DROPPED_DST); ++ if (!a->exchange) ++ d_move(a->src_dentry, a->dst_dentry); ++ else { ++ d_exchange(a->src_dentry, a->dst_dentry); ++ if (au_ftest_ren(a->auren_flags, DROPPED_DST)) ++ d_drop(a->dst_dentry); ++ } ++ if (au_ftest_ren(a->auren_flags, DROPPED_SRC)) ++ d_drop(a->src_dentry); ++ } else { ++ au_update_dbtop(a->dst_dentry); ++ if (!a->dst_inode) ++ d_drop(a->dst_dentry); ++ } ++ if (au_ftest_ren(a->auren_flags, ISSAMEDIR)) ++ di_write_unlock(a->dst_parent); ++ else ++ di_write_unlock2(a->src_parent, a->dst_parent); ++out_unlock: ++ aufs_read_and_write_unlock2(a->dst_dentry, a->src_dentry); ++out_free: ++ iput(a->dst_inode); ++ if (a->thargs) ++ au_whtmp_rmdir_free(a->thargs); ++ au_kfree_rcu(a); ++out: ++ AuTraceErr(err); ++ return err; ++} +diff -Nurp linux-5.4/fs/aufs/Kconfig linux-5.4-aufs/fs/aufs/Kconfig +--- linux-5.4/fs/aufs/Kconfig 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/Kconfig 2019-11-28 01:25:59.062925618 +0200 +@@ -0,0 +1,199 @@ ++# SPDX-License-Identifier: GPL-2.0 ++config AUFS_FS ++ bool "Aufs (Advanced multi layered unification filesystem) support" ++ help ++ Aufs is a stackable unification filesystem such as Unionfs, ++ which unifies several directories and provides a merged single ++ directory. ++ In the early days, aufs was entirely re-designed and ++ re-implemented Unionfs Version 1.x series. Introducing many ++ original ideas, approaches and improvements, it becomes totally ++ different from Unionfs while keeping the basic features. ++ ++if AUFS_FS ++choice ++ prompt "Maximum number of branches" ++ default AUFS_BRANCH_MAX_127 ++ help ++ Specifies the maximum number of branches (or member directories) ++ in a single aufs. The larger value consumes more system ++ resources and has a minor impact to performance. ++config AUFS_BRANCH_MAX_127 ++ bool "127" ++ help ++ Specifies the maximum number of branches (or member directories) ++ in a single aufs. The larger value consumes more system ++ resources and has a minor impact to performance. ++config AUFS_BRANCH_MAX_511 ++ bool "511" ++ help ++ Specifies the maximum number of branches (or member directories) ++ in a single aufs. The larger value consumes more system ++ resources and has a minor impact to performance. ++config AUFS_BRANCH_MAX_1023 ++ bool "1023" ++ help ++ Specifies the maximum number of branches (or member directories) ++ in a single aufs. The larger value consumes more system ++ resources and has a minor impact to performance. ++config AUFS_BRANCH_MAX_32767 ++ bool "32767" ++ help ++ Specifies the maximum number of branches (or member directories) ++ in a single aufs. The larger value consumes more system ++ resources and has a minor impact to performance. ++endchoice ++ ++config AUFS_SBILIST ++ bool ++ depends on AUFS_MAGIC_SYSRQ || PROC_FS ++ default y ++ help ++ Automatic configuration for internal use. ++ When aufs supports Magic SysRq or /proc, enabled automatically. ++ ++config AUFS_HNOTIFY ++ bool "Detect direct branch access (bypassing aufs)" ++ help ++ If you want to modify files on branches directly, eg. bypassing aufs, ++ and want aufs to detect the changes of them fully, then enable this ++ option and use 'udba=notify' mount option. ++ Currently there is only one available configuration, "fsnotify". ++ It will have a negative impact to the performance. ++ See detail in aufs.5. ++ ++choice ++ prompt "method" if AUFS_HNOTIFY ++ default AUFS_HFSNOTIFY ++config AUFS_HFSNOTIFY ++ bool "fsnotify" ++ select FSNOTIFY ++endchoice ++ ++config AUFS_EXPORT ++ bool "NFS-exportable aufs" ++ depends on EXPORTFS = y ++ help ++ If you want to export your mounted aufs via NFS, then enable this ++ option. There are several requirements for this configuration. ++ See detail in aufs.5. ++ ++config AUFS_INO_T_64 ++ bool ++ depends on AUFS_EXPORT ++ depends on 64BIT && !(ALPHA || S390) ++ default y ++ help ++ Automatic configuration for internal use. ++ /* typedef unsigned long/int __kernel_ino_t */ ++ /* alpha and s390x are int */ ++ ++config AUFS_XATTR ++ bool "support for XATTR/EA (including Security Labels)" ++ help ++ If your branch fs supports XATTR/EA and you want to make them ++ available in aufs too, then enable this opsion and specify the ++ branch attributes for EA. ++ See detail in aufs.5. ++ ++config AUFS_FHSM ++ bool "File-based Hierarchical Storage Management" ++ help ++ Hierarchical Storage Management (or HSM) is a well-known feature ++ in the storage world. Aufs provides this feature as file-based. ++ with multiple branches. ++ These multiple branches are prioritized, ie. the topmost one ++ should be the fastest drive and be used heavily. ++ ++config AUFS_RDU ++ bool "Readdir in userspace" ++ help ++ Aufs has two methods to provide a merged view for a directory, ++ by a user-space library and by kernel-space natively. The latter ++ is always enabled but sometimes large and slow. ++ If you enable this option, install the library in aufs2-util ++ package, and set some environment variables for your readdir(3), ++ then the work will be handled in user-space which generally ++ shows better performance in most cases. ++ See detail in aufs.5. ++ ++config AUFS_DIRREN ++ bool "Workaround for rename(2)-ing a directory" ++ help ++ By default, aufs returns EXDEV error in renameing a dir who has ++ his child on the lower branch, since it is a bad idea to issue ++ rename(2) internally for every lower branch. But user may not ++ accept this behaviour. So here is a workaround to allow such ++ rename(2) and store some extra infromation on the writable ++ branch. Obviously this costs high (and I don't like it). ++ To use this feature, you need to enable this configuration AND ++ to specify the mount option `dirren.' ++ See details in aufs.5 and the design documents. ++ ++config AUFS_SHWH ++ bool "Show whiteouts" ++ help ++ If you want to make the whiteouts in aufs visible, then enable ++ this option and specify 'shwh' mount option. Although it may ++ sounds like philosophy or something, but in technically it ++ simply shows the name of whiteout with keeping its behaviour. ++ ++config AUFS_BR_RAMFS ++ bool "Ramfs (initramfs/rootfs) as an aufs branch" ++ help ++ If you want to use ramfs as an aufs branch fs, then enable this ++ option. Generally tmpfs is recommended. ++ Aufs prohibited them to be a branch fs by default, because ++ initramfs becomes unusable after switch_root or something ++ generally. If you sets initramfs as an aufs branch and boot your ++ system by switch_root, you will meet a problem easily since the ++ files in initramfs may be inaccessible. ++ Unless you are going to use ramfs as an aufs branch fs without ++ switch_root or something, leave it N. ++ ++config AUFS_BR_FUSE ++ bool "Fuse fs as an aufs branch" ++ depends on FUSE_FS ++ select AUFS_POLL ++ help ++ If you want to use fuse-based userspace filesystem as an aufs ++ branch fs, then enable this option. ++ It implements the internal poll(2) operation which is ++ implemented by fuse only (curretnly). ++ ++config AUFS_POLL ++ bool ++ help ++ Automatic configuration for internal use. ++ ++config AUFS_BR_HFSPLUS ++ bool "Hfsplus as an aufs branch" ++ depends on HFSPLUS_FS ++ default y ++ help ++ If you want to use hfsplus fs as an aufs branch fs, then enable ++ this option. This option introduces a small overhead at ++ copying-up a file on hfsplus. ++ ++config AUFS_BDEV_LOOP ++ bool ++ depends on BLK_DEV_LOOP ++ default y ++ help ++ Automatic configuration for internal use. ++ Convert =[ym] into =y. ++ ++config AUFS_DEBUG ++ bool "Debug aufs" ++ help ++ Enable this to compile aufs internal debug code. ++ It will have a negative impact to the performance. ++ ++config AUFS_MAGIC_SYSRQ ++ bool ++ depends on AUFS_DEBUG && MAGIC_SYSRQ ++ default y ++ help ++ Automatic configuration for internal use. ++ When aufs supports Magic SysRq, enabled automatically. ++endif +diff -Nurp linux-5.4/fs/aufs/lcnt.h linux-5.4-aufs/fs/aufs/lcnt.h +--- linux-5.4/fs/aufs/lcnt.h 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/lcnt.h 2019-11-28 01:25:59.066925618 +0200 +@@ -0,0 +1,173 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2018-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * simple long counter wrapper ++ */ ++ ++#ifndef __AUFS_LCNT_H__ ++#define __AUFS_LCNT_H__ ++ ++#ifdef __KERNEL__ ++ ++#include "debug.h" ++ ++#define AuLCntATOMIC 1 ++#define AuLCntPCPUCNT 2 ++/* ++ * why does percpu_refcount require extra synchronize_rcu()s in ++ * au_br_do_free() ++ */ ++#define AuLCntPCPUREF 3 ++ ++/* #define AuLCntChosen AuLCntATOMIC */ ++#define AuLCntChosen AuLCntPCPUCNT ++/* #define AuLCntChosen AuLCntPCPUREF */ ++ ++#if AuLCntChosen == AuLCntATOMIC ++#include ++ ++typedef atomic_long_t au_lcnt_t; ++ ++static inline int au_lcnt_init(au_lcnt_t *cnt, void *release __maybe_unused) ++{ ++ atomic_long_set(cnt, 0); ++ return 0; ++} ++ ++static inline void au_lcnt_wait_for_fin(au_lcnt_t *cnt __maybe_unused) ++{ ++ /* empty */ ++} ++ ++static inline void au_lcnt_fin(au_lcnt_t *cnt __maybe_unused, ++ int do_sync __maybe_unused) ++{ ++ /* empty */ ++} ++ ++static inline void au_lcnt_inc(au_lcnt_t *cnt) ++{ ++ atomic_long_inc(cnt); ++} ++ ++static inline void au_lcnt_dec(au_lcnt_t *cnt) ++{ ++ atomic_long_dec(cnt); ++} ++ ++static inline long au_lcnt_read(au_lcnt_t *cnt, int do_rev __maybe_unused) ++{ ++ return atomic_long_read(cnt); ++} ++#endif ++ ++#if AuLCntChosen == AuLCntPCPUCNT ++#include ++ ++typedef struct percpu_counter au_lcnt_t; ++ ++static inline int au_lcnt_init(au_lcnt_t *cnt, void *release __maybe_unused) ++{ ++ return percpu_counter_init(cnt, 0, GFP_NOFS); ++} ++ ++static inline void au_lcnt_wait_for_fin(au_lcnt_t *cnt __maybe_unused) ++{ ++ /* empty */ ++} ++ ++static inline void au_lcnt_fin(au_lcnt_t *cnt, int do_sync __maybe_unused) ++{ ++ percpu_counter_destroy(cnt); ++} ++ ++static inline void au_lcnt_inc(au_lcnt_t *cnt) ++{ ++ percpu_counter_inc(cnt); ++} ++ ++static inline void au_lcnt_dec(au_lcnt_t *cnt) ++{ ++ percpu_counter_dec(cnt); ++} ++ ++static inline long au_lcnt_read(au_lcnt_t *cnt, int do_rev __maybe_unused) ++{ ++ s64 n; ++ ++ n = percpu_counter_sum(cnt); ++ BUG_ON(n < 0); ++ if (LONG_MAX != LLONG_MAX ++ && n > LONG_MAX) ++ AuWarn1("%s\n", "wrap-around"); ++ ++ return n; ++} ++#endif ++ ++#if AuLCntChosen == AuLCntPCPUREF ++#include ++ ++typedef struct percpu_ref au_lcnt_t; ++ ++static inline int au_lcnt_init(au_lcnt_t *cnt, percpu_ref_func_t *release) ++{ ++ if (!release) ++ release = percpu_ref_exit; ++ return percpu_ref_init(cnt, release, /*percpu mode*/0, GFP_NOFS); ++} ++ ++static inline void au_lcnt_wait_for_fin(au_lcnt_t *cnt __maybe_unused) ++{ ++ synchronize_rcu(); ++} ++ ++static inline void au_lcnt_fin(au_lcnt_t *cnt, int do_sync) ++{ ++ percpu_ref_kill(cnt); ++ if (do_sync) ++ au_lcnt_wait_for_fin(cnt); ++} ++ ++static inline void au_lcnt_inc(au_lcnt_t *cnt) ++{ ++ percpu_ref_get(cnt); ++} ++ ++static inline void au_lcnt_dec(au_lcnt_t *cnt) ++{ ++ percpu_ref_put(cnt); ++} ++ ++/* ++ * avoid calling this func as possible. ++ */ ++static inline long au_lcnt_read(au_lcnt_t *cnt, int do_rev) ++{ ++ long l; ++ ++ percpu_ref_switch_to_atomic_sync(cnt); ++ l = atomic_long_read(&cnt->count); ++ if (do_rev) ++ percpu_ref_switch_to_percpu(cnt); ++ ++ /* percpu_ref is initialized by 1 instead of 0 */ ++ return l - 1; ++} ++#endif ++ ++#ifdef CONFIG_AUFS_DEBUG ++#define AuLCntZero(val) do { \ ++ long l = val; \ ++ if (l) \ ++ AuDbg("%s = %ld\n", #val, l); \ ++} while (0) ++#else ++#define AuLCntZero(val) do {} while (0) ++#endif ++ ++#endif /* __KERNEL__ */ ++#endif /* __AUFS_LCNT_H__ */ +diff -Nurp linux-5.4/fs/aufs/loop.c linux-5.4-aufs/fs/aufs/loop.c +--- linux-5.4/fs/aufs/loop.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/loop.c 2019-11-28 01:25:59.066925618 +0200 +@@ -0,0 +1,135 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * support for loopback block device as a branch ++ */ ++ ++#include "aufs.h" ++ ++/* added into drivers/block/loop.c */ ++static struct file *(*backing_file_func)(struct super_block *sb); ++ ++/* ++ * test if two lower dentries have overlapping branches. ++ */ ++int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding) ++{ ++ struct super_block *h_sb; ++ struct file *backing_file; ++ ++ if (unlikely(!backing_file_func)) { ++ /* don't load "loop" module here */ ++ backing_file_func = symbol_get(loop_backing_file); ++ if (unlikely(!backing_file_func)) ++ /* "loop" module is not loaded */ ++ return 0; ++ } ++ ++ h_sb = h_adding->d_sb; ++ backing_file = backing_file_func(h_sb); ++ if (!backing_file) ++ return 0; ++ ++ h_adding = backing_file->f_path.dentry; ++ /* ++ * h_adding can be local NFS. ++ * in this case aufs cannot detect the loop. ++ */ ++ if (unlikely(h_adding->d_sb == sb)) ++ return 1; ++ return !!au_test_subdir(h_adding, sb->s_root); ++} ++ ++/* true if a kernel thread named 'loop[0-9].*' accesses a file */ ++int au_test_loopback_kthread(void) ++{ ++ int ret; ++ struct task_struct *tsk = current; ++ char c, comm[sizeof(tsk->comm)]; ++ ++ ret = 0; ++ if (tsk->flags & PF_KTHREAD) { ++ get_task_comm(comm, tsk); ++ c = comm[4]; ++ ret = ('0' <= c && c <= '9' ++ && !strncmp(comm, "loop", 4)); ++ } ++ ++ return ret; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++#define au_warn_loopback_step 16 ++static int au_warn_loopback_nelem = au_warn_loopback_step; ++static unsigned long *au_warn_loopback_array; ++ ++void au_warn_loopback(struct super_block *h_sb) ++{ ++ int i, new_nelem; ++ unsigned long *a, magic; ++ static DEFINE_SPINLOCK(spin); ++ ++ magic = h_sb->s_magic; ++ spin_lock(&spin); ++ a = au_warn_loopback_array; ++ for (i = 0; i < au_warn_loopback_nelem && *a; i++) ++ if (a[i] == magic) { ++ spin_unlock(&spin); ++ return; ++ } ++ ++ /* h_sb is new to us, print it */ ++ if (i < au_warn_loopback_nelem) { ++ a[i] = magic; ++ goto pr; ++ } ++ ++ /* expand the array */ ++ new_nelem = au_warn_loopback_nelem + au_warn_loopback_step; ++ a = au_kzrealloc(au_warn_loopback_array, ++ au_warn_loopback_nelem * sizeof(unsigned long), ++ new_nelem * sizeof(unsigned long), GFP_ATOMIC, ++ /*may_shrink*/0); ++ if (a) { ++ au_warn_loopback_nelem = new_nelem; ++ au_warn_loopback_array = a; ++ a[i] = magic; ++ goto pr; ++ } ++ ++ spin_unlock(&spin); ++ AuWarn1("realloc failed, ignored\n"); ++ return; ++ ++pr: ++ spin_unlock(&spin); ++ pr_warn("you may want to try another patch for loopback file " ++ "on %s(0x%lx) branch\n", au_sbtype(h_sb), magic); ++} ++ ++int au_loopback_init(void) ++{ ++ int err; ++ struct super_block *sb __maybe_unused; ++ ++ BUILD_BUG_ON(sizeof(sb->s_magic) != sizeof(*au_warn_loopback_array)); ++ ++ err = 0; ++ au_warn_loopback_array = kcalloc(au_warn_loopback_step, ++ sizeof(unsigned long), GFP_NOFS); ++ if (unlikely(!au_warn_loopback_array)) ++ err = -ENOMEM; ++ ++ return err; ++} ++ ++void au_loopback_fin(void) ++{ ++ if (backing_file_func) ++ symbol_put(loop_backing_file); ++ au_kfree_try_rcu(au_warn_loopback_array); ++} +diff -Nurp linux-5.4/fs/aufs/loop.h linux-5.4-aufs/fs/aufs/loop.h +--- linux-5.4/fs/aufs/loop.h 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/loop.h 2019-11-28 01:25:59.066925618 +0200 +@@ -0,0 +1,42 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * support for loopback mount as a branch ++ */ ++ ++#ifndef __AUFS_LOOP_H__ ++#define __AUFS_LOOP_H__ ++ ++#ifdef __KERNEL__ ++ ++struct dentry; ++struct super_block; ++ ++#ifdef CONFIG_AUFS_BDEV_LOOP ++/* drivers/block/loop.c */ ++struct file *loop_backing_file(struct super_block *sb); ++ ++/* loop.c */ ++int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding); ++int au_test_loopback_kthread(void); ++void au_warn_loopback(struct super_block *h_sb); ++ ++int au_loopback_init(void); ++void au_loopback_fin(void); ++#else ++AuStub(struct file *, loop_backing_file, return NULL, struct super_block *sb) ++ ++AuStubInt0(au_test_loopback_overlap, struct super_block *sb, ++ struct dentry *h_adding) ++AuStubInt0(au_test_loopback_kthread, void) ++AuStubVoid(au_warn_loopback, struct super_block *h_sb) ++ ++AuStubInt0(au_loopback_init, void) ++AuStubVoid(au_loopback_fin, void) ++#endif /* BLK_DEV_LOOP */ ++ ++#endif /* __KERNEL__ */ ++#endif /* __AUFS_LOOP_H__ */ +diff -Nurp linux-5.4/fs/aufs/magic.mk linux-5.4-aufs/fs/aufs/magic.mk +--- linux-5.4/fs/aufs/magic.mk 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/magic.mk 2019-11-28 01:25:59.066925618 +0200 +@@ -0,0 +1,31 @@ ++# SPDX-License-Identifier: GPL-2.0 ++ ++# defined in ${srctree}/fs/fuse/inode.c ++# tristate ++ifdef CONFIG_FUSE_FS ++ccflags-y += -DFUSE_SUPER_MAGIC=0x65735546 ++endif ++ ++# defined in ${srctree}/fs/xfs/xfs_sb.h ++# tristate ++ifdef CONFIG_XFS_FS ++ccflags-y += -DXFS_SB_MAGIC=0x58465342 ++endif ++ ++# defined in ${srctree}/fs/configfs/mount.c ++# tristate ++ifdef CONFIG_CONFIGFS_FS ++ccflags-y += -DCONFIGFS_MAGIC=0x62656570 ++endif ++ ++# defined in ${srctree}/fs/ubifs/ubifs.h ++# tristate ++ifdef CONFIG_UBIFS_FS ++ccflags-y += -DUBIFS_SUPER_MAGIC=0x24051905 ++endif ++ ++# defined in ${srctree}/fs/hfsplus/hfsplus_raw.h ++# tristate ++ifdef CONFIG_HFSPLUS_FS ++ccflags-y += -DHFSPLUS_SUPER_MAGIC=0x482b ++endif +diff -Nurp linux-5.4/fs/aufs/Makefile linux-5.4-aufs/fs/aufs/Makefile +--- linux-5.4/fs/aufs/Makefile 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/Makefile 2019-11-28 01:25:59.062925618 +0200 +@@ -0,0 +1,39 @@ ++# SPDX-License-Identifier: GPL-2.0 ++ ++include ${srctree}/${src}/magic.mk ++-include ${srctree}/${src}/priv_def.mk ++ ++# cf. include/linux/kernel.h ++# enable pr_debug ++ccflags-y += -DDEBUG ++# sparse requires the full pathname ++ccflags-y += -include ${srctree}/include/uapi/linux/aufs_type.h ++ ++obj-$(CONFIG_AUFS_FS) += aufs.o ++aufs-y := module.o sbinfo.o super.o branch.o xino.o sysaufs.o opts.o \ ++ wkq.o vfsub.o dcsub.o \ ++ cpup.o whout.o wbr_policy.o \ ++ dinfo.o dentry.o \ ++ dynop.o \ ++ finfo.o file.o f_op.o \ ++ dir.o vdir.o \ ++ iinfo.o inode.o i_op.o i_op_add.o i_op_del.o i_op_ren.o \ ++ mvdown.o ioctl.o ++ ++# all are boolean ++aufs-$(CONFIG_PROC_FS) += procfs.o plink.o ++aufs-$(CONFIG_SYSFS) += sysfs.o ++aufs-$(CONFIG_DEBUG_FS) += dbgaufs.o ++aufs-$(CONFIG_AUFS_BDEV_LOOP) += loop.o ++aufs-$(CONFIG_AUFS_HNOTIFY) += hnotify.o ++aufs-$(CONFIG_AUFS_HFSNOTIFY) += hfsnotify.o ++aufs-$(CONFIG_AUFS_EXPORT) += export.o ++aufs-$(CONFIG_AUFS_XATTR) += xattr.o ++aufs-$(CONFIG_FS_POSIX_ACL) += posix_acl.o ++aufs-$(CONFIG_AUFS_DIRREN) += dirren.o ++aufs-$(CONFIG_AUFS_FHSM) += fhsm.o ++aufs-$(CONFIG_AUFS_POLL) += poll.o ++aufs-$(CONFIG_AUFS_RDU) += rdu.o ++aufs-$(CONFIG_AUFS_BR_HFSPLUS) += hfsplus.o ++aufs-$(CONFIG_AUFS_DEBUG) += debug.o ++aufs-$(CONFIG_AUFS_MAGIC_SYSRQ) += sysrq.o +diff -Nurp linux-5.4/fs/aufs/module.c linux-5.4-aufs/fs/aufs/module.c +--- linux-5.4/fs/aufs/module.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/module.c 2019-11-28 01:25:59.066925618 +0200 +@@ -0,0 +1,259 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * module global variables and operations ++ */ ++ ++#include ++#include ++#include "aufs.h" ++ ++/* shrinkable realloc */ ++void *au_krealloc(void *p, unsigned int new_sz, gfp_t gfp, int may_shrink) ++{ ++ size_t sz; ++ int diff; ++ ++ sz = 0; ++ diff = -1; ++ if (p) { ++#if 0 /* unused */ ++ if (!new_sz) { ++ au_kfree_rcu(p); ++ p = NULL; ++ goto out; ++ } ++#else ++ AuDebugOn(!new_sz); ++#endif ++ sz = ksize(p); ++ diff = au_kmidx_sub(sz, new_sz); ++ } ++ if (sz && !diff) ++ goto out; ++ ++ if (sz < new_sz) ++ /* expand or SLOB */ ++ p = krealloc(p, new_sz, gfp); ++ else if (new_sz < sz && may_shrink) { ++ /* shrink */ ++ void *q; ++ ++ q = kmalloc(new_sz, gfp); ++ if (q) { ++ if (p) { ++ memcpy(q, p, new_sz); ++ au_kfree_try_rcu(p); ++ } ++ p = q; ++ } else ++ p = NULL; ++ } ++ ++out: ++ return p; ++} ++ ++void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp, ++ int may_shrink) ++{ ++ p = au_krealloc(p, new_sz, gfp, may_shrink); ++ if (p && new_sz > nused) ++ memset(p + nused, 0, new_sz - nused); ++ return p; ++} ++ ++/* ---------------------------------------------------------------------- */ ++/* ++ * aufs caches ++ */ ++struct kmem_cache *au_cache[AuCache_Last]; ++ ++static void au_cache_fin(void) ++{ ++ int i; ++ ++ /* ++ * Make sure all delayed rcu free inodes are flushed before we ++ * destroy cache. ++ */ ++ rcu_barrier(); ++ ++ /* excluding AuCache_HNOTIFY */ ++ BUILD_BUG_ON(AuCache_HNOTIFY + 1 != AuCache_Last); ++ for (i = 0; i < AuCache_HNOTIFY; i++) { ++ kmem_cache_destroy(au_cache[i]); ++ au_cache[i] = NULL; ++ } ++} ++ ++static int __init au_cache_init(void) ++{ ++ au_cache[AuCache_DINFO] = AuCacheCtor(au_dinfo, au_di_init_once); ++ if (au_cache[AuCache_DINFO]) ++ /* SLAB_DESTROY_BY_RCU */ ++ au_cache[AuCache_ICNTNR] = AuCacheCtor(au_icntnr, ++ au_icntnr_init_once); ++ if (au_cache[AuCache_ICNTNR]) ++ au_cache[AuCache_FINFO] = AuCacheCtor(au_finfo, ++ au_fi_init_once); ++ if (au_cache[AuCache_FINFO]) ++ au_cache[AuCache_VDIR] = AuCache(au_vdir); ++ if (au_cache[AuCache_VDIR]) ++ au_cache[AuCache_DEHSTR] = AuCache(au_vdir_dehstr); ++ if (au_cache[AuCache_DEHSTR]) ++ return 0; ++ ++ au_cache_fin(); ++ return -ENOMEM; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++int au_dir_roflags; ++ ++#ifdef CONFIG_AUFS_SBILIST ++/* ++ * iterate_supers_type() doesn't protect us from ++ * remounting (branch management) ++ */ ++struct hlist_bl_head au_sbilist; ++#endif ++ ++/* ++ * functions for module interface. ++ */ ++MODULE_LICENSE("GPL"); ++/* MODULE_LICENSE("GPL v2"); */ ++MODULE_AUTHOR("Junjiro R. Okajima "); ++MODULE_DESCRIPTION(AUFS_NAME ++ " -- Advanced multi layered unification filesystem"); ++MODULE_VERSION(AUFS_VERSION); ++ ++/* this module parameter has no meaning when SYSFS is disabled */ ++int sysaufs_brs = 1; ++MODULE_PARM_DESC(brs, "use /fs/aufs/si_*/brN"); ++module_param_named(brs, sysaufs_brs, int, 0444); ++ ++/* this module parameter has no meaning when USER_NS is disabled */ ++bool au_userns; ++MODULE_PARM_DESC(allow_userns, "allow unprivileged to mount under userns"); ++module_param_named(allow_userns, au_userns, bool, 0444); ++ ++/* ---------------------------------------------------------------------- */ ++ ++static char au_esc_chars[0x20 + 3]; /* 0x01-0x20, backslash, del, and NULL */ ++ ++int au_seq_path(struct seq_file *seq, struct path *path) ++{ ++ int err; ++ ++ err = seq_path(seq, path, au_esc_chars); ++ if (err >= 0) ++ err = 0; ++ else ++ err = -ENOMEM; ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int __init aufs_init(void) ++{ ++ int err, i; ++ char *p; ++ ++ p = au_esc_chars; ++ for (i = 1; i <= ' '; i++) ++ *p++ = i; ++ *p++ = '\\'; ++ *p++ = '\x7f'; ++ *p = 0; ++ ++ au_dir_roflags = au_file_roflags(O_DIRECTORY | O_LARGEFILE); ++ ++ memcpy(aufs_iop_nogetattr, aufs_iop, sizeof(aufs_iop)); ++ for (i = 0; i < AuIop_Last; i++) ++ aufs_iop_nogetattr[i].getattr = NULL; ++ ++ memset(au_cache, 0, sizeof(au_cache)); /* including hnotify */ ++ ++ au_sbilist_init(); ++ sysaufs_brs_init(); ++ au_debug_init(); ++ au_dy_init(); ++ err = sysaufs_init(); ++ if (unlikely(err)) ++ goto out; ++ err = dbgaufs_init(); ++ if (unlikely(err)) ++ goto out_sysaufs; ++ err = au_procfs_init(); ++ if (unlikely(err)) ++ goto out_dbgaufs; ++ err = au_wkq_init(); ++ if (unlikely(err)) ++ goto out_procfs; ++ err = au_loopback_init(); ++ if (unlikely(err)) ++ goto out_wkq; ++ err = au_hnotify_init(); ++ if (unlikely(err)) ++ goto out_loopback; ++ err = au_sysrq_init(); ++ if (unlikely(err)) ++ goto out_hin; ++ err = au_cache_init(); ++ if (unlikely(err)) ++ goto out_sysrq; ++ ++ aufs_fs_type.fs_flags |= au_userns ? FS_USERNS_MOUNT : 0; ++ err = register_filesystem(&aufs_fs_type); ++ if (unlikely(err)) ++ goto out_cache; ++ ++ /* since we define pr_fmt, call printk directly */ ++ printk(KERN_INFO AUFS_NAME " " AUFS_VERSION "\n"); ++ goto out; /* success */ ++ ++out_cache: ++ au_cache_fin(); ++out_sysrq: ++ au_sysrq_fin(); ++out_hin: ++ au_hnotify_fin(); ++out_loopback: ++ au_loopback_fin(); ++out_wkq: ++ au_wkq_fin(); ++out_procfs: ++ au_procfs_fin(); ++out_dbgaufs: ++ dbgaufs_fin(); ++out_sysaufs: ++ sysaufs_fin(); ++ au_dy_fin(); ++out: ++ return err; ++} ++ ++static void __exit aufs_exit(void) ++{ ++ unregister_filesystem(&aufs_fs_type); ++ au_cache_fin(); ++ au_sysrq_fin(); ++ au_hnotify_fin(); ++ au_loopback_fin(); ++ au_wkq_fin(); ++ au_procfs_fin(); ++ dbgaufs_fin(); ++ sysaufs_fin(); ++ au_dy_fin(); ++} ++ ++module_init(aufs_init); ++module_exit(aufs_exit); +diff -Nurp linux-5.4/fs/aufs/module.h linux-5.4-aufs/fs/aufs/module.h +--- linux-5.4/fs/aufs/module.h 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/module.h 2019-11-28 01:25:59.066925618 +0200 +@@ -0,0 +1,153 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * module initialization and module-global ++ */ ++ ++#ifndef __AUFS_MODULE_H__ ++#define __AUFS_MODULE_H__ ++ ++#ifdef __KERNEL__ ++ ++#include ++#include "debug.h" ++#include "dentry.h" ++#include "dir.h" ++#include "file.h" ++#include "inode.h" ++ ++struct path; ++struct seq_file; ++ ++/* module parameters */ ++extern int sysaufs_brs; ++extern bool au_userns; ++ ++/* ---------------------------------------------------------------------- */ ++ ++extern int au_dir_roflags; ++ ++void *au_krealloc(void *p, unsigned int new_sz, gfp_t gfp, int may_shrink); ++void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp, ++ int may_shrink); ++ ++/* ++ * Comparing the size of the object with sizeof(struct rcu_head) ++ * case 1: object is always larger ++ * --> au_kfree_rcu() or au_kfree_do_rcu() ++ * case 2: object is always smaller ++ * --> au_kfree_small() ++ * case 3: object can be any size ++ * --> au_kfree_try_rcu() ++ */ ++ ++static inline void au_kfree_do_rcu(const void *p) ++{ ++ struct { ++ struct rcu_head rcu; ++ } *a = (void *)p; ++ ++ kfree_rcu(a, rcu); ++} ++ ++#define au_kfree_rcu(_p) do { \ ++ typeof(_p) p = (_p); \ ++ BUILD_BUG_ON(sizeof(*p) < sizeof(struct rcu_head)); \ ++ if (p) \ ++ au_kfree_do_rcu(p); \ ++ } while (0) ++ ++#define au_kfree_do_sz_test(sz) (sz >= sizeof(struct rcu_head)) ++#define au_kfree_sz_test(p) (p && au_kfree_do_sz_test(ksize(p))) ++ ++static inline void au_kfree_try_rcu(const void *p) ++{ ++ if (!p) ++ return; ++ if (au_kfree_sz_test(p)) ++ au_kfree_do_rcu(p); ++ else ++ kfree(p); ++} ++ ++static inline void au_kfree_small(const void *p) ++{ ++ if (!p) ++ return; ++ AuDebugOn(au_kfree_sz_test(p)); ++ kfree(p); ++} ++ ++static inline int au_kmidx_sub(size_t sz, size_t new_sz) ++{ ++#ifndef CONFIG_SLOB ++ return kmalloc_index(sz) - kmalloc_index(new_sz); ++#else ++ return -1; /* SLOB is untested */ ++#endif ++} ++ ++int au_seq_path(struct seq_file *seq, struct path *path); ++ ++#ifdef CONFIG_PROC_FS ++/* procfs.c */ ++int __init au_procfs_init(void); ++void au_procfs_fin(void); ++#else ++AuStubInt0(au_procfs_init, void); ++AuStubVoid(au_procfs_fin, void); ++#endif ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* kmem cache */ ++enum { ++ AuCache_DINFO, ++ AuCache_ICNTNR, ++ AuCache_FINFO, ++ AuCache_VDIR, ++ AuCache_DEHSTR, ++ AuCache_HNOTIFY, /* must be last */ ++ AuCache_Last ++}; ++ ++extern struct kmem_cache *au_cache[AuCache_Last]; ++ ++#define AuCacheFlags (SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD) ++#define AuCache(type) KMEM_CACHE(type, AuCacheFlags) ++#define AuCacheCtor(type, ctor) \ ++ kmem_cache_create(#type, sizeof(struct type), \ ++ __alignof__(struct type), AuCacheFlags, ctor) ++ ++#define AuCacheFuncs(name, index) \ ++ static inline struct au_##name *au_cache_alloc_##name(void) \ ++ { return kmem_cache_alloc(au_cache[AuCache_##index], GFP_NOFS); } \ ++ static inline void au_cache_free_##name##_norcu(struct au_##name *p) \ ++ { kmem_cache_free(au_cache[AuCache_##index], p); } \ ++ \ ++ static inline void au_cache_free_##name##_rcu_cb(struct rcu_head *rcu) \ ++ { void *p = rcu; \ ++ p -= offsetof(struct au_##name, rcu); \ ++ kmem_cache_free(au_cache[AuCache_##index], p); } \ ++ static inline void au_cache_free_##name##_rcu(struct au_##name *p) \ ++ { BUILD_BUG_ON(sizeof(struct au_##name) < sizeof(struct rcu_head)); \ ++ call_rcu(&p->rcu, au_cache_free_##name##_rcu_cb); } \ ++ \ ++ static inline void au_cache_free_##name(struct au_##name *p) \ ++ { /* au_cache_free_##name##_norcu(p); */ \ ++ au_cache_free_##name##_rcu(p); } ++ ++AuCacheFuncs(dinfo, DINFO); ++AuCacheFuncs(icntnr, ICNTNR); ++AuCacheFuncs(finfo, FINFO); ++AuCacheFuncs(vdir, VDIR); ++AuCacheFuncs(vdir_dehstr, DEHSTR); ++#ifdef CONFIG_AUFS_HNOTIFY ++AuCacheFuncs(hnotify, HNOTIFY); ++#endif ++ ++#endif /* __KERNEL__ */ ++#endif /* __AUFS_MODULE_H__ */ +diff -Nurp linux-5.4/fs/aufs/mvdown.c linux-5.4-aufs/fs/aufs/mvdown.c +--- linux-5.4/fs/aufs/mvdown.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/mvdown.c 2019-11-28 01:25:59.067925618 +0200 +@@ -0,0 +1,693 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2011-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * move-down, opposite of copy-up ++ */ ++ ++#include "aufs.h" ++ ++struct au_mvd_args { ++ struct { ++ struct super_block *h_sb; ++ struct dentry *h_parent; ++ struct au_hinode *hdir; ++ struct inode *h_dir, *h_inode; ++ struct au_pin pin; ++ } info[AUFS_MVDOWN_NARRAY]; ++ ++ struct aufs_mvdown mvdown; ++ struct dentry *dentry, *parent; ++ struct inode *inode, *dir; ++ struct super_block *sb; ++ aufs_bindex_t bopq, bwh, bfound; ++ unsigned char rename_lock; ++}; ++ ++#define mvd_errno mvdown.au_errno ++#define mvd_bsrc mvdown.stbr[AUFS_MVDOWN_UPPER].bindex ++#define mvd_src_brid mvdown.stbr[AUFS_MVDOWN_UPPER].brid ++#define mvd_bdst mvdown.stbr[AUFS_MVDOWN_LOWER].bindex ++#define mvd_dst_brid mvdown.stbr[AUFS_MVDOWN_LOWER].brid ++ ++#define mvd_h_src_sb info[AUFS_MVDOWN_UPPER].h_sb ++#define mvd_h_src_parent info[AUFS_MVDOWN_UPPER].h_parent ++#define mvd_hdir_src info[AUFS_MVDOWN_UPPER].hdir ++#define mvd_h_src_dir info[AUFS_MVDOWN_UPPER].h_dir ++#define mvd_h_src_inode info[AUFS_MVDOWN_UPPER].h_inode ++#define mvd_pin_src info[AUFS_MVDOWN_UPPER].pin ++ ++#define mvd_h_dst_sb info[AUFS_MVDOWN_LOWER].h_sb ++#define mvd_h_dst_parent info[AUFS_MVDOWN_LOWER].h_parent ++#define mvd_hdir_dst info[AUFS_MVDOWN_LOWER].hdir ++#define mvd_h_dst_dir info[AUFS_MVDOWN_LOWER].h_dir ++#define mvd_h_dst_inode info[AUFS_MVDOWN_LOWER].h_inode ++#define mvd_pin_dst info[AUFS_MVDOWN_LOWER].pin ++ ++#define AU_MVD_PR(flag, ...) do { \ ++ if (flag) \ ++ pr_err(__VA_ARGS__); \ ++ } while (0) ++ ++static int find_lower_writable(struct au_mvd_args *a) ++{ ++ struct super_block *sb; ++ aufs_bindex_t bindex, bbot; ++ struct au_branch *br; ++ ++ sb = a->sb; ++ bindex = a->mvd_bsrc; ++ bbot = au_sbbot(sb); ++ if (a->mvdown.flags & AUFS_MVDOWN_FHSM_LOWER) ++ for (bindex++; bindex <= bbot; bindex++) { ++ br = au_sbr(sb, bindex); ++ if (au_br_fhsm(br->br_perm) ++ && !sb_rdonly(au_br_sb(br))) ++ return bindex; ++ } ++ else if (!(a->mvdown.flags & AUFS_MVDOWN_ROLOWER)) ++ for (bindex++; bindex <= bbot; bindex++) { ++ br = au_sbr(sb, bindex); ++ if (!au_br_rdonly(br)) ++ return bindex; ++ } ++ else ++ for (bindex++; bindex <= bbot; bindex++) { ++ br = au_sbr(sb, bindex); ++ if (!sb_rdonly(au_br_sb(br))) { ++ if (au_br_rdonly(br)) ++ a->mvdown.flags ++ |= AUFS_MVDOWN_ROLOWER_R; ++ return bindex; ++ } ++ } ++ ++ return -1; ++} ++ ++/* make the parent dir on bdst */ ++static int au_do_mkdir(const unsigned char dmsg, struct au_mvd_args *a) ++{ ++ int err; ++ ++ err = 0; ++ a->mvd_hdir_src = au_hi(a->dir, a->mvd_bsrc); ++ a->mvd_hdir_dst = au_hi(a->dir, a->mvd_bdst); ++ a->mvd_h_src_parent = au_h_dptr(a->parent, a->mvd_bsrc); ++ a->mvd_h_dst_parent = NULL; ++ if (au_dbbot(a->parent) >= a->mvd_bdst) ++ a->mvd_h_dst_parent = au_h_dptr(a->parent, a->mvd_bdst); ++ if (!a->mvd_h_dst_parent) { ++ err = au_cpdown_dirs(a->dentry, a->mvd_bdst); ++ if (unlikely(err)) { ++ AU_MVD_PR(dmsg, "cpdown_dirs failed\n"); ++ goto out; ++ } ++ a->mvd_h_dst_parent = au_h_dptr(a->parent, a->mvd_bdst); ++ } ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++/* lock them all */ ++static int au_do_lock(const unsigned char dmsg, struct au_mvd_args *a) ++{ ++ int err; ++ struct dentry *h_trap; ++ ++ a->mvd_h_src_sb = au_sbr_sb(a->sb, a->mvd_bsrc); ++ a->mvd_h_dst_sb = au_sbr_sb(a->sb, a->mvd_bdst); ++ err = au_pin(&a->mvd_pin_dst, a->dentry, a->mvd_bdst, ++ au_opt_udba(a->sb), ++ AuPin_MNT_WRITE | AuPin_DI_LOCKED); ++ AuTraceErr(err); ++ if (unlikely(err)) { ++ AU_MVD_PR(dmsg, "pin_dst failed\n"); ++ goto out; ++ } ++ ++ if (a->mvd_h_src_sb != a->mvd_h_dst_sb) { ++ a->rename_lock = 0; ++ au_pin_init(&a->mvd_pin_src, a->dentry, a->mvd_bsrc, ++ AuLsc_DI_PARENT, AuLsc_I_PARENT3, ++ au_opt_udba(a->sb), ++ AuPin_MNT_WRITE | AuPin_DI_LOCKED); ++ err = au_do_pin(&a->mvd_pin_src); ++ AuTraceErr(err); ++ a->mvd_h_src_dir = d_inode(a->mvd_h_src_parent); ++ if (unlikely(err)) { ++ AU_MVD_PR(dmsg, "pin_src failed\n"); ++ goto out_dst; ++ } ++ goto out; /* success */ ++ } ++ ++ a->rename_lock = 1; ++ au_pin_hdir_unlock(&a->mvd_pin_dst); ++ err = au_pin(&a->mvd_pin_src, a->dentry, a->mvd_bsrc, ++ au_opt_udba(a->sb), ++ AuPin_MNT_WRITE | AuPin_DI_LOCKED); ++ AuTraceErr(err); ++ a->mvd_h_src_dir = d_inode(a->mvd_h_src_parent); ++ if (unlikely(err)) { ++ AU_MVD_PR(dmsg, "pin_src failed\n"); ++ au_pin_hdir_lock(&a->mvd_pin_dst); ++ goto out_dst; ++ } ++ au_pin_hdir_unlock(&a->mvd_pin_src); ++ h_trap = vfsub_lock_rename(a->mvd_h_src_parent, a->mvd_hdir_src, ++ a->mvd_h_dst_parent, a->mvd_hdir_dst); ++ if (h_trap) { ++ err = (h_trap != a->mvd_h_src_parent); ++ if (err) ++ err = (h_trap != a->mvd_h_dst_parent); ++ } ++ BUG_ON(err); /* it should never happen */ ++ if (unlikely(a->mvd_h_src_dir != au_pinned_h_dir(&a->mvd_pin_src))) { ++ err = -EBUSY; ++ AuTraceErr(err); ++ vfsub_unlock_rename(a->mvd_h_src_parent, a->mvd_hdir_src, ++ a->mvd_h_dst_parent, a->mvd_hdir_dst); ++ au_pin_hdir_lock(&a->mvd_pin_src); ++ au_unpin(&a->mvd_pin_src); ++ au_pin_hdir_lock(&a->mvd_pin_dst); ++ goto out_dst; ++ } ++ goto out; /* success */ ++ ++out_dst: ++ au_unpin(&a->mvd_pin_dst); ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++static void au_do_unlock(const unsigned char dmsg, struct au_mvd_args *a) ++{ ++ if (!a->rename_lock) ++ au_unpin(&a->mvd_pin_src); ++ else { ++ vfsub_unlock_rename(a->mvd_h_src_parent, a->mvd_hdir_src, ++ a->mvd_h_dst_parent, a->mvd_hdir_dst); ++ au_pin_hdir_lock(&a->mvd_pin_src); ++ au_unpin(&a->mvd_pin_src); ++ au_pin_hdir_lock(&a->mvd_pin_dst); ++ } ++ au_unpin(&a->mvd_pin_dst); ++} ++ ++/* copy-down the file */ ++static int au_do_cpdown(const unsigned char dmsg, struct au_mvd_args *a) ++{ ++ int err; ++ struct au_cp_generic cpg = { ++ .dentry = a->dentry, ++ .bdst = a->mvd_bdst, ++ .bsrc = a->mvd_bsrc, ++ .len = -1, ++ .pin = &a->mvd_pin_dst, ++ .flags = AuCpup_DTIME | AuCpup_HOPEN ++ }; ++ ++ AuDbg("b%d, b%d\n", cpg.bsrc, cpg.bdst); ++ if (a->mvdown.flags & AUFS_MVDOWN_OWLOWER) ++ au_fset_cpup(cpg.flags, OVERWRITE); ++ if (a->mvdown.flags & AUFS_MVDOWN_ROLOWER) ++ au_fset_cpup(cpg.flags, RWDST); ++ err = au_sio_cpdown_simple(&cpg); ++ if (unlikely(err)) ++ AU_MVD_PR(dmsg, "cpdown failed\n"); ++ ++ AuTraceErr(err); ++ return err; ++} ++ ++/* ++ * unlink the whiteout on bdst if exist which may be created by UDBA while we ++ * were sleeping ++ */ ++static int au_do_unlink_wh(const unsigned char dmsg, struct au_mvd_args *a) ++{ ++ int err; ++ struct path h_path; ++ struct au_branch *br; ++ struct inode *delegated; ++ ++ br = au_sbr(a->sb, a->mvd_bdst); ++ h_path.dentry = au_wh_lkup(a->mvd_h_dst_parent, &a->dentry->d_name, br); ++ err = PTR_ERR(h_path.dentry); ++ if (IS_ERR(h_path.dentry)) { ++ AU_MVD_PR(dmsg, "wh_lkup failed\n"); ++ goto out; ++ } ++ ++ err = 0; ++ if (d_is_positive(h_path.dentry)) { ++ h_path.mnt = au_br_mnt(br); ++ delegated = NULL; ++ err = vfsub_unlink(d_inode(a->mvd_h_dst_parent), &h_path, ++ &delegated, /*force*/0); ++ if (unlikely(err == -EWOULDBLOCK)) { ++ pr_warn("cannot retry for NFSv4 delegation" ++ " for an internal unlink\n"); ++ iput(delegated); ++ } ++ if (unlikely(err)) ++ AU_MVD_PR(dmsg, "wh_unlink failed\n"); ++ } ++ dput(h_path.dentry); ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++/* ++ * unlink the topmost h_dentry ++ */ ++static int au_do_unlink(const unsigned char dmsg, struct au_mvd_args *a) ++{ ++ int err; ++ struct path h_path; ++ struct inode *delegated; ++ ++ h_path.mnt = au_sbr_mnt(a->sb, a->mvd_bsrc); ++ h_path.dentry = au_h_dptr(a->dentry, a->mvd_bsrc); ++ delegated = NULL; ++ err = vfsub_unlink(a->mvd_h_src_dir, &h_path, &delegated, /*force*/0); ++ if (unlikely(err == -EWOULDBLOCK)) { ++ pr_warn("cannot retry for NFSv4 delegation" ++ " for an internal unlink\n"); ++ iput(delegated); ++ } ++ if (unlikely(err)) ++ AU_MVD_PR(dmsg, "unlink failed\n"); ++ ++ AuTraceErr(err); ++ return err; ++} ++ ++/* Since mvdown succeeded, we ignore an error of this function */ ++static void au_do_stfs(const unsigned char dmsg, struct au_mvd_args *a) ++{ ++ int err; ++ struct au_branch *br; ++ ++ a->mvdown.flags |= AUFS_MVDOWN_STFS_FAILED; ++ br = au_sbr(a->sb, a->mvd_bsrc); ++ err = au_br_stfs(br, &a->mvdown.stbr[AUFS_MVDOWN_UPPER].stfs); ++ if (!err) { ++ br = au_sbr(a->sb, a->mvd_bdst); ++ a->mvdown.stbr[AUFS_MVDOWN_LOWER].brid = br->br_id; ++ err = au_br_stfs(br, &a->mvdown.stbr[AUFS_MVDOWN_LOWER].stfs); ++ } ++ if (!err) ++ a->mvdown.flags &= ~AUFS_MVDOWN_STFS_FAILED; ++ else ++ AU_MVD_PR(dmsg, "statfs failed (%d), ignored\n", err); ++} ++ ++/* ++ * copy-down the file and unlink the bsrc file. ++ * - unlink the bdst whout if exist ++ * - copy-down the file (with whtmp name and rename) ++ * - unlink the bsrc file ++ */ ++static int au_do_mvdown(const unsigned char dmsg, struct au_mvd_args *a) ++{ ++ int err; ++ ++ err = au_do_mkdir(dmsg, a); ++ if (!err) ++ err = au_do_lock(dmsg, a); ++ if (unlikely(err)) ++ goto out; ++ ++ /* ++ * do not revert the activities we made on bdst since they should be ++ * harmless in aufs. ++ */ ++ ++ err = au_do_cpdown(dmsg, a); ++ if (!err) ++ err = au_do_unlink_wh(dmsg, a); ++ if (!err && !(a->mvdown.flags & AUFS_MVDOWN_KUPPER)) ++ err = au_do_unlink(dmsg, a); ++ if (unlikely(err)) ++ goto out_unlock; ++ ++ AuDbg("%pd2, 0x%x, %d --> %d\n", ++ a->dentry, a->mvdown.flags, a->mvd_bsrc, a->mvd_bdst); ++ if (find_lower_writable(a) < 0) ++ a->mvdown.flags |= AUFS_MVDOWN_BOTTOM; ++ ++ if (a->mvdown.flags & AUFS_MVDOWN_STFS) ++ au_do_stfs(dmsg, a); ++ ++ /* maintain internal array */ ++ if (!(a->mvdown.flags & AUFS_MVDOWN_KUPPER)) { ++ au_set_h_dptr(a->dentry, a->mvd_bsrc, NULL); ++ au_set_dbtop(a->dentry, a->mvd_bdst); ++ au_set_h_iptr(a->inode, a->mvd_bsrc, NULL, /*flags*/0); ++ au_set_ibtop(a->inode, a->mvd_bdst); ++ } else { ++ /* hide the lower */ ++ au_set_h_dptr(a->dentry, a->mvd_bdst, NULL); ++ au_set_dbbot(a->dentry, a->mvd_bsrc); ++ au_set_h_iptr(a->inode, a->mvd_bdst, NULL, /*flags*/0); ++ au_set_ibbot(a->inode, a->mvd_bsrc); ++ } ++ if (au_dbbot(a->dentry) < a->mvd_bdst) ++ au_set_dbbot(a->dentry, a->mvd_bdst); ++ if (au_ibbot(a->inode) < a->mvd_bdst) ++ au_set_ibbot(a->inode, a->mvd_bdst); ++ ++out_unlock: ++ au_do_unlock(dmsg, a); ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* make sure the file is idle */ ++static int au_mvd_args_busy(const unsigned char dmsg, struct au_mvd_args *a) ++{ ++ int err, plinked; ++ ++ err = 0; ++ plinked = !!au_opt_test(au_mntflags(a->sb), PLINK); ++ if (au_dbtop(a->dentry) == a->mvd_bsrc ++ && au_dcount(a->dentry) == 1 ++ && atomic_read(&a->inode->i_count) == 1 ++ /* && a->mvd_h_src_inode->i_nlink == 1 */ ++ && (!plinked || !au_plink_test(a->inode)) ++ && a->inode->i_nlink == 1) ++ goto out; ++ ++ err = -EBUSY; ++ AU_MVD_PR(dmsg, ++ "b%d, d{b%d, c%d?}, i{c%d?, l%u}, hi{l%u}, p{%d, %d}\n", ++ a->mvd_bsrc, au_dbtop(a->dentry), au_dcount(a->dentry), ++ atomic_read(&a->inode->i_count), a->inode->i_nlink, ++ a->mvd_h_src_inode->i_nlink, ++ plinked, plinked ? au_plink_test(a->inode) : 0); ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++/* make sure the parent dir is fine */ ++static int au_mvd_args_parent(const unsigned char dmsg, ++ struct au_mvd_args *a) ++{ ++ int err; ++ aufs_bindex_t bindex; ++ ++ err = 0; ++ if (unlikely(au_alive_dir(a->parent))) { ++ err = -ENOENT; ++ AU_MVD_PR(dmsg, "parent dir is dead\n"); ++ goto out; ++ } ++ ++ a->bopq = au_dbdiropq(a->parent); ++ bindex = au_wbr_nonopq(a->dentry, a->mvd_bdst); ++ AuDbg("b%d\n", bindex); ++ if (unlikely((bindex >= 0 && bindex < a->mvd_bdst) ++ || (a->bopq != -1 && a->bopq < a->mvd_bdst))) { ++ err = -EINVAL; ++ a->mvd_errno = EAU_MVDOWN_OPAQUE; ++ AU_MVD_PR(dmsg, "ancestor is opaque b%d, b%d\n", ++ a->bopq, a->mvd_bdst); ++ } ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++static int au_mvd_args_intermediate(const unsigned char dmsg, ++ struct au_mvd_args *a) ++{ ++ int err; ++ struct au_dinfo *dinfo, *tmp; ++ ++ /* lookup the next lower positive entry */ ++ err = -ENOMEM; ++ tmp = au_di_alloc(a->sb, AuLsc_DI_TMP); ++ if (unlikely(!tmp)) ++ goto out; ++ ++ a->bfound = -1; ++ a->bwh = -1; ++ dinfo = au_di(a->dentry); ++ au_di_cp(tmp, dinfo); ++ au_di_swap(tmp, dinfo); ++ ++ /* returns the number of positive dentries */ ++ err = au_lkup_dentry(a->dentry, a->mvd_bsrc + 1, ++ /* AuLkup_IGNORE_PERM */ 0); ++ if (!err) ++ a->bwh = au_dbwh(a->dentry); ++ else if (err > 0) ++ a->bfound = au_dbtop(a->dentry); ++ ++ au_di_swap(tmp, dinfo); ++ au_rw_write_unlock(&tmp->di_rwsem); ++ au_di_free(tmp); ++ if (unlikely(err < 0)) ++ AU_MVD_PR(dmsg, "failed look-up lower\n"); ++ ++ /* ++ * here, we have these cases. ++ * bfound == -1 ++ * no positive dentry under bsrc. there are more sub-cases. ++ * bwh < 0 ++ * there no whiteout, we can safely move-down. ++ * bwh <= bsrc ++ * impossible ++ * bsrc < bwh && bwh < bdst ++ * there is a whiteout on RO branch. cannot proceed. ++ * bwh == bdst ++ * there is a whiteout on the RW target branch. it should ++ * be removed. ++ * bdst < bwh ++ * there is a whiteout somewhere unrelated branch. ++ * -1 < bfound && bfound <= bsrc ++ * impossible. ++ * bfound < bdst ++ * found, but it is on RO branch between bsrc and bdst. cannot ++ * proceed. ++ * bfound == bdst ++ * found, replace it if AUFS_MVDOWN_FORCE is set. otherwise return ++ * error. ++ * bdst < bfound ++ * found, after we create the file on bdst, it will be hidden. ++ */ ++ ++ AuDebugOn(a->bfound == -1 ++ && a->bwh != -1 ++ && a->bwh <= a->mvd_bsrc); ++ AuDebugOn(-1 < a->bfound ++ && a->bfound <= a->mvd_bsrc); ++ ++ err = -EINVAL; ++ if (a->bfound == -1 ++ && a->mvd_bsrc < a->bwh ++ && a->bwh != -1 ++ && a->bwh < a->mvd_bdst) { ++ a->mvd_errno = EAU_MVDOWN_WHITEOUT; ++ AU_MVD_PR(dmsg, "bsrc %d, bdst %d, bfound %d, bwh %d\n", ++ a->mvd_bsrc, a->mvd_bdst, a->bfound, a->bwh); ++ goto out; ++ } else if (a->bfound != -1 && a->bfound < a->mvd_bdst) { ++ a->mvd_errno = EAU_MVDOWN_UPPER; ++ AU_MVD_PR(dmsg, "bdst %d, bfound %d\n", ++ a->mvd_bdst, a->bfound); ++ goto out; ++ } ++ ++ err = 0; /* success */ ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++static int au_mvd_args_exist(const unsigned char dmsg, struct au_mvd_args *a) ++{ ++ int err; ++ ++ err = 0; ++ if (!(a->mvdown.flags & AUFS_MVDOWN_OWLOWER) ++ && a->bfound == a->mvd_bdst) ++ err = -EEXIST; ++ AuTraceErr(err); ++ return err; ++} ++ ++static int au_mvd_args(const unsigned char dmsg, struct au_mvd_args *a) ++{ ++ int err; ++ struct au_branch *br; ++ ++ err = -EISDIR; ++ if (unlikely(S_ISDIR(a->inode->i_mode))) ++ goto out; ++ ++ err = -EINVAL; ++ if (!(a->mvdown.flags & AUFS_MVDOWN_BRID_UPPER)) ++ a->mvd_bsrc = au_ibtop(a->inode); ++ else { ++ a->mvd_bsrc = au_br_index(a->sb, a->mvd_src_brid); ++ if (unlikely(a->mvd_bsrc < 0 ++ || (a->mvd_bsrc < au_dbtop(a->dentry) ++ || au_dbbot(a->dentry) < a->mvd_bsrc ++ || !au_h_dptr(a->dentry, a->mvd_bsrc)) ++ || (a->mvd_bsrc < au_ibtop(a->inode) ++ || au_ibbot(a->inode) < a->mvd_bsrc ++ || !au_h_iptr(a->inode, a->mvd_bsrc)))) { ++ a->mvd_errno = EAU_MVDOWN_NOUPPER; ++ AU_MVD_PR(dmsg, "no upper\n"); ++ goto out; ++ } ++ } ++ if (unlikely(a->mvd_bsrc == au_sbbot(a->sb))) { ++ a->mvd_errno = EAU_MVDOWN_BOTTOM; ++ AU_MVD_PR(dmsg, "on the bottom\n"); ++ goto out; ++ } ++ a->mvd_h_src_inode = au_h_iptr(a->inode, a->mvd_bsrc); ++ br = au_sbr(a->sb, a->mvd_bsrc); ++ err = au_br_rdonly(br); ++ if (!(a->mvdown.flags & AUFS_MVDOWN_ROUPPER)) { ++ if (unlikely(err)) ++ goto out; ++ } else if (!(vfsub_native_ro(a->mvd_h_src_inode) ++ || IS_APPEND(a->mvd_h_src_inode))) { ++ if (err) ++ a->mvdown.flags |= AUFS_MVDOWN_ROUPPER_R; ++ /* go on */ ++ } else ++ goto out; ++ ++ err = -EINVAL; ++ if (!(a->mvdown.flags & AUFS_MVDOWN_BRID_LOWER)) { ++ a->mvd_bdst = find_lower_writable(a); ++ if (unlikely(a->mvd_bdst < 0)) { ++ a->mvd_errno = EAU_MVDOWN_BOTTOM; ++ AU_MVD_PR(dmsg, "no writable lower branch\n"); ++ goto out; ++ } ++ } else { ++ a->mvd_bdst = au_br_index(a->sb, a->mvd_dst_brid); ++ if (unlikely(a->mvd_bdst < 0 ++ || au_sbbot(a->sb) < a->mvd_bdst)) { ++ a->mvd_errno = EAU_MVDOWN_NOLOWERBR; ++ AU_MVD_PR(dmsg, "no lower brid\n"); ++ goto out; ++ } ++ } ++ ++ err = au_mvd_args_busy(dmsg, a); ++ if (!err) ++ err = au_mvd_args_parent(dmsg, a); ++ if (!err) ++ err = au_mvd_args_intermediate(dmsg, a); ++ if (!err) ++ err = au_mvd_args_exist(dmsg, a); ++ if (!err) ++ AuDbg("b%d, b%d\n", a->mvd_bsrc, a->mvd_bdst); ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++int au_mvdown(struct dentry *dentry, struct aufs_mvdown __user *uarg) ++{ ++ int err, e; ++ unsigned char dmsg; ++ struct au_mvd_args *args; ++ struct inode *inode; ++ ++ inode = d_inode(dentry); ++ err = -EPERM; ++ if (unlikely(!capable(CAP_SYS_ADMIN))) ++ goto out; ++ ++ err = -ENOMEM; ++ args = kmalloc(sizeof(*args), GFP_NOFS); ++ if (unlikely(!args)) ++ goto out; ++ ++ err = copy_from_user(&args->mvdown, uarg, sizeof(args->mvdown)); ++ if (!err) ++ /* VERIFY_WRITE */ ++ err = !access_ok(uarg, sizeof(*uarg)); ++ if (unlikely(err)) { ++ err = -EFAULT; ++ AuTraceErr(err); ++ goto out_free; ++ } ++ AuDbg("flags 0x%x\n", args->mvdown.flags); ++ args->mvdown.flags &= ~(AUFS_MVDOWN_ROLOWER_R | AUFS_MVDOWN_ROUPPER_R); ++ args->mvdown.au_errno = 0; ++ args->dentry = dentry; ++ args->inode = inode; ++ args->sb = dentry->d_sb; ++ ++ err = -ENOENT; ++ dmsg = !!(args->mvdown.flags & AUFS_MVDOWN_DMSG); ++ args->parent = dget_parent(dentry); ++ args->dir = d_inode(args->parent); ++ inode_lock_nested(args->dir, I_MUTEX_PARENT); ++ dput(args->parent); ++ if (unlikely(args->parent != dentry->d_parent)) { ++ AU_MVD_PR(dmsg, "parent dir is moved\n"); ++ goto out_dir; ++ } ++ ++ inode_lock_nested(inode, I_MUTEX_CHILD); ++ err = aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH | AuLock_NOPLMW); ++ if (unlikely(err)) ++ goto out_inode; ++ ++ di_write_lock_parent(args->parent); ++ err = au_mvd_args(dmsg, args); ++ if (unlikely(err)) ++ goto out_parent; ++ ++ err = au_do_mvdown(dmsg, args); ++ if (unlikely(err)) ++ goto out_parent; ++ ++ au_cpup_attr_timesizes(args->dir); ++ au_cpup_attr_timesizes(inode); ++ if (!(args->mvdown.flags & AUFS_MVDOWN_KUPPER)) ++ au_cpup_igen(inode, au_h_iptr(inode, args->mvd_bdst)); ++ /* au_digen_dec(dentry); */ ++ ++out_parent: ++ di_write_unlock(args->parent); ++ aufs_read_unlock(dentry, AuLock_DW); ++out_inode: ++ inode_unlock(inode); ++out_dir: ++ inode_unlock(args->dir); ++out_free: ++ e = copy_to_user(uarg, &args->mvdown, sizeof(args->mvdown)); ++ if (unlikely(e)) ++ err = -EFAULT; ++ au_kfree_rcu(args); ++out: ++ AuTraceErr(err); ++ return err; ++} +diff -Nurp linux-5.4/fs/aufs/opts.c linux-5.4-aufs/fs/aufs/opts.c +--- linux-5.4/fs/aufs/opts.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/opts.c 2019-11-28 01:25:59.067925618 +0200 +@@ -0,0 +1,1867 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * mount options/flags ++ */ ++ ++#include ++#include /* a distribution requires */ ++#include ++#include "aufs.h" ++ ++/* ---------------------------------------------------------------------- */ ++ ++enum { ++ Opt_br, ++ Opt_add, Opt_del, Opt_mod, Opt_append, Opt_prepend, ++ Opt_idel, Opt_imod, ++ Opt_dirwh, Opt_rdcache, Opt_rdblk, Opt_rdhash, ++ Opt_rdblk_def, Opt_rdhash_def, ++ Opt_xino, Opt_noxino, ++ Opt_trunc_xino, Opt_trunc_xino_v, Opt_notrunc_xino, ++ Opt_trunc_xino_path, Opt_itrunc_xino, ++ Opt_trunc_xib, Opt_notrunc_xib, ++ Opt_shwh, Opt_noshwh, ++ Opt_plink, Opt_noplink, Opt_list_plink, ++ Opt_udba, ++ Opt_dio, Opt_nodio, ++ Opt_diropq_a, Opt_diropq_w, ++ Opt_warn_perm, Opt_nowarn_perm, ++ Opt_wbr_copyup, Opt_wbr_create, ++ Opt_fhsm_sec, ++ Opt_verbose, Opt_noverbose, ++ Opt_sum, Opt_nosum, Opt_wsum, ++ Opt_dirperm1, Opt_nodirperm1, ++ Opt_dirren, Opt_nodirren, ++ Opt_acl, Opt_noacl, ++ Opt_tail, Opt_ignore, Opt_ignore_silent, Opt_err ++}; ++ ++static match_table_t options = { ++ {Opt_br, "br=%s"}, ++ {Opt_br, "br:%s"}, ++ ++ {Opt_add, "add=%d:%s"}, ++ {Opt_add, "add:%d:%s"}, ++ {Opt_add, "ins=%d:%s"}, ++ {Opt_add, "ins:%d:%s"}, ++ {Opt_append, "append=%s"}, ++ {Opt_append, "append:%s"}, ++ {Opt_prepend, "prepend=%s"}, ++ {Opt_prepend, "prepend:%s"}, ++ ++ {Opt_del, "del=%s"}, ++ {Opt_del, "del:%s"}, ++ /* {Opt_idel, "idel:%d"}, */ ++ {Opt_mod, "mod=%s"}, ++ {Opt_mod, "mod:%s"}, ++ /* {Opt_imod, "imod:%d:%s"}, */ ++ ++ {Opt_dirwh, "dirwh=%d"}, ++ ++ {Opt_xino, "xino=%s"}, ++ {Opt_noxino, "noxino"}, ++ {Opt_trunc_xino, "trunc_xino"}, ++ {Opt_trunc_xino_v, "trunc_xino_v=%d:%d"}, ++ {Opt_notrunc_xino, "notrunc_xino"}, ++ {Opt_trunc_xino_path, "trunc_xino=%s"}, ++ {Opt_itrunc_xino, "itrunc_xino=%d"}, ++ /* {Opt_zxino, "zxino=%s"}, */ ++ {Opt_trunc_xib, "trunc_xib"}, ++ {Opt_notrunc_xib, "notrunc_xib"}, ++ ++#ifdef CONFIG_PROC_FS ++ {Opt_plink, "plink"}, ++#else ++ {Opt_ignore_silent, "plink"}, ++#endif ++ ++ {Opt_noplink, "noplink"}, ++ ++#ifdef CONFIG_AUFS_DEBUG ++ {Opt_list_plink, "list_plink"}, ++#endif ++ ++ {Opt_udba, "udba=%s"}, ++ ++ {Opt_dio, "dio"}, ++ {Opt_nodio, "nodio"}, ++ ++#ifdef CONFIG_AUFS_DIRREN ++ {Opt_dirren, "dirren"}, ++ {Opt_nodirren, "nodirren"}, ++#else ++ {Opt_ignore, "dirren"}, ++ {Opt_ignore_silent, "nodirren"}, ++#endif ++ ++#ifdef CONFIG_AUFS_FHSM ++ {Opt_fhsm_sec, "fhsm_sec=%d"}, ++#else ++ {Opt_ignore, "fhsm_sec=%d"}, ++#endif ++ ++ {Opt_diropq_a, "diropq=always"}, ++ {Opt_diropq_a, "diropq=a"}, ++ {Opt_diropq_w, "diropq=whiteouted"}, ++ {Opt_diropq_w, "diropq=w"}, ++ ++ {Opt_warn_perm, "warn_perm"}, ++ {Opt_nowarn_perm, "nowarn_perm"}, ++ ++ /* keep them temporary */ ++ {Opt_ignore_silent, "nodlgt"}, ++ {Opt_ignore, "clean_plink"}, ++ ++#ifdef CONFIG_AUFS_SHWH ++ {Opt_shwh, "shwh"}, ++#endif ++ {Opt_noshwh, "noshwh"}, ++ ++ {Opt_dirperm1, "dirperm1"}, ++ {Opt_nodirperm1, "nodirperm1"}, ++ ++ {Opt_verbose, "verbose"}, ++ {Opt_verbose, "v"}, ++ {Opt_noverbose, "noverbose"}, ++ {Opt_noverbose, "quiet"}, ++ {Opt_noverbose, "q"}, ++ {Opt_noverbose, "silent"}, ++ ++ {Opt_sum, "sum"}, ++ {Opt_nosum, "nosum"}, ++ {Opt_wsum, "wsum"}, ++ ++ {Opt_rdcache, "rdcache=%d"}, ++ {Opt_rdblk, "rdblk=%d"}, ++ {Opt_rdblk_def, "rdblk=def"}, ++ {Opt_rdhash, "rdhash=%d"}, ++ {Opt_rdhash_def, "rdhash=def"}, ++ ++ {Opt_wbr_create, "create=%s"}, ++ {Opt_wbr_create, "create_policy=%s"}, ++ {Opt_wbr_copyup, "cpup=%s"}, ++ {Opt_wbr_copyup, "copyup=%s"}, ++ {Opt_wbr_copyup, "copyup_policy=%s"}, ++ ++ /* generic VFS flag */ ++#ifdef CONFIG_FS_POSIX_ACL ++ {Opt_acl, "acl"}, ++ {Opt_noacl, "noacl"}, ++#else ++ {Opt_ignore, "acl"}, ++ {Opt_ignore_silent, "noacl"}, ++#endif ++ ++ /* internal use for the scripts */ ++ {Opt_ignore_silent, "si=%s"}, ++ ++ {Opt_br, "dirs=%s"}, ++ {Opt_ignore, "debug=%d"}, ++ {Opt_ignore, "delete=whiteout"}, ++ {Opt_ignore, "delete=all"}, ++ {Opt_ignore, "imap=%s"}, ++ ++ /* temporary workaround, due to old mount(8)? */ ++ {Opt_ignore_silent, "relatime"}, ++ ++ {Opt_err, NULL} ++}; ++ ++/* ---------------------------------------------------------------------- */ ++ ++static const char *au_parser_pattern(int val, match_table_t tbl) ++{ ++ struct match_token *p; ++ ++ p = tbl; ++ while (p->pattern) { ++ if (p->token == val) ++ return p->pattern; ++ p++; ++ } ++ BUG(); ++ return "??"; ++} ++ ++static const char *au_optstr(int *val, match_table_t tbl) ++{ ++ struct match_token *p; ++ int v; ++ ++ v = *val; ++ if (!v) ++ goto out; ++ p = tbl; ++ while (p->pattern) { ++ if (p->token ++ && (v & p->token) == p->token) { ++ *val &= ~p->token; ++ return p->pattern; ++ } ++ p++; ++ } ++ ++out: ++ return NULL; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static match_table_t brperm = { ++ {AuBrPerm_RO, AUFS_BRPERM_RO}, ++ {AuBrPerm_RR, AUFS_BRPERM_RR}, ++ {AuBrPerm_RW, AUFS_BRPERM_RW}, ++ {0, NULL} ++}; ++ ++static match_table_t brattr = { ++ /* general */ ++ {AuBrAttr_COO_REG, AUFS_BRATTR_COO_REG}, ++ {AuBrAttr_COO_ALL, AUFS_BRATTR_COO_ALL}, ++ /* 'unpin' attrib is meaningless since linux-3.18-rc1 */ ++ {AuBrAttr_UNPIN, AUFS_BRATTR_UNPIN}, ++#ifdef CONFIG_AUFS_FHSM ++ {AuBrAttr_FHSM, AUFS_BRATTR_FHSM}, ++#endif ++#ifdef CONFIG_AUFS_XATTR ++ {AuBrAttr_ICEX, AUFS_BRATTR_ICEX}, ++ {AuBrAttr_ICEX_SEC, AUFS_BRATTR_ICEX_SEC}, ++ {AuBrAttr_ICEX_SYS, AUFS_BRATTR_ICEX_SYS}, ++ {AuBrAttr_ICEX_TR, AUFS_BRATTR_ICEX_TR}, ++ {AuBrAttr_ICEX_USR, AUFS_BRATTR_ICEX_USR}, ++ {AuBrAttr_ICEX_OTH, AUFS_BRATTR_ICEX_OTH}, ++#endif ++ ++ /* ro/rr branch */ ++ {AuBrRAttr_WH, AUFS_BRRATTR_WH}, ++ ++ /* rw branch */ ++ {AuBrWAttr_MOO, AUFS_BRWATTR_MOO}, ++ {AuBrWAttr_NoLinkWH, AUFS_BRWATTR_NLWH}, ++ ++ {0, NULL} ++}; ++ ++static int br_attr_val(char *str, match_table_t table, substring_t args[]) ++{ ++ int attr, v; ++ char *p; ++ ++ attr = 0; ++ do { ++ p = strchr(str, '+'); ++ if (p) ++ *p = 0; ++ v = match_token(str, table, args); ++ if (v) { ++ if (v & AuBrAttr_CMOO_Mask) ++ attr &= ~AuBrAttr_CMOO_Mask; ++ attr |= v; ++ } else { ++ if (p) ++ *p = '+'; ++ pr_warn("ignored branch attribute %s\n", str); ++ break; ++ } ++ if (p) ++ str = p + 1; ++ } while (p); ++ ++ return attr; ++} ++ ++static int au_do_optstr_br_attr(au_br_perm_str_t *str, int perm) ++{ ++ int sz; ++ const char *p; ++ char *q; ++ ++ q = str->a; ++ *q = 0; ++ p = au_optstr(&perm, brattr); ++ if (p) { ++ sz = strlen(p); ++ memcpy(q, p, sz + 1); ++ q += sz; ++ } else ++ goto out; ++ ++ do { ++ p = au_optstr(&perm, brattr); ++ if (p) { ++ *q++ = '+'; ++ sz = strlen(p); ++ memcpy(q, p, sz + 1); ++ q += sz; ++ } ++ } while (p); ++ ++out: ++ return q - str->a; ++} ++ ++static int noinline_for_stack br_perm_val(char *perm) ++{ ++ int val, bad, sz; ++ char *p; ++ substring_t args[MAX_OPT_ARGS]; ++ au_br_perm_str_t attr; ++ ++ p = strchr(perm, '+'); ++ if (p) ++ *p = 0; ++ val = match_token(perm, brperm, args); ++ if (!val) { ++ if (p) ++ *p = '+'; ++ pr_warn("ignored branch permission %s\n", perm); ++ val = AuBrPerm_RO; ++ goto out; ++ } ++ if (!p) ++ goto out; ++ ++ val |= br_attr_val(p + 1, brattr, args); ++ ++ bad = 0; ++ switch (val & AuBrPerm_Mask) { ++ case AuBrPerm_RO: ++ case AuBrPerm_RR: ++ bad = val & AuBrWAttr_Mask; ++ val &= ~AuBrWAttr_Mask; ++ break; ++ case AuBrPerm_RW: ++ bad = val & AuBrRAttr_Mask; ++ val &= ~AuBrRAttr_Mask; ++ break; ++ } ++ ++ /* ++ * 'unpin' attrib becomes meaningless since linux-3.18-rc1, but aufs ++ * does not treat it as an error, just warning. ++ * this is a tiny guard for the user operation. ++ */ ++ if (val & AuBrAttr_UNPIN) { ++ bad |= AuBrAttr_UNPIN; ++ val &= ~AuBrAttr_UNPIN; ++ } ++ ++ if (unlikely(bad)) { ++ sz = au_do_optstr_br_attr(&attr, bad); ++ AuDebugOn(!sz); ++ pr_warn("ignored branch attribute %s\n", attr.a); ++ } ++ ++out: ++ return val; ++} ++ ++void au_optstr_br_perm(au_br_perm_str_t *str, int perm) ++{ ++ au_br_perm_str_t attr; ++ const char *p; ++ char *q; ++ int sz; ++ ++ q = str->a; ++ p = au_optstr(&perm, brperm); ++ AuDebugOn(!p || !*p); ++ sz = strlen(p); ++ memcpy(q, p, sz + 1); ++ q += sz; ++ ++ sz = au_do_optstr_br_attr(&attr, perm); ++ if (sz) { ++ *q++ = '+'; ++ memcpy(q, attr.a, sz + 1); ++ } ++ ++ AuDebugOn(strlen(str->a) >= sizeof(str->a)); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static match_table_t udbalevel = { ++ {AuOpt_UDBA_REVAL, "reval"}, ++ {AuOpt_UDBA_NONE, "none"}, ++#ifdef CONFIG_AUFS_HNOTIFY ++ {AuOpt_UDBA_HNOTIFY, "notify"}, /* abstraction */ ++#ifdef CONFIG_AUFS_HFSNOTIFY ++ {AuOpt_UDBA_HNOTIFY, "fsnotify"}, ++#endif ++#endif ++ {-1, NULL} ++}; ++ ++static int noinline_for_stack udba_val(char *str) ++{ ++ substring_t args[MAX_OPT_ARGS]; ++ ++ return match_token(str, udbalevel, args); ++} ++ ++const char *au_optstr_udba(int udba) ++{ ++ return au_parser_pattern(udba, udbalevel); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static match_table_t au_wbr_create_policy = { ++ {AuWbrCreate_TDP, "tdp"}, ++ {AuWbrCreate_TDP, "top-down-parent"}, ++ {AuWbrCreate_RR, "rr"}, ++ {AuWbrCreate_RR, "round-robin"}, ++ {AuWbrCreate_MFS, "mfs"}, ++ {AuWbrCreate_MFS, "most-free-space"}, ++ {AuWbrCreate_MFSV, "mfs:%d"}, ++ {AuWbrCreate_MFSV, "most-free-space:%d"}, ++ ++ /* top-down regardless the parent, and then mfs */ ++ {AuWbrCreate_TDMFS, "tdmfs:%d"}, ++ {AuWbrCreate_TDMFSV, "tdmfs:%d:%d"}, ++ ++ {AuWbrCreate_MFSRR, "mfsrr:%d"}, ++ {AuWbrCreate_MFSRRV, "mfsrr:%d:%d"}, ++ {AuWbrCreate_PMFS, "pmfs"}, ++ {AuWbrCreate_PMFSV, "pmfs:%d"}, ++ {AuWbrCreate_PMFSRR, "pmfsrr:%d"}, ++ {AuWbrCreate_PMFSRRV, "pmfsrr:%d:%d"}, ++ ++ {-1, NULL} ++}; ++ ++static int au_wbr_mfs_wmark(substring_t *arg, char *str, ++ struct au_opt_wbr_create *create) ++{ ++ int err; ++ unsigned long long ull; ++ ++ err = 0; ++ if (!match_u64(arg, &ull)) ++ create->mfsrr_watermark = ull; ++ else { ++ pr_err("bad integer in %s\n", str); ++ err = -EINVAL; ++ } ++ ++ return err; ++} ++ ++static int au_wbr_mfs_sec(substring_t *arg, char *str, ++ struct au_opt_wbr_create *create) ++{ ++ int n, err; ++ ++ err = 0; ++ if (!match_int(arg, &n) && 0 <= n && n <= AUFS_MFS_MAX_SEC) ++ create->mfs_second = n; ++ else { ++ pr_err("bad integer in %s\n", str); ++ err = -EINVAL; ++ } ++ ++ return err; ++} ++ ++static int noinline_for_stack ++au_wbr_create_val(char *str, struct au_opt_wbr_create *create) ++{ ++ int err, e; ++ substring_t args[MAX_OPT_ARGS]; ++ ++ err = match_token(str, au_wbr_create_policy, args); ++ create->wbr_create = err; ++ switch (err) { ++ case AuWbrCreate_MFSRRV: ++ case AuWbrCreate_TDMFSV: ++ case AuWbrCreate_PMFSRRV: ++ e = au_wbr_mfs_wmark(&args[0], str, create); ++ if (!e) ++ e = au_wbr_mfs_sec(&args[1], str, create); ++ if (unlikely(e)) ++ err = e; ++ break; ++ case AuWbrCreate_MFSRR: ++ case AuWbrCreate_TDMFS: ++ case AuWbrCreate_PMFSRR: ++ e = au_wbr_mfs_wmark(&args[0], str, create); ++ if (unlikely(e)) { ++ err = e; ++ break; ++ } ++ /*FALLTHROUGH*/ ++ case AuWbrCreate_MFS: ++ case AuWbrCreate_PMFS: ++ create->mfs_second = AUFS_MFS_DEF_SEC; ++ break; ++ case AuWbrCreate_MFSV: ++ case AuWbrCreate_PMFSV: ++ e = au_wbr_mfs_sec(&args[0], str, create); ++ if (unlikely(e)) ++ err = e; ++ break; ++ } ++ ++ return err; ++} ++ ++const char *au_optstr_wbr_create(int wbr_create) ++{ ++ return au_parser_pattern(wbr_create, au_wbr_create_policy); ++} ++ ++static match_table_t au_wbr_copyup_policy = { ++ {AuWbrCopyup_TDP, "tdp"}, ++ {AuWbrCopyup_TDP, "top-down-parent"}, ++ {AuWbrCopyup_BUP, "bup"}, ++ {AuWbrCopyup_BUP, "bottom-up-parent"}, ++ {AuWbrCopyup_BU, "bu"}, ++ {AuWbrCopyup_BU, "bottom-up"}, ++ {-1, NULL} ++}; ++ ++static int noinline_for_stack au_wbr_copyup_val(char *str) ++{ ++ substring_t args[MAX_OPT_ARGS]; ++ ++ return match_token(str, au_wbr_copyup_policy, args); ++} ++ ++const char *au_optstr_wbr_copyup(int wbr_copyup) ++{ ++ return au_parser_pattern(wbr_copyup, au_wbr_copyup_policy); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static const int lkup_dirflags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY; ++ ++static void dump_opts(struct au_opts *opts) ++{ ++#ifdef CONFIG_AUFS_DEBUG ++ /* reduce stack space */ ++ union { ++ struct au_opt_add *add; ++ struct au_opt_del *del; ++ struct au_opt_mod *mod; ++ struct au_opt_xino *xino; ++ struct au_opt_xino_itrunc *xino_itrunc; ++ struct au_opt_wbr_create *create; ++ } u; ++ struct au_opt *opt; ++ ++ opt = opts->opt; ++ while (opt->type != Opt_tail) { ++ switch (opt->type) { ++ case Opt_add: ++ u.add = &opt->add; ++ AuDbg("add {b%d, %s, 0x%x, %p}\n", ++ u.add->bindex, u.add->pathname, u.add->perm, ++ u.add->path.dentry); ++ break; ++ case Opt_del: ++ case Opt_idel: ++ u.del = &opt->del; ++ AuDbg("del {%s, %p}\n", ++ u.del->pathname, u.del->h_path.dentry); ++ break; ++ case Opt_mod: ++ case Opt_imod: ++ u.mod = &opt->mod; ++ AuDbg("mod {%s, 0x%x, %p}\n", ++ u.mod->path, u.mod->perm, u.mod->h_root); ++ break; ++ case Opt_append: ++ u.add = &opt->add; ++ AuDbg("append {b%d, %s, 0x%x, %p}\n", ++ u.add->bindex, u.add->pathname, u.add->perm, ++ u.add->path.dentry); ++ break; ++ case Opt_prepend: ++ u.add = &opt->add; ++ AuDbg("prepend {b%d, %s, 0x%x, %p}\n", ++ u.add->bindex, u.add->pathname, u.add->perm, ++ u.add->path.dentry); ++ break; ++ case Opt_dirwh: ++ AuDbg("dirwh %d\n", opt->dirwh); ++ break; ++ case Opt_rdcache: ++ AuDbg("rdcache %d\n", opt->rdcache); ++ break; ++ case Opt_rdblk: ++ AuDbg("rdblk %u\n", opt->rdblk); ++ break; ++ case Opt_rdblk_def: ++ AuDbg("rdblk_def\n"); ++ break; ++ case Opt_rdhash: ++ AuDbg("rdhash %u\n", opt->rdhash); ++ break; ++ case Opt_rdhash_def: ++ AuDbg("rdhash_def\n"); ++ break; ++ case Opt_xino: ++ u.xino = &opt->xino; ++ AuDbg("xino {%s %pD}\n", u.xino->path, u.xino->file); ++ break; ++ case Opt_trunc_xino: ++ AuLabel(trunc_xino); ++ break; ++ case Opt_notrunc_xino: ++ AuLabel(notrunc_xino); ++ break; ++ case Opt_trunc_xino_path: ++ case Opt_itrunc_xino: ++ u.xino_itrunc = &opt->xino_itrunc; ++ AuDbg("trunc_xino %d\n", u.xino_itrunc->bindex); ++ break; ++ case Opt_noxino: ++ AuLabel(noxino); ++ break; ++ case Opt_trunc_xib: ++ AuLabel(trunc_xib); ++ break; ++ case Opt_notrunc_xib: ++ AuLabel(notrunc_xib); ++ break; ++ case Opt_shwh: ++ AuLabel(shwh); ++ break; ++ case Opt_noshwh: ++ AuLabel(noshwh); ++ break; ++ case Opt_dirperm1: ++ AuLabel(dirperm1); ++ break; ++ case Opt_nodirperm1: ++ AuLabel(nodirperm1); ++ break; ++ case Opt_plink: ++ AuLabel(plink); ++ break; ++ case Opt_noplink: ++ AuLabel(noplink); ++ break; ++ case Opt_list_plink: ++ AuLabel(list_plink); ++ break; ++ case Opt_udba: ++ AuDbg("udba %d, %s\n", ++ opt->udba, au_optstr_udba(opt->udba)); ++ break; ++ case Opt_dio: ++ AuLabel(dio); ++ break; ++ case Opt_nodio: ++ AuLabel(nodio); ++ break; ++ case Opt_diropq_a: ++ AuLabel(diropq_a); ++ break; ++ case Opt_diropq_w: ++ AuLabel(diropq_w); ++ break; ++ case Opt_warn_perm: ++ AuLabel(warn_perm); ++ break; ++ case Opt_nowarn_perm: ++ AuLabel(nowarn_perm); ++ break; ++ case Opt_verbose: ++ AuLabel(verbose); ++ break; ++ case Opt_noverbose: ++ AuLabel(noverbose); ++ break; ++ case Opt_sum: ++ AuLabel(sum); ++ break; ++ case Opt_nosum: ++ AuLabel(nosum); ++ break; ++ case Opt_wsum: ++ AuLabel(wsum); ++ break; ++ case Opt_wbr_create: ++ u.create = &opt->wbr_create; ++ AuDbg("create %d, %s\n", u.create->wbr_create, ++ au_optstr_wbr_create(u.create->wbr_create)); ++ switch (u.create->wbr_create) { ++ case AuWbrCreate_MFSV: ++ case AuWbrCreate_PMFSV: ++ AuDbg("%d sec\n", u.create->mfs_second); ++ break; ++ case AuWbrCreate_MFSRR: ++ case AuWbrCreate_TDMFS: ++ AuDbg("%llu watermark\n", ++ u.create->mfsrr_watermark); ++ break; ++ case AuWbrCreate_MFSRRV: ++ case AuWbrCreate_TDMFSV: ++ case AuWbrCreate_PMFSRRV: ++ AuDbg("%llu watermark, %d sec\n", ++ u.create->mfsrr_watermark, ++ u.create->mfs_second); ++ break; ++ } ++ break; ++ case Opt_wbr_copyup: ++ AuDbg("copyup %d, %s\n", opt->wbr_copyup, ++ au_optstr_wbr_copyup(opt->wbr_copyup)); ++ break; ++ case Opt_fhsm_sec: ++ AuDbg("fhsm_sec %u\n", opt->fhsm_second); ++ break; ++ case Opt_dirren: ++ AuLabel(dirren); ++ break; ++ case Opt_nodirren: ++ AuLabel(nodirren); ++ break; ++ case Opt_acl: ++ AuLabel(acl); ++ break; ++ case Opt_noacl: ++ AuLabel(noacl); ++ break; ++ default: ++ BUG(); ++ } ++ opt++; ++ } ++#endif ++} ++ ++void au_opts_free(struct au_opts *opts) ++{ ++ struct au_opt *opt; ++ ++ opt = opts->opt; ++ while (opt->type != Opt_tail) { ++ switch (opt->type) { ++ case Opt_add: ++ case Opt_append: ++ case Opt_prepend: ++ path_put(&opt->add.path); ++ break; ++ case Opt_del: ++ case Opt_idel: ++ path_put(&opt->del.h_path); ++ break; ++ case Opt_mod: ++ case Opt_imod: ++ dput(opt->mod.h_root); ++ break; ++ case Opt_xino: ++ fput(opt->xino.file); ++ break; ++ } ++ opt++; ++ } ++} ++ ++static int opt_add(struct au_opt *opt, char *opt_str, unsigned long sb_flags, ++ aufs_bindex_t bindex) ++{ ++ int err; ++ struct au_opt_add *add = &opt->add; ++ char *p; ++ ++ add->bindex = bindex; ++ add->perm = AuBrPerm_RO; ++ add->pathname = opt_str; ++ p = strchr(opt_str, '='); ++ if (p) { ++ *p++ = 0; ++ if (*p) ++ add->perm = br_perm_val(p); ++ } ++ ++ err = vfsub_kern_path(add->pathname, lkup_dirflags, &add->path); ++ if (!err) { ++ if (!p) { ++ add->perm = AuBrPerm_RO; ++ if (au_test_fs_rr(add->path.dentry->d_sb)) ++ add->perm = AuBrPerm_RR; ++ else if (!bindex && !(sb_flags & SB_RDONLY)) ++ add->perm = AuBrPerm_RW; ++ } ++ opt->type = Opt_add; ++ goto out; ++ } ++ pr_err("lookup failed %s (%d)\n", add->pathname, err); ++ err = -EINVAL; ++ ++out: ++ return err; ++} ++ ++static int au_opts_parse_del(struct au_opt_del *del, substring_t args[]) ++{ ++ int err; ++ ++ del->pathname = args[0].from; ++ AuDbg("del path %s\n", del->pathname); ++ ++ err = vfsub_kern_path(del->pathname, lkup_dirflags, &del->h_path); ++ if (unlikely(err)) ++ pr_err("lookup failed %s (%d)\n", del->pathname, err); ++ ++ return err; ++} ++ ++#if 0 /* reserved for future use */ ++static int au_opts_parse_idel(struct super_block *sb, aufs_bindex_t bindex, ++ struct au_opt_del *del, substring_t args[]) ++{ ++ int err; ++ struct dentry *root; ++ ++ err = -EINVAL; ++ root = sb->s_root; ++ aufs_read_lock(root, AuLock_FLUSH); ++ if (bindex < 0 || au_sbbot(sb) < bindex) { ++ pr_err("out of bounds, %d\n", bindex); ++ goto out; ++ } ++ ++ err = 0; ++ del->h_path.dentry = dget(au_h_dptr(root, bindex)); ++ del->h_path.mnt = mntget(au_sbr_mnt(sb, bindex)); ++ ++out: ++ aufs_read_unlock(root, !AuLock_IR); ++ return err; ++} ++#endif ++ ++static int noinline_for_stack ++au_opts_parse_mod(struct au_opt_mod *mod, substring_t args[]) ++{ ++ int err; ++ struct path path; ++ char *p; ++ ++ err = -EINVAL; ++ mod->path = args[0].from; ++ p = strchr(mod->path, '='); ++ if (unlikely(!p)) { ++ pr_err("no permission %s\n", args[0].from); ++ goto out; ++ } ++ ++ *p++ = 0; ++ err = vfsub_kern_path(mod->path, lkup_dirflags, &path); ++ if (unlikely(err)) { ++ pr_err("lookup failed %s (%d)\n", mod->path, err); ++ goto out; ++ } ++ ++ mod->perm = br_perm_val(p); ++ AuDbg("mod path %s, perm 0x%x, %s\n", mod->path, mod->perm, p); ++ mod->h_root = dget(path.dentry); ++ path_put(&path); ++ ++out: ++ return err; ++} ++ ++#if 0 /* reserved for future use */ ++static int au_opts_parse_imod(struct super_block *sb, aufs_bindex_t bindex, ++ struct au_opt_mod *mod, substring_t args[]) ++{ ++ int err; ++ struct dentry *root; ++ ++ err = -EINVAL; ++ root = sb->s_root; ++ aufs_read_lock(root, AuLock_FLUSH); ++ if (bindex < 0 || au_sbbot(sb) < bindex) { ++ pr_err("out of bounds, %d\n", bindex); ++ goto out; ++ } ++ ++ err = 0; ++ mod->perm = br_perm_val(args[1].from); ++ AuDbg("mod path %s, perm 0x%x, %s\n", ++ mod->path, mod->perm, args[1].from); ++ mod->h_root = dget(au_h_dptr(root, bindex)); ++ ++out: ++ aufs_read_unlock(root, !AuLock_IR); ++ return err; ++} ++#endif ++ ++static int au_opts_parse_xino(struct super_block *sb, struct au_opt_xino *xino, ++ substring_t args[]) ++{ ++ int err; ++ struct file *file; ++ ++ file = au_xino_create(sb, args[0].from, /*silent*/0, /*wbrtop*/0); ++ err = PTR_ERR(file); ++ if (IS_ERR(file)) ++ goto out; ++ ++ err = -EINVAL; ++ if (unlikely(file->f_path.dentry->d_sb == sb)) { ++ fput(file); ++ pr_err("%s must be outside\n", args[0].from); ++ goto out; ++ } ++ ++ err = 0; ++ xino->file = file; ++ xino->path = args[0].from; ++ ++out: ++ return err; ++} ++ ++static int noinline_for_stack ++au_opts_parse_xino_itrunc_path(struct super_block *sb, ++ struct au_opt_xino_itrunc *xino_itrunc, ++ substring_t args[]) ++{ ++ int err; ++ aufs_bindex_t bbot, bindex; ++ struct path path; ++ struct dentry *root; ++ ++ err = vfsub_kern_path(args[0].from, lkup_dirflags, &path); ++ if (unlikely(err)) { ++ pr_err("lookup failed %s (%d)\n", args[0].from, err); ++ goto out; ++ } ++ ++ xino_itrunc->bindex = -1; ++ root = sb->s_root; ++ aufs_read_lock(root, AuLock_FLUSH); ++ bbot = au_sbbot(sb); ++ for (bindex = 0; bindex <= bbot; bindex++) { ++ if (au_h_dptr(root, bindex) == path.dentry) { ++ xino_itrunc->bindex = bindex; ++ break; ++ } ++ } ++ aufs_read_unlock(root, !AuLock_IR); ++ path_put(&path); ++ ++ if (unlikely(xino_itrunc->bindex < 0)) { ++ pr_err("no such branch %s\n", args[0].from); ++ err = -EINVAL; ++ } ++ ++out: ++ return err; ++} ++ ++/* called without aufs lock */ ++int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts) ++{ ++ int err, n, token; ++ aufs_bindex_t bindex; ++ unsigned char skipped; ++ struct dentry *root; ++ struct au_opt *opt, *opt_tail; ++ char *opt_str; ++ /* reduce the stack space */ ++ union { ++ struct au_opt_xino_itrunc *xino_itrunc; ++ struct au_opt_wbr_create *create; ++ } u; ++ struct { ++ substring_t args[MAX_OPT_ARGS]; ++ } *a; ++ ++ err = -ENOMEM; ++ a = kmalloc(sizeof(*a), GFP_NOFS); ++ if (unlikely(!a)) ++ goto out; ++ ++ root = sb->s_root; ++ err = 0; ++ bindex = 0; ++ opt = opts->opt; ++ opt_tail = opt + opts->max_opt - 1; ++ opt->type = Opt_tail; ++ while (!err && (opt_str = strsep(&str, ",")) && *opt_str) { ++ err = -EINVAL; ++ skipped = 0; ++ token = match_token(opt_str, options, a->args); ++ switch (token) { ++ case Opt_br: ++ err = 0; ++ while (!err && (opt_str = strsep(&a->args[0].from, ":")) ++ && *opt_str) { ++ err = opt_add(opt, opt_str, opts->sb_flags, ++ bindex++); ++ if (unlikely(!err && ++opt > opt_tail)) { ++ err = -E2BIG; ++ break; ++ } ++ opt->type = Opt_tail; ++ skipped = 1; ++ } ++ break; ++ case Opt_add: ++ if (unlikely(match_int(&a->args[0], &n))) { ++ pr_err("bad integer in %s\n", opt_str); ++ break; ++ } ++ bindex = n; ++ err = opt_add(opt, a->args[1].from, opts->sb_flags, ++ bindex); ++ if (!err) ++ opt->type = token; ++ break; ++ case Opt_append: ++ err = opt_add(opt, a->args[0].from, opts->sb_flags, ++ /*dummy bindex*/1); ++ if (!err) ++ opt->type = token; ++ break; ++ case Opt_prepend: ++ err = opt_add(opt, a->args[0].from, opts->sb_flags, ++ /*bindex*/0); ++ if (!err) ++ opt->type = token; ++ break; ++ case Opt_del: ++ err = au_opts_parse_del(&opt->del, a->args); ++ if (!err) ++ opt->type = token; ++ break; ++#if 0 /* reserved for future use */ ++ case Opt_idel: ++ del->pathname = "(indexed)"; ++ if (unlikely(match_int(&args[0], &n))) { ++ pr_err("bad integer in %s\n", opt_str); ++ break; ++ } ++ err = au_opts_parse_idel(sb, n, &opt->del, a->args); ++ if (!err) ++ opt->type = token; ++ break; ++#endif ++ case Opt_mod: ++ err = au_opts_parse_mod(&opt->mod, a->args); ++ if (!err) ++ opt->type = token; ++ break; ++#ifdef IMOD /* reserved for future use */ ++ case Opt_imod: ++ u.mod->path = "(indexed)"; ++ if (unlikely(match_int(&a->args[0], &n))) { ++ pr_err("bad integer in %s\n", opt_str); ++ break; ++ } ++ err = au_opts_parse_imod(sb, n, &opt->mod, a->args); ++ if (!err) ++ opt->type = token; ++ break; ++#endif ++ case Opt_xino: ++ err = au_opts_parse_xino(sb, &opt->xino, a->args); ++ if (!err) ++ opt->type = token; ++ break; ++ ++ case Opt_trunc_xino_path: ++ err = au_opts_parse_xino_itrunc_path ++ (sb, &opt->xino_itrunc, a->args); ++ if (!err) ++ opt->type = token; ++ break; ++ ++ case Opt_itrunc_xino: ++ u.xino_itrunc = &opt->xino_itrunc; ++ if (unlikely(match_int(&a->args[0], &n))) { ++ pr_err("bad integer in %s\n", opt_str); ++ break; ++ } ++ u.xino_itrunc->bindex = n; ++ aufs_read_lock(root, AuLock_FLUSH); ++ if (n < 0 || au_sbbot(sb) < n) { ++ pr_err("out of bounds, %d\n", n); ++ aufs_read_unlock(root, !AuLock_IR); ++ break; ++ } ++ aufs_read_unlock(root, !AuLock_IR); ++ err = 0; ++ opt->type = token; ++ break; ++ ++ case Opt_dirwh: ++ if (unlikely(match_int(&a->args[0], &opt->dirwh))) ++ break; ++ err = 0; ++ opt->type = token; ++ break; ++ ++ case Opt_rdcache: ++ if (unlikely(match_int(&a->args[0], &n))) { ++ pr_err("bad integer in %s\n", opt_str); ++ break; ++ } ++ if (unlikely(n > AUFS_RDCACHE_MAX)) { ++ pr_err("rdcache must be smaller than %d\n", ++ AUFS_RDCACHE_MAX); ++ break; ++ } ++ opt->rdcache = n; ++ err = 0; ++ opt->type = token; ++ break; ++ case Opt_rdblk: ++ if (unlikely(match_int(&a->args[0], &n) ++ || n < 0 ++ || n > KMALLOC_MAX_SIZE)) { ++ pr_err("bad integer in %s\n", opt_str); ++ break; ++ } ++ if (unlikely(n && n < NAME_MAX)) { ++ pr_err("rdblk must be larger than %d\n", ++ NAME_MAX); ++ break; ++ } ++ opt->rdblk = n; ++ err = 0; ++ opt->type = token; ++ break; ++ case Opt_rdhash: ++ if (unlikely(match_int(&a->args[0], &n) ++ || n < 0 ++ || n * sizeof(struct hlist_head) ++ > KMALLOC_MAX_SIZE)) { ++ pr_err("bad integer in %s\n", opt_str); ++ break; ++ } ++ opt->rdhash = n; ++ err = 0; ++ opt->type = token; ++ break; ++ ++ case Opt_trunc_xino: ++ case Opt_notrunc_xino: ++ case Opt_noxino: ++ case Opt_trunc_xib: ++ case Opt_notrunc_xib: ++ case Opt_shwh: ++ case Opt_noshwh: ++ case Opt_dirperm1: ++ case Opt_nodirperm1: ++ case Opt_plink: ++ case Opt_noplink: ++ case Opt_list_plink: ++ case Opt_dio: ++ case Opt_nodio: ++ case Opt_diropq_a: ++ case Opt_diropq_w: ++ case Opt_warn_perm: ++ case Opt_nowarn_perm: ++ case Opt_verbose: ++ case Opt_noverbose: ++ case Opt_sum: ++ case Opt_nosum: ++ case Opt_wsum: ++ case Opt_rdblk_def: ++ case Opt_rdhash_def: ++ case Opt_dirren: ++ case Opt_nodirren: ++ case Opt_acl: ++ case Opt_noacl: ++ err = 0; ++ opt->type = token; ++ break; ++ ++ case Opt_udba: ++ opt->udba = udba_val(a->args[0].from); ++ if (opt->udba >= 0) { ++ err = 0; ++ opt->type = token; ++ } else ++ pr_err("wrong value, %s\n", opt_str); ++ break; ++ ++ case Opt_wbr_create: ++ u.create = &opt->wbr_create; ++ u.create->wbr_create ++ = au_wbr_create_val(a->args[0].from, u.create); ++ if (u.create->wbr_create >= 0) { ++ err = 0; ++ opt->type = token; ++ } else ++ pr_err("wrong value, %s\n", opt_str); ++ break; ++ case Opt_wbr_copyup: ++ opt->wbr_copyup = au_wbr_copyup_val(a->args[0].from); ++ if (opt->wbr_copyup >= 0) { ++ err = 0; ++ opt->type = token; ++ } else ++ pr_err("wrong value, %s\n", opt_str); ++ break; ++ ++ case Opt_fhsm_sec: ++ if (unlikely(match_int(&a->args[0], &n) ++ || n < 0)) { ++ pr_err("bad integer in %s\n", opt_str); ++ break; ++ } ++ if (sysaufs_brs) { ++ opt->fhsm_second = n; ++ opt->type = token; ++ } else ++ pr_warn("ignored %s\n", opt_str); ++ err = 0; ++ break; ++ ++ case Opt_ignore: ++ pr_warn("ignored %s\n", opt_str); ++ /*FALLTHROUGH*/ ++ case Opt_ignore_silent: ++ skipped = 1; ++ err = 0; ++ break; ++ case Opt_err: ++ pr_err("unknown option %s\n", opt_str); ++ break; ++ } ++ ++ if (!err && !skipped) { ++ if (unlikely(++opt > opt_tail)) { ++ err = -E2BIG; ++ opt--; ++ opt->type = Opt_tail; ++ break; ++ } ++ opt->type = Opt_tail; ++ } ++ } ++ ++ au_kfree_rcu(a); ++ dump_opts(opts); ++ if (unlikely(err)) ++ au_opts_free(opts); ++ ++out: ++ return err; ++} ++ ++static int au_opt_wbr_create(struct super_block *sb, ++ struct au_opt_wbr_create *create) ++{ ++ int err; ++ struct au_sbinfo *sbinfo; ++ ++ SiMustWriteLock(sb); ++ ++ err = 1; /* handled */ ++ sbinfo = au_sbi(sb); ++ if (sbinfo->si_wbr_create_ops->fin) { ++ err = sbinfo->si_wbr_create_ops->fin(sb); ++ if (!err) ++ err = 1; ++ } ++ ++ sbinfo->si_wbr_create = create->wbr_create; ++ sbinfo->si_wbr_create_ops = au_wbr_create_ops + create->wbr_create; ++ switch (create->wbr_create) { ++ case AuWbrCreate_MFSRRV: ++ case AuWbrCreate_MFSRR: ++ case AuWbrCreate_TDMFS: ++ case AuWbrCreate_TDMFSV: ++ case AuWbrCreate_PMFSRR: ++ case AuWbrCreate_PMFSRRV: ++ sbinfo->si_wbr_mfs.mfsrr_watermark = create->mfsrr_watermark; ++ /*FALLTHROUGH*/ ++ case AuWbrCreate_MFS: ++ case AuWbrCreate_MFSV: ++ case AuWbrCreate_PMFS: ++ case AuWbrCreate_PMFSV: ++ sbinfo->si_wbr_mfs.mfs_expire ++ = msecs_to_jiffies(create->mfs_second * MSEC_PER_SEC); ++ break; ++ } ++ ++ if (sbinfo->si_wbr_create_ops->init) ++ sbinfo->si_wbr_create_ops->init(sb); /* ignore */ ++ ++ return err; ++} ++ ++/* ++ * returns, ++ * plus: processed without an error ++ * zero: unprocessed ++ */ ++static int au_opt_simple(struct super_block *sb, struct au_opt *opt, ++ struct au_opts *opts) ++{ ++ int err; ++ struct au_sbinfo *sbinfo; ++ ++ SiMustWriteLock(sb); ++ ++ err = 1; /* handled */ ++ sbinfo = au_sbi(sb); ++ switch (opt->type) { ++ case Opt_udba: ++ sbinfo->si_mntflags &= ~AuOptMask_UDBA; ++ sbinfo->si_mntflags |= opt->udba; ++ opts->given_udba |= opt->udba; ++ break; ++ ++ case Opt_plink: ++ au_opt_set(sbinfo->si_mntflags, PLINK); ++ break; ++ case Opt_noplink: ++ if (au_opt_test(sbinfo->si_mntflags, PLINK)) ++ au_plink_put(sb, /*verbose*/1); ++ au_opt_clr(sbinfo->si_mntflags, PLINK); ++ break; ++ case Opt_list_plink: ++ if (au_opt_test(sbinfo->si_mntflags, PLINK)) ++ au_plink_list(sb); ++ break; ++ ++ case Opt_dio: ++ au_opt_set(sbinfo->si_mntflags, DIO); ++ au_fset_opts(opts->flags, REFRESH_DYAOP); ++ break; ++ case Opt_nodio: ++ au_opt_clr(sbinfo->si_mntflags, DIO); ++ au_fset_opts(opts->flags, REFRESH_DYAOP); ++ break; ++ ++ case Opt_fhsm_sec: ++ au_fhsm_set(sbinfo, opt->fhsm_second); ++ break; ++ ++ case Opt_diropq_a: ++ au_opt_set(sbinfo->si_mntflags, ALWAYS_DIROPQ); ++ break; ++ case Opt_diropq_w: ++ au_opt_clr(sbinfo->si_mntflags, ALWAYS_DIROPQ); ++ break; ++ ++ case Opt_warn_perm: ++ au_opt_set(sbinfo->si_mntflags, WARN_PERM); ++ break; ++ case Opt_nowarn_perm: ++ au_opt_clr(sbinfo->si_mntflags, WARN_PERM); ++ break; ++ ++ case Opt_verbose: ++ au_opt_set(sbinfo->si_mntflags, VERBOSE); ++ break; ++ case Opt_noverbose: ++ au_opt_clr(sbinfo->si_mntflags, VERBOSE); ++ break; ++ ++ case Opt_sum: ++ au_opt_set(sbinfo->si_mntflags, SUM); ++ break; ++ case Opt_wsum: ++ au_opt_clr(sbinfo->si_mntflags, SUM); ++ au_opt_set(sbinfo->si_mntflags, SUM_W); ++ break; ++ case Opt_nosum: ++ au_opt_clr(sbinfo->si_mntflags, SUM); ++ au_opt_clr(sbinfo->si_mntflags, SUM_W); ++ break; ++ ++ case Opt_wbr_create: ++ err = au_opt_wbr_create(sb, &opt->wbr_create); ++ break; ++ case Opt_wbr_copyup: ++ sbinfo->si_wbr_copyup = opt->wbr_copyup; ++ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + opt->wbr_copyup; ++ break; ++ ++ case Opt_dirwh: ++ sbinfo->si_dirwh = opt->dirwh; ++ break; ++ ++ case Opt_rdcache: ++ sbinfo->si_rdcache ++ = msecs_to_jiffies(opt->rdcache * MSEC_PER_SEC); ++ break; ++ case Opt_rdblk: ++ sbinfo->si_rdblk = opt->rdblk; ++ break; ++ case Opt_rdblk_def: ++ sbinfo->si_rdblk = AUFS_RDBLK_DEF; ++ break; ++ case Opt_rdhash: ++ sbinfo->si_rdhash = opt->rdhash; ++ break; ++ case Opt_rdhash_def: ++ sbinfo->si_rdhash = AUFS_RDHASH_DEF; ++ break; ++ ++ case Opt_shwh: ++ au_opt_set(sbinfo->si_mntflags, SHWH); ++ break; ++ case Opt_noshwh: ++ au_opt_clr(sbinfo->si_mntflags, SHWH); ++ break; ++ ++ case Opt_dirperm1: ++ au_opt_set(sbinfo->si_mntflags, DIRPERM1); ++ break; ++ case Opt_nodirperm1: ++ au_opt_clr(sbinfo->si_mntflags, DIRPERM1); ++ break; ++ ++ case Opt_trunc_xino: ++ au_opt_set(sbinfo->si_mntflags, TRUNC_XINO); ++ break; ++ case Opt_notrunc_xino: ++ au_opt_clr(sbinfo->si_mntflags, TRUNC_XINO); ++ break; ++ ++ case Opt_trunc_xino_path: ++ case Opt_itrunc_xino: ++ err = au_xino_trunc(sb, opt->xino_itrunc.bindex, ++ /*idx_begin*/0); ++ if (!err) ++ err = 1; ++ break; ++ ++ case Opt_trunc_xib: ++ au_fset_opts(opts->flags, TRUNC_XIB); ++ break; ++ case Opt_notrunc_xib: ++ au_fclr_opts(opts->flags, TRUNC_XIB); ++ break; ++ ++ case Opt_dirren: ++ err = 1; ++ if (!au_opt_test(sbinfo->si_mntflags, DIRREN)) { ++ err = au_dr_opt_set(sb); ++ if (!err) ++ err = 1; ++ } ++ if (err == 1) ++ au_opt_set(sbinfo->si_mntflags, DIRREN); ++ break; ++ case Opt_nodirren: ++ err = 1; ++ if (au_opt_test(sbinfo->si_mntflags, DIRREN)) { ++ err = au_dr_opt_clr(sb, au_ftest_opts(opts->flags, ++ DR_FLUSHED)); ++ if (!err) ++ err = 1; ++ } ++ if (err == 1) ++ au_opt_clr(sbinfo->si_mntflags, DIRREN); ++ break; ++ ++ case Opt_acl: ++ sb->s_flags |= SB_POSIXACL; ++ break; ++ case Opt_noacl: ++ sb->s_flags &= ~SB_POSIXACL; ++ break; ++ ++ default: ++ err = 0; ++ break; ++ } ++ ++ return err; ++} ++ ++/* ++ * returns tri-state. ++ * plus: processed without an error ++ * zero: unprocessed ++ * minus: error ++ */ ++static int au_opt_br(struct super_block *sb, struct au_opt *opt, ++ struct au_opts *opts) ++{ ++ int err, do_refresh; ++ ++ err = 0; ++ switch (opt->type) { ++ case Opt_append: ++ opt->add.bindex = au_sbbot(sb) + 1; ++ if (opt->add.bindex < 0) ++ opt->add.bindex = 0; ++ goto add; ++ /* Always goto add, not fallthrough */ ++ case Opt_prepend: ++ opt->add.bindex = 0; ++ /* fallthrough */ ++ add: /* indented label */ ++ case Opt_add: ++ err = au_br_add(sb, &opt->add, ++ au_ftest_opts(opts->flags, REMOUNT)); ++ if (!err) { ++ err = 1; ++ au_fset_opts(opts->flags, REFRESH); ++ } ++ break; ++ ++ case Opt_del: ++ case Opt_idel: ++ err = au_br_del(sb, &opt->del, ++ au_ftest_opts(opts->flags, REMOUNT)); ++ if (!err) { ++ err = 1; ++ au_fset_opts(opts->flags, TRUNC_XIB); ++ au_fset_opts(opts->flags, REFRESH); ++ } ++ break; ++ ++ case Opt_mod: ++ case Opt_imod: ++ err = au_br_mod(sb, &opt->mod, ++ au_ftest_opts(opts->flags, REMOUNT), ++ &do_refresh); ++ if (!err) { ++ err = 1; ++ if (do_refresh) ++ au_fset_opts(opts->flags, REFRESH); ++ } ++ break; ++ } ++ return err; ++} ++ ++static int au_opt_xino(struct super_block *sb, struct au_opt *opt, ++ struct au_opt_xino **opt_xino, ++ struct au_opts *opts) ++{ ++ int err; ++ ++ err = 0; ++ switch (opt->type) { ++ case Opt_xino: ++ err = au_xino_set(sb, &opt->xino, ++ !!au_ftest_opts(opts->flags, REMOUNT)); ++ if (unlikely(err)) ++ break; ++ ++ *opt_xino = &opt->xino; ++ break; ++ ++ case Opt_noxino: ++ au_xino_clr(sb); ++ *opt_xino = (void *)-1; ++ break; ++ } ++ ++ return err; ++} ++ ++int au_opts_verify(struct super_block *sb, unsigned long sb_flags, ++ unsigned int pending) ++{ ++ int err, fhsm; ++ aufs_bindex_t bindex, bbot; ++ unsigned char do_plink, skip, do_free, can_no_dreval; ++ struct au_branch *br; ++ struct au_wbr *wbr; ++ struct dentry *root, *dentry; ++ struct inode *dir, *h_dir; ++ struct au_sbinfo *sbinfo; ++ struct au_hinode *hdir; ++ ++ SiMustAnyLock(sb); ++ ++ sbinfo = au_sbi(sb); ++ AuDebugOn(!(sbinfo->si_mntflags & AuOptMask_UDBA)); ++ ++ if (!(sb_flags & SB_RDONLY)) { ++ if (unlikely(!au_br_writable(au_sbr_perm(sb, 0)))) ++ pr_warn("first branch should be rw\n"); ++ if (unlikely(au_opt_test(sbinfo->si_mntflags, SHWH))) ++ pr_warn_once("shwh should be used with ro\n"); ++ } ++ ++ if (au_opt_test((sbinfo->si_mntflags | pending), UDBA_HNOTIFY) ++ && !au_opt_test(sbinfo->si_mntflags, XINO)) ++ pr_warn_once("udba=*notify requires xino\n"); ++ ++ if (au_opt_test(sbinfo->si_mntflags, DIRPERM1)) ++ pr_warn_once("dirperm1 breaks the protection" ++ " by the permission bits on the lower branch\n"); ++ ++ err = 0; ++ fhsm = 0; ++ root = sb->s_root; ++ dir = d_inode(root); ++ do_plink = !!au_opt_test(sbinfo->si_mntflags, PLINK); ++ can_no_dreval = !!au_opt_test((sbinfo->si_mntflags | pending), ++ UDBA_NONE); ++ bbot = au_sbbot(sb); ++ for (bindex = 0; !err && bindex <= bbot; bindex++) { ++ skip = 0; ++ h_dir = au_h_iptr(dir, bindex); ++ br = au_sbr(sb, bindex); ++ ++ if ((br->br_perm & AuBrAttr_ICEX) ++ && !h_dir->i_op->listxattr) ++ br->br_perm &= ~AuBrAttr_ICEX; ++#if 0 ++ if ((br->br_perm & AuBrAttr_ICEX_SEC) ++ && (au_br_sb(br)->s_flags & SB_NOSEC)) ++ br->br_perm &= ~AuBrAttr_ICEX_SEC; ++#endif ++ ++ do_free = 0; ++ wbr = br->br_wbr; ++ if (wbr) ++ wbr_wh_read_lock(wbr); ++ ++ if (!au_br_writable(br->br_perm)) { ++ do_free = !!wbr; ++ skip = (!wbr ++ || (!wbr->wbr_whbase ++ && !wbr->wbr_plink ++ && !wbr->wbr_orph)); ++ } else if (!au_br_wh_linkable(br->br_perm)) { ++ /* skip = (!br->br_whbase && !br->br_orph); */ ++ skip = (!wbr || !wbr->wbr_whbase); ++ if (skip && wbr) { ++ if (do_plink) ++ skip = !!wbr->wbr_plink; ++ else ++ skip = !wbr->wbr_plink; ++ } ++ } else { ++ /* skip = (br->br_whbase && br->br_ohph); */ ++ skip = (wbr && wbr->wbr_whbase); ++ if (skip) { ++ if (do_plink) ++ skip = !!wbr->wbr_plink; ++ else ++ skip = !wbr->wbr_plink; ++ } ++ } ++ if (wbr) ++ wbr_wh_read_unlock(wbr); ++ ++ if (can_no_dreval) { ++ dentry = br->br_path.dentry; ++ spin_lock(&dentry->d_lock); ++ if (dentry->d_flags & ++ (DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE)) ++ can_no_dreval = 0; ++ spin_unlock(&dentry->d_lock); ++ } ++ ++ if (au_br_fhsm(br->br_perm)) { ++ fhsm++; ++ AuDebugOn(!br->br_fhsm); ++ } ++ ++ if (skip) ++ continue; ++ ++ hdir = au_hi(dir, bindex); ++ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT); ++ if (wbr) ++ wbr_wh_write_lock(wbr); ++ err = au_wh_init(br, sb); ++ if (wbr) ++ wbr_wh_write_unlock(wbr); ++ au_hn_inode_unlock(hdir); ++ ++ if (!err && do_free) { ++ au_kfree_rcu(wbr); ++ br->br_wbr = NULL; ++ } ++ } ++ ++ if (can_no_dreval) ++ au_fset_si(sbinfo, NO_DREVAL); ++ else ++ au_fclr_si(sbinfo, NO_DREVAL); ++ ++ if (fhsm >= 2) { ++ au_fset_si(sbinfo, FHSM); ++ for (bindex = bbot; bindex >= 0; bindex--) { ++ br = au_sbr(sb, bindex); ++ if (au_br_fhsm(br->br_perm)) { ++ au_fhsm_set_bottom(sb, bindex); ++ break; ++ } ++ } ++ } else { ++ au_fclr_si(sbinfo, FHSM); ++ au_fhsm_set_bottom(sb, -1); ++ } ++ ++ return err; ++} ++ ++int au_opts_mount(struct super_block *sb, struct au_opts *opts) ++{ ++ int err; ++ unsigned int tmp; ++ aufs_bindex_t bindex, bbot; ++ struct au_opt *opt; ++ struct au_opt_xino *opt_xino, xino; ++ struct au_sbinfo *sbinfo; ++ struct au_branch *br; ++ struct inode *dir; ++ ++ SiMustWriteLock(sb); ++ ++ err = 0; ++ opt_xino = NULL; ++ opt = opts->opt; ++ while (err >= 0 && opt->type != Opt_tail) ++ err = au_opt_simple(sb, opt++, opts); ++ if (err > 0) ++ err = 0; ++ else if (unlikely(err < 0)) ++ goto out; ++ ++ /* disable xino and udba temporary */ ++ sbinfo = au_sbi(sb); ++ tmp = sbinfo->si_mntflags; ++ au_opt_clr(sbinfo->si_mntflags, XINO); ++ au_opt_set_udba(sbinfo->si_mntflags, UDBA_REVAL); ++ ++ opt = opts->opt; ++ while (err >= 0 && opt->type != Opt_tail) ++ err = au_opt_br(sb, opt++, opts); ++ if (err > 0) ++ err = 0; ++ else if (unlikely(err < 0)) ++ goto out; ++ ++ bbot = au_sbbot(sb); ++ if (unlikely(bbot < 0)) { ++ err = -EINVAL; ++ pr_err("no branches\n"); ++ goto out; ++ } ++ ++ if (au_opt_test(tmp, XINO)) ++ au_opt_set(sbinfo->si_mntflags, XINO); ++ opt = opts->opt; ++ while (!err && opt->type != Opt_tail) ++ err = au_opt_xino(sb, opt++, &opt_xino, opts); ++ if (unlikely(err)) ++ goto out; ++ ++ err = au_opts_verify(sb, sb->s_flags, tmp); ++ if (unlikely(err)) ++ goto out; ++ ++ /* restore xino */ ++ if (au_opt_test(tmp, XINO) && !opt_xino) { ++ xino.file = au_xino_def(sb); ++ err = PTR_ERR(xino.file); ++ if (IS_ERR(xino.file)) ++ goto out; ++ ++ err = au_xino_set(sb, &xino, /*remount*/0); ++ fput(xino.file); ++ if (unlikely(err)) ++ goto out; ++ } ++ ++ /* restore udba */ ++ tmp &= AuOptMask_UDBA; ++ sbinfo->si_mntflags &= ~AuOptMask_UDBA; ++ sbinfo->si_mntflags |= tmp; ++ bbot = au_sbbot(sb); ++ for (bindex = 0; bindex <= bbot; bindex++) { ++ br = au_sbr(sb, bindex); ++ err = au_hnotify_reset_br(tmp, br, br->br_perm); ++ if (unlikely(err)) ++ AuIOErr("hnotify failed on br %d, %d, ignored\n", ++ bindex, err); ++ /* go on even if err */ ++ } ++ if (au_opt_test(tmp, UDBA_HNOTIFY)) { ++ dir = d_inode(sb->s_root); ++ au_hn_reset(dir, au_hi_flags(dir, /*isdir*/1) & ~AuHi_XINO); ++ } ++ ++out: ++ return err; ++} ++ ++int au_opts_remount(struct super_block *sb, struct au_opts *opts) ++{ ++ int err, rerr; ++ unsigned char no_dreval; ++ struct inode *dir; ++ struct au_opt_xino *opt_xino; ++ struct au_opt *opt; ++ struct au_sbinfo *sbinfo; ++ ++ SiMustWriteLock(sb); ++ ++ err = au_dr_opt_flush(sb); ++ if (unlikely(err)) ++ goto out; ++ au_fset_opts(opts->flags, DR_FLUSHED); ++ ++ dir = d_inode(sb->s_root); ++ sbinfo = au_sbi(sb); ++ opt_xino = NULL; ++ opt = opts->opt; ++ while (err >= 0 && opt->type != Opt_tail) { ++ err = au_opt_simple(sb, opt, opts); ++ if (!err) ++ err = au_opt_br(sb, opt, opts); ++ if (!err) ++ err = au_opt_xino(sb, opt, &opt_xino, opts); ++ opt++; ++ } ++ if (err > 0) ++ err = 0; ++ AuTraceErr(err); ++ /* go on even err */ ++ ++ no_dreval = !!au_ftest_si(sbinfo, NO_DREVAL); ++ rerr = au_opts_verify(sb, opts->sb_flags, /*pending*/0); ++ if (unlikely(rerr && !err)) ++ err = rerr; ++ ++ if (no_dreval != !!au_ftest_si(sbinfo, NO_DREVAL)) ++ au_fset_opts(opts->flags, REFRESH_IDOP); ++ ++ if (au_ftest_opts(opts->flags, TRUNC_XIB)) { ++ rerr = au_xib_trunc(sb); ++ if (unlikely(rerr && !err)) ++ err = rerr; ++ } ++ ++ /* will be handled by the caller */ ++ if (!au_ftest_opts(opts->flags, REFRESH) ++ && (opts->given_udba ++ || au_opt_test(sbinfo->si_mntflags, XINO) ++ || au_ftest_opts(opts->flags, REFRESH_IDOP) ++ )) ++ au_fset_opts(opts->flags, REFRESH); ++ ++ AuDbg("status 0x%x\n", opts->flags); ++ ++out: ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++unsigned int au_opt_udba(struct super_block *sb) ++{ ++ return au_mntflags(sb) & AuOptMask_UDBA; ++} +diff -Nurp linux-5.4/fs/aufs/opts.h linux-5.4-aufs/fs/aufs/opts.h +--- linux-5.4/fs/aufs/opts.h 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/opts.h 2019-11-28 01:25:59.067925618 +0200 +@@ -0,0 +1,212 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * mount options/flags ++ */ ++ ++#ifndef __AUFS_OPTS_H__ ++#define __AUFS_OPTS_H__ ++ ++#ifdef __KERNEL__ ++ ++#include ++ ++struct file; ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* mount flags */ ++#define AuOpt_XINO 1 /* external inode number bitmap ++ and translation table */ ++#define AuOpt_TRUNC_XINO (1 << 1) /* truncate xino files */ ++#define AuOpt_UDBA_NONE (1 << 2) /* users direct branch access */ ++#define AuOpt_UDBA_REVAL (1 << 3) ++#define AuOpt_UDBA_HNOTIFY (1 << 4) ++#define AuOpt_SHWH (1 << 5) /* show whiteout */ ++#define AuOpt_PLINK (1 << 6) /* pseudo-link */ ++#define AuOpt_DIRPERM1 (1 << 7) /* ignore the lower dir's perm ++ bits */ ++#define AuOpt_ALWAYS_DIROPQ (1 << 9) /* policy to creating diropq */ ++#define AuOpt_SUM (1 << 10) /* summation for statfs(2) */ ++#define AuOpt_SUM_W (1 << 11) /* unimplemented */ ++#define AuOpt_WARN_PERM (1 << 12) /* warn when add-branch */ ++#define AuOpt_VERBOSE (1 << 13) /* print the cause of error */ ++#define AuOpt_DIO (1 << 14) /* direct io */ ++#define AuOpt_DIRREN (1 << 15) /* directory rename */ ++ ++#ifndef CONFIG_AUFS_HNOTIFY ++#undef AuOpt_UDBA_HNOTIFY ++#define AuOpt_UDBA_HNOTIFY 0 ++#endif ++#ifndef CONFIG_AUFS_DIRREN ++#undef AuOpt_DIRREN ++#define AuOpt_DIRREN 0 ++#endif ++#ifndef CONFIG_AUFS_SHWH ++#undef AuOpt_SHWH ++#define AuOpt_SHWH 0 ++#endif ++ ++#define AuOpt_Def (AuOpt_XINO \ ++ | AuOpt_UDBA_REVAL \ ++ | AuOpt_PLINK \ ++ /* | AuOpt_DIRPERM1 */ \ ++ | AuOpt_WARN_PERM) ++#define AuOptMask_UDBA (AuOpt_UDBA_NONE \ ++ | AuOpt_UDBA_REVAL \ ++ | AuOpt_UDBA_HNOTIFY) ++ ++#define au_opt_test(flags, name) (flags & AuOpt_##name) ++#define au_opt_set(flags, name) do { \ ++ BUILD_BUG_ON(AuOpt_##name & AuOptMask_UDBA); \ ++ ((flags) |= AuOpt_##name); \ ++} while (0) ++#define au_opt_set_udba(flags, name) do { \ ++ (flags) &= ~AuOptMask_UDBA; \ ++ ((flags) |= AuOpt_##name); \ ++} while (0) ++#define au_opt_clr(flags, name) do { \ ++ ((flags) &= ~AuOpt_##name); \ ++} while (0) ++ ++static inline unsigned int au_opts_plink(unsigned int mntflags) ++{ ++#ifdef CONFIG_PROC_FS ++ return mntflags; ++#else ++ return mntflags & ~AuOpt_PLINK; ++#endif ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* policies to select one among multiple writable branches */ ++enum { ++ AuWbrCreate_TDP, /* top down parent */ ++ AuWbrCreate_RR, /* round robin */ ++ AuWbrCreate_MFS, /* most free space */ ++ AuWbrCreate_MFSV, /* mfs with seconds */ ++ AuWbrCreate_MFSRR, /* mfs then rr */ ++ AuWbrCreate_MFSRRV, /* mfs then rr with seconds */ ++ AuWbrCreate_TDMFS, /* top down regardless parent and mfs */ ++ AuWbrCreate_TDMFSV, /* top down regardless parent and mfs */ ++ AuWbrCreate_PMFS, /* parent and mfs */ ++ AuWbrCreate_PMFSV, /* parent and mfs with seconds */ ++ AuWbrCreate_PMFSRR, /* parent, mfs and round-robin */ ++ AuWbrCreate_PMFSRRV, /* plus seconds */ ++ ++ AuWbrCreate_Def = AuWbrCreate_TDP ++}; ++ ++enum { ++ AuWbrCopyup_TDP, /* top down parent */ ++ AuWbrCopyup_BUP, /* bottom up parent */ ++ AuWbrCopyup_BU, /* bottom up */ ++ ++ AuWbrCopyup_Def = AuWbrCopyup_TDP ++}; ++ ++/* ---------------------------------------------------------------------- */ ++ ++struct au_opt_add { ++ aufs_bindex_t bindex; ++ char *pathname; ++ int perm; ++ struct path path; ++}; ++ ++struct au_opt_del { ++ char *pathname; ++ struct path h_path; ++}; ++ ++struct au_opt_mod { ++ char *path; ++ int perm; ++ struct dentry *h_root; ++}; ++ ++struct au_opt_xino { ++ char *path; ++ struct file *file; ++}; ++ ++struct au_opt_xino_itrunc { ++ aufs_bindex_t bindex; ++}; ++ ++struct au_opt_wbr_create { ++ int wbr_create; ++ int mfs_second; ++ unsigned long long mfsrr_watermark; ++}; ++ ++struct au_opt { ++ int type; ++ union { ++ struct au_opt_xino xino; ++ struct au_opt_xino_itrunc xino_itrunc; ++ struct au_opt_add add; ++ struct au_opt_del del; ++ struct au_opt_mod mod; ++ int dirwh; ++ int rdcache; ++ unsigned int rdblk; ++ unsigned int rdhash; ++ int udba; ++ struct au_opt_wbr_create wbr_create; ++ int wbr_copyup; ++ unsigned int fhsm_second; ++ }; ++}; ++ ++/* opts flags */ ++#define AuOpts_REMOUNT 1 ++#define AuOpts_REFRESH (1 << 1) ++#define AuOpts_TRUNC_XIB (1 << 2) ++#define AuOpts_REFRESH_DYAOP (1 << 3) ++#define AuOpts_REFRESH_IDOP (1 << 4) ++#define AuOpts_DR_FLUSHED (1 << 5) ++#define au_ftest_opts(flags, name) ((flags) & AuOpts_##name) ++#define au_fset_opts(flags, name) \ ++ do { (flags) |= AuOpts_##name; } while (0) ++#define au_fclr_opts(flags, name) \ ++ do { (flags) &= ~AuOpts_##name; } while (0) ++ ++#ifndef CONFIG_AUFS_DIRREN ++#undef AuOpts_DR_FLUSHED ++#define AuOpts_DR_FLUSHED 0 ++#endif ++ ++struct au_opts { ++ struct au_opt *opt; ++ int max_opt; ++ ++ unsigned int given_udba; ++ unsigned int flags; ++ unsigned long sb_flags; ++}; ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* opts.c */ ++void au_optstr_br_perm(au_br_perm_str_t *str, int perm); ++const char *au_optstr_udba(int udba); ++const char *au_optstr_wbr_copyup(int wbr_copyup); ++const char *au_optstr_wbr_create(int wbr_create); ++ ++void au_opts_free(struct au_opts *opts); ++struct super_block; ++int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts); ++int au_opts_verify(struct super_block *sb, unsigned long sb_flags, ++ unsigned int pending); ++int au_opts_mount(struct super_block *sb, struct au_opts *opts); ++int au_opts_remount(struct super_block *sb, struct au_opts *opts); ++ ++unsigned int au_opt_udba(struct super_block *sb); ++ ++#endif /* __KERNEL__ */ ++#endif /* __AUFS_OPTS_H__ */ +diff -Nurp linux-5.4/fs/aufs/plink.c linux-5.4-aufs/fs/aufs/plink.c +--- linux-5.4/fs/aufs/plink.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/plink.c 2019-11-28 01:25:59.067925618 +0200 +@@ -0,0 +1,503 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * pseudo-link ++ */ ++ ++#include "aufs.h" ++ ++/* ++ * the pseudo-link maintenance mode. ++ * during a user process maintains the pseudo-links, ++ * prohibit adding a new plink and branch manipulation. ++ * ++ * Flags ++ * NOPLM: ++ * For entry functions which will handle plink, and i_mutex is already held ++ * in VFS. ++ * They cannot wait and should return an error at once. ++ * Callers has to check the error. ++ * NOPLMW: ++ * For entry functions which will handle plink, but i_mutex is not held ++ * in VFS. ++ * They can wait the plink maintenance mode to finish. ++ * ++ * They behave like F_SETLK and F_SETLKW. ++ * If the caller never handle plink, then both flags are unnecessary. ++ */ ++ ++int au_plink_maint(struct super_block *sb, int flags) ++{ ++ int err; ++ pid_t pid, ppid; ++ struct task_struct *parent, *prev; ++ struct au_sbinfo *sbi; ++ ++ SiMustAnyLock(sb); ++ ++ err = 0; ++ if (!au_opt_test(au_mntflags(sb), PLINK)) ++ goto out; ++ ++ sbi = au_sbi(sb); ++ pid = sbi->si_plink_maint_pid; ++ if (!pid || pid == current->pid) ++ goto out; ++ ++ /* todo: it highly depends upon /sbin/mount.aufs */ ++ prev = NULL; ++ parent = current; ++ ppid = 0; ++ rcu_read_lock(); ++ while (1) { ++ parent = rcu_dereference(parent->real_parent); ++ if (parent == prev) ++ break; ++ ppid = task_pid_vnr(parent); ++ if (pid == ppid) { ++ rcu_read_unlock(); ++ goto out; ++ } ++ prev = parent; ++ } ++ rcu_read_unlock(); ++ ++ if (au_ftest_lock(flags, NOPLMW)) { ++ /* if there is no i_mutex lock in VFS, we don't need to wait */ ++ /* AuDebugOn(!lockdep_depth(current)); */ ++ while (sbi->si_plink_maint_pid) { ++ si_read_unlock(sb); ++ /* gave up wake_up_bit() */ ++ wait_event(sbi->si_plink_wq, !sbi->si_plink_maint_pid); ++ ++ if (au_ftest_lock(flags, FLUSH)) ++ au_nwt_flush(&sbi->si_nowait); ++ si_noflush_read_lock(sb); ++ } ++ } else if (au_ftest_lock(flags, NOPLM)) { ++ AuDbg("ppid %d, pid %d\n", ppid, pid); ++ err = -EAGAIN; ++ } ++ ++out: ++ return err; ++} ++ ++void au_plink_maint_leave(struct au_sbinfo *sbinfo) ++{ ++ spin_lock(&sbinfo->si_plink_maint_lock); ++ sbinfo->si_plink_maint_pid = 0; ++ spin_unlock(&sbinfo->si_plink_maint_lock); ++ wake_up_all(&sbinfo->si_plink_wq); ++} ++ ++int au_plink_maint_enter(struct super_block *sb) ++{ ++ int err; ++ struct au_sbinfo *sbinfo; ++ ++ err = 0; ++ sbinfo = au_sbi(sb); ++ /* make sure i am the only one in this fs */ ++ si_write_lock(sb, AuLock_FLUSH); ++ if (au_opt_test(au_mntflags(sb), PLINK)) { ++ spin_lock(&sbinfo->si_plink_maint_lock); ++ if (!sbinfo->si_plink_maint_pid) ++ sbinfo->si_plink_maint_pid = current->pid; ++ else ++ err = -EBUSY; ++ spin_unlock(&sbinfo->si_plink_maint_lock); ++ } ++ si_write_unlock(sb); ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++#ifdef CONFIG_AUFS_DEBUG ++void au_plink_list(struct super_block *sb) ++{ ++ int i; ++ struct au_sbinfo *sbinfo; ++ struct hlist_bl_head *hbl; ++ struct hlist_bl_node *pos; ++ struct au_icntnr *icntnr; ++ ++ SiMustAnyLock(sb); ++ ++ sbinfo = au_sbi(sb); ++ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK)); ++ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM)); ++ ++ for (i = 0; i < AuPlink_NHASH; i++) { ++ hbl = sbinfo->si_plink + i; ++ hlist_bl_lock(hbl); ++ hlist_bl_for_each_entry(icntnr, pos, hbl, plink) ++ AuDbg("%lu\n", icntnr->vfs_inode.i_ino); ++ hlist_bl_unlock(hbl); ++ } ++} ++#endif ++ ++/* is the inode pseudo-linked? */ ++int au_plink_test(struct inode *inode) ++{ ++ int found, i; ++ struct au_sbinfo *sbinfo; ++ struct hlist_bl_head *hbl; ++ struct hlist_bl_node *pos; ++ struct au_icntnr *icntnr; ++ ++ sbinfo = au_sbi(inode->i_sb); ++ AuRwMustAnyLock(&sbinfo->si_rwsem); ++ AuDebugOn(!au_opt_test(au_mntflags(inode->i_sb), PLINK)); ++ AuDebugOn(au_plink_maint(inode->i_sb, AuLock_NOPLM)); ++ ++ found = 0; ++ i = au_plink_hash(inode->i_ino); ++ hbl = sbinfo->si_plink + i; ++ hlist_bl_lock(hbl); ++ hlist_bl_for_each_entry(icntnr, pos, hbl, plink) ++ if (&icntnr->vfs_inode == inode) { ++ found = 1; ++ break; ++ } ++ hlist_bl_unlock(hbl); ++ return found; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * generate a name for plink. ++ * the file will be stored under AUFS_WH_PLINKDIR. ++ */ ++/* 20 is max digits length of ulong 64 */ ++#define PLINK_NAME_LEN ((20 + 1) * 2) ++ ++static int plink_name(char *name, int len, struct inode *inode, ++ aufs_bindex_t bindex) ++{ ++ int rlen; ++ struct inode *h_inode; ++ ++ h_inode = au_h_iptr(inode, bindex); ++ rlen = snprintf(name, len, "%lu.%lu", inode->i_ino, h_inode->i_ino); ++ return rlen; ++} ++ ++struct au_do_plink_lkup_args { ++ struct dentry **errp; ++ struct qstr *tgtname; ++ struct dentry *h_parent; ++ struct au_branch *br; ++}; ++ ++static struct dentry *au_do_plink_lkup(struct qstr *tgtname, ++ struct dentry *h_parent, ++ struct au_branch *br) ++{ ++ struct dentry *h_dentry; ++ struct inode *h_inode; ++ ++ h_inode = d_inode(h_parent); ++ inode_lock_shared_nested(h_inode, AuLsc_I_CHILD2); ++ h_dentry = vfsub_lkup_one(tgtname, h_parent); ++ inode_unlock_shared(h_inode); ++ return h_dentry; ++} ++ ++static void au_call_do_plink_lkup(void *args) ++{ ++ struct au_do_plink_lkup_args *a = args; ++ *a->errp = au_do_plink_lkup(a->tgtname, a->h_parent, a->br); ++} ++ ++/* lookup the plink-ed @inode under the branch at @bindex */ ++struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex) ++{ ++ struct dentry *h_dentry, *h_parent; ++ struct au_branch *br; ++ int wkq_err; ++ char a[PLINK_NAME_LEN]; ++ struct qstr tgtname = QSTR_INIT(a, 0); ++ ++ AuDebugOn(au_plink_maint(inode->i_sb, AuLock_NOPLM)); ++ ++ br = au_sbr(inode->i_sb, bindex); ++ h_parent = br->br_wbr->wbr_plink; ++ tgtname.len = plink_name(a, sizeof(a), inode, bindex); ++ ++ if (!uid_eq(current_fsuid(), GLOBAL_ROOT_UID)) { ++ struct au_do_plink_lkup_args args = { ++ .errp = &h_dentry, ++ .tgtname = &tgtname, ++ .h_parent = h_parent, ++ .br = br ++ }; ++ ++ wkq_err = au_wkq_wait(au_call_do_plink_lkup, &args); ++ if (unlikely(wkq_err)) ++ h_dentry = ERR_PTR(wkq_err); ++ } else ++ h_dentry = au_do_plink_lkup(&tgtname, h_parent, br); ++ ++ return h_dentry; ++} ++ ++/* create a pseudo-link */ ++static int do_whplink(struct qstr *tgt, struct dentry *h_parent, ++ struct dentry *h_dentry, struct au_branch *br) ++{ ++ int err; ++ struct path h_path = { ++ .mnt = au_br_mnt(br) ++ }; ++ struct inode *h_dir, *delegated; ++ ++ h_dir = d_inode(h_parent); ++ inode_lock_nested(h_dir, AuLsc_I_CHILD2); ++again: ++ h_path.dentry = vfsub_lkup_one(tgt, h_parent); ++ err = PTR_ERR(h_path.dentry); ++ if (IS_ERR(h_path.dentry)) ++ goto out; ++ ++ err = 0; ++ /* wh.plink dir is not monitored */ ++ /* todo: is it really safe? */ ++ if (d_is_positive(h_path.dentry) ++ && d_inode(h_path.dentry) != d_inode(h_dentry)) { ++ delegated = NULL; ++ err = vfsub_unlink(h_dir, &h_path, &delegated, /*force*/0); ++ if (unlikely(err == -EWOULDBLOCK)) { ++ pr_warn("cannot retry for NFSv4 delegation" ++ " for an internal unlink\n"); ++ iput(delegated); ++ } ++ dput(h_path.dentry); ++ h_path.dentry = NULL; ++ if (!err) ++ goto again; ++ } ++ if (!err && d_is_negative(h_path.dentry)) { ++ delegated = NULL; ++ err = vfsub_link(h_dentry, h_dir, &h_path, &delegated); ++ if (unlikely(err == -EWOULDBLOCK)) { ++ pr_warn("cannot retry for NFSv4 delegation" ++ " for an internal link\n"); ++ iput(delegated); ++ } ++ } ++ dput(h_path.dentry); ++ ++out: ++ inode_unlock(h_dir); ++ return err; ++} ++ ++struct do_whplink_args { ++ int *errp; ++ struct qstr *tgt; ++ struct dentry *h_parent; ++ struct dentry *h_dentry; ++ struct au_branch *br; ++}; ++ ++static void call_do_whplink(void *args) ++{ ++ struct do_whplink_args *a = args; ++ *a->errp = do_whplink(a->tgt, a->h_parent, a->h_dentry, a->br); ++} ++ ++static int whplink(struct dentry *h_dentry, struct inode *inode, ++ aufs_bindex_t bindex, struct au_branch *br) ++{ ++ int err, wkq_err; ++ struct au_wbr *wbr; ++ struct dentry *h_parent; ++ char a[PLINK_NAME_LEN]; ++ struct qstr tgtname = QSTR_INIT(a, 0); ++ ++ wbr = au_sbr(inode->i_sb, bindex)->br_wbr; ++ h_parent = wbr->wbr_plink; ++ tgtname.len = plink_name(a, sizeof(a), inode, bindex); ++ ++ /* always superio. */ ++ if (!uid_eq(current_fsuid(), GLOBAL_ROOT_UID)) { ++ struct do_whplink_args args = { ++ .errp = &err, ++ .tgt = &tgtname, ++ .h_parent = h_parent, ++ .h_dentry = h_dentry, ++ .br = br ++ }; ++ wkq_err = au_wkq_wait(call_do_whplink, &args); ++ if (unlikely(wkq_err)) ++ err = wkq_err; ++ } else ++ err = do_whplink(&tgtname, h_parent, h_dentry, br); ++ ++ return err; ++} ++ ++/* ++ * create a new pseudo-link for @h_dentry on @bindex. ++ * the linked inode is held in aufs @inode. ++ */ ++void au_plink_append(struct inode *inode, aufs_bindex_t bindex, ++ struct dentry *h_dentry) ++{ ++ struct super_block *sb; ++ struct au_sbinfo *sbinfo; ++ struct hlist_bl_head *hbl; ++ struct hlist_bl_node *pos; ++ struct au_icntnr *icntnr; ++ int found, err, cnt, i; ++ ++ sb = inode->i_sb; ++ sbinfo = au_sbi(sb); ++ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK)); ++ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM)); ++ ++ found = au_plink_test(inode); ++ if (found) ++ return; ++ ++ i = au_plink_hash(inode->i_ino); ++ hbl = sbinfo->si_plink + i; ++ au_igrab(inode); ++ ++ hlist_bl_lock(hbl); ++ hlist_bl_for_each_entry(icntnr, pos, hbl, plink) { ++ if (&icntnr->vfs_inode == inode) { ++ found = 1; ++ break; ++ } ++ } ++ if (!found) { ++ icntnr = container_of(inode, struct au_icntnr, vfs_inode); ++ hlist_bl_add_head(&icntnr->plink, hbl); ++ } ++ hlist_bl_unlock(hbl); ++ if (!found) { ++ cnt = au_hbl_count(hbl); ++#define msg "unexpectedly unbalanced or too many pseudo-links" ++ if (cnt > AUFS_PLINK_WARN) ++ AuWarn1(msg ", %d\n", cnt); ++#undef msg ++ err = whplink(h_dentry, inode, bindex, au_sbr(sb, bindex)); ++ if (unlikely(err)) { ++ pr_warn("err %d, damaged pseudo link.\n", err); ++ au_hbl_del(&icntnr->plink, hbl); ++ iput(&icntnr->vfs_inode); ++ } ++ } else ++ iput(&icntnr->vfs_inode); ++} ++ ++/* free all plinks */ ++void au_plink_put(struct super_block *sb, int verbose) ++{ ++ int i, warned; ++ struct au_sbinfo *sbinfo; ++ struct hlist_bl_head *hbl; ++ struct hlist_bl_node *pos, *tmp; ++ struct au_icntnr *icntnr; ++ ++ SiMustWriteLock(sb); ++ ++ sbinfo = au_sbi(sb); ++ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK)); ++ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM)); ++ ++ /* no spin_lock since sbinfo is write-locked */ ++ warned = 0; ++ for (i = 0; i < AuPlink_NHASH; i++) { ++ hbl = sbinfo->si_plink + i; ++ if (!warned && verbose && !hlist_bl_empty(hbl)) { ++ pr_warn("pseudo-link is not flushed"); ++ warned = 1; ++ } ++ hlist_bl_for_each_entry_safe(icntnr, pos, tmp, hbl, plink) ++ iput(&icntnr->vfs_inode); ++ INIT_HLIST_BL_HEAD(hbl); ++ } ++} ++ ++void au_plink_clean(struct super_block *sb, int verbose) ++{ ++ struct dentry *root; ++ ++ root = sb->s_root; ++ aufs_write_lock(root); ++ if (au_opt_test(au_mntflags(sb), PLINK)) ++ au_plink_put(sb, verbose); ++ aufs_write_unlock(root); ++} ++ ++static int au_plink_do_half_refresh(struct inode *inode, aufs_bindex_t br_id) ++{ ++ int do_put; ++ aufs_bindex_t btop, bbot, bindex; ++ ++ do_put = 0; ++ btop = au_ibtop(inode); ++ bbot = au_ibbot(inode); ++ if (btop >= 0) { ++ for (bindex = btop; bindex <= bbot; bindex++) { ++ if (!au_h_iptr(inode, bindex) ++ || au_ii_br_id(inode, bindex) != br_id) ++ continue; ++ au_set_h_iptr(inode, bindex, NULL, 0); ++ do_put = 1; ++ break; ++ } ++ if (do_put) ++ for (bindex = btop; bindex <= bbot; bindex++) ++ if (au_h_iptr(inode, bindex)) { ++ do_put = 0; ++ break; ++ } ++ } else ++ do_put = 1; ++ ++ return do_put; ++} ++ ++/* free the plinks on a branch specified by @br_id */ ++void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id) ++{ ++ struct au_sbinfo *sbinfo; ++ struct hlist_bl_head *hbl; ++ struct hlist_bl_node *pos, *tmp; ++ struct au_icntnr *icntnr; ++ struct inode *inode; ++ int i, do_put; ++ ++ SiMustWriteLock(sb); ++ ++ sbinfo = au_sbi(sb); ++ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK)); ++ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM)); ++ ++ /* no bit_lock since sbinfo is write-locked */ ++ for (i = 0; i < AuPlink_NHASH; i++) { ++ hbl = sbinfo->si_plink + i; ++ hlist_bl_for_each_entry_safe(icntnr, pos, tmp, hbl, plink) { ++ inode = au_igrab(&icntnr->vfs_inode); ++ ii_write_lock_child(inode); ++ do_put = au_plink_do_half_refresh(inode, br_id); ++ if (do_put) { ++ hlist_bl_del(&icntnr->plink); ++ iput(inode); ++ } ++ ii_write_unlock(inode); ++ iput(inode); ++ } ++ } ++} +diff -Nurp linux-5.4/fs/aufs/poll.c linux-5.4-aufs/fs/aufs/poll.c +--- linux-5.4/fs/aufs/poll.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/poll.c 2019-11-28 01:25:59.067925618 +0200 +@@ -0,0 +1,38 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * poll operation ++ * There is only one filesystem which implements ->poll operation, currently. ++ */ ++ ++#include "aufs.h" ++ ++__poll_t aufs_poll(struct file *file, struct poll_table_struct *pt) ++{ ++ __poll_t mask; ++ struct file *h_file; ++ struct super_block *sb; ++ ++ /* We should pretend an error happened. */ ++ mask = EPOLLERR /* | EPOLLIN | EPOLLOUT */; ++ sb = file->f_path.dentry->d_sb; ++ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); ++ ++ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0); ++ if (IS_ERR(h_file)) { ++ AuDbg("h_file %ld\n", PTR_ERR(h_file)); ++ goto out; ++ } ++ ++ mask = vfs_poll(h_file, pt); ++ fput(h_file); /* instead of au_read_post() */ ++ ++out: ++ si_read_unlock(sb); ++ if (mask & EPOLLERR) ++ AuDbg("mask 0x%x\n", mask); ++ return mask; ++} +diff -Nurp linux-5.4/fs/aufs/posix_acl.c linux-5.4-aufs/fs/aufs/posix_acl.c +--- linux-5.4/fs/aufs/posix_acl.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/posix_acl.c 2019-11-28 01:25:59.067925618 +0200 +@@ -0,0 +1,92 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2014-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * posix acl operations ++ */ ++ ++#include ++#include "aufs.h" ++ ++struct posix_acl *aufs_get_acl(struct inode *inode, int type) ++{ ++ struct posix_acl *acl; ++ int err; ++ aufs_bindex_t bindex; ++ struct inode *h_inode; ++ struct super_block *sb; ++ ++ acl = NULL; ++ sb = inode->i_sb; ++ si_read_lock(sb, AuLock_FLUSH); ++ ii_read_lock_child(inode); ++ if (!(sb->s_flags & SB_POSIXACL)) ++ goto out; ++ ++ bindex = au_ibtop(inode); ++ h_inode = au_h_iptr(inode, bindex); ++ if (unlikely(!h_inode ++ || ((h_inode->i_mode & S_IFMT) ++ != (inode->i_mode & S_IFMT)))) { ++ err = au_busy_or_stale(); ++ acl = ERR_PTR(err); ++ goto out; ++ } ++ ++ /* always topmost only */ ++ acl = get_acl(h_inode, type); ++ if (IS_ERR(acl)) ++ forget_cached_acl(inode, type); ++ else ++ set_cached_acl(inode, type, acl); ++ ++out: ++ ii_read_unlock(inode); ++ si_read_unlock(sb); ++ ++ AuTraceErrPtr(acl); ++ return acl; ++} ++ ++int aufs_set_acl(struct inode *inode, struct posix_acl *acl, int type) ++{ ++ int err; ++ ssize_t ssz; ++ struct dentry *dentry; ++ struct au_sxattr arg = { ++ .type = AU_ACL_SET, ++ .u.acl_set = { ++ .acl = acl, ++ .type = type ++ }, ++ }; ++ ++ IMustLock(inode); ++ ++ if (inode->i_ino == AUFS_ROOT_INO) ++ dentry = dget(inode->i_sb->s_root); ++ else { ++ dentry = d_find_alias(inode); ++ if (!dentry) ++ dentry = d_find_any_alias(inode); ++ if (!dentry) { ++ pr_warn("cannot handle this inode, " ++ "please report to aufs-users ML\n"); ++ err = -ENOENT; ++ goto out; ++ } ++ } ++ ++ ssz = au_sxattr(dentry, inode, &arg); ++ /* forget even it if succeeds since the branch might set differently */ ++ forget_cached_acl(inode, type); ++ dput(dentry); ++ err = ssz; ++ if (ssz >= 0) ++ err = 0; ++ ++out: ++ return err; ++} +diff -Nurp linux-5.4/fs/aufs/procfs.c linux-5.4-aufs/fs/aufs/procfs.c +--- linux-5.4/fs/aufs/procfs.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/procfs.c 2019-11-28 01:25:59.067925618 +0200 +@@ -0,0 +1,158 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2010-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * procfs interfaces ++ */ ++ ++#include ++#include "aufs.h" ++ ++static int au_procfs_plm_release(struct inode *inode, struct file *file) ++{ ++ struct au_sbinfo *sbinfo; ++ ++ sbinfo = file->private_data; ++ if (sbinfo) { ++ au_plink_maint_leave(sbinfo); ++ kobject_put(&sbinfo->si_kobj); ++ } ++ ++ return 0; ++} ++ ++static void au_procfs_plm_write_clean(struct file *file) ++{ ++ struct au_sbinfo *sbinfo; ++ ++ sbinfo = file->private_data; ++ if (sbinfo) ++ au_plink_clean(sbinfo->si_sb, /*verbose*/0); ++} ++ ++static int au_procfs_plm_write_si(struct file *file, unsigned long id) ++{ ++ int err; ++ struct super_block *sb; ++ struct au_sbinfo *sbinfo; ++ struct hlist_bl_node *pos; ++ ++ err = -EBUSY; ++ if (unlikely(file->private_data)) ++ goto out; ++ ++ sb = NULL; ++ /* don't use au_sbilist_lock() here */ ++ hlist_bl_lock(&au_sbilist); ++ hlist_bl_for_each_entry(sbinfo, pos, &au_sbilist, si_list) ++ if (id == sysaufs_si_id(sbinfo)) { ++ if (kobject_get_unless_zero(&sbinfo->si_kobj)) ++ sb = sbinfo->si_sb; ++ break; ++ } ++ hlist_bl_unlock(&au_sbilist); ++ ++ err = -EINVAL; ++ if (unlikely(!sb)) ++ goto out; ++ ++ err = au_plink_maint_enter(sb); ++ if (!err) ++ /* keep kobject_get() */ ++ file->private_data = sbinfo; ++ else ++ kobject_put(&sbinfo->si_kobj); ++out: ++ return err; ++} ++ ++/* ++ * Accept a valid "si=xxxx" only. ++ * Once it is accepted successfully, accept "clean" too. ++ */ ++static ssize_t au_procfs_plm_write(struct file *file, const char __user *ubuf, ++ size_t count, loff_t *ppos) ++{ ++ ssize_t err; ++ unsigned long id; ++ /* last newline is allowed */ ++ char buf[3 + sizeof(unsigned long) * 2 + 1]; ++ ++ err = -EACCES; ++ if (unlikely(!capable(CAP_SYS_ADMIN))) ++ goto out; ++ ++ err = -EINVAL; ++ if (unlikely(count > sizeof(buf))) ++ goto out; ++ ++ err = copy_from_user(buf, ubuf, count); ++ if (unlikely(err)) { ++ err = -EFAULT; ++ goto out; ++ } ++ buf[count] = 0; ++ ++ err = -EINVAL; ++ if (!strcmp("clean", buf)) { ++ au_procfs_plm_write_clean(file); ++ goto out_success; ++ } else if (unlikely(strncmp("si=", buf, 3))) ++ goto out; ++ ++ err = kstrtoul(buf + 3, 16, &id); ++ if (unlikely(err)) ++ goto out; ++ ++ err = au_procfs_plm_write_si(file, id); ++ if (unlikely(err)) ++ goto out; ++ ++out_success: ++ err = count; /* success */ ++out: ++ return err; ++} ++ ++static const struct file_operations au_procfs_plm_fop = { ++ .write = au_procfs_plm_write, ++ .release = au_procfs_plm_release, ++ .owner = THIS_MODULE ++}; ++ ++/* ---------------------------------------------------------------------- */ ++ ++static struct proc_dir_entry *au_procfs_dir; ++ ++void au_procfs_fin(void) ++{ ++ remove_proc_entry(AUFS_PLINK_MAINT_NAME, au_procfs_dir); ++ remove_proc_entry(AUFS_PLINK_MAINT_DIR, NULL); ++} ++ ++int __init au_procfs_init(void) ++{ ++ int err; ++ struct proc_dir_entry *entry; ++ ++ err = -ENOMEM; ++ au_procfs_dir = proc_mkdir(AUFS_PLINK_MAINT_DIR, NULL); ++ if (unlikely(!au_procfs_dir)) ++ goto out; ++ ++ entry = proc_create(AUFS_PLINK_MAINT_NAME, S_IFREG | 0200, ++ au_procfs_dir, &au_procfs_plm_fop); ++ if (unlikely(!entry)) ++ goto out_dir; ++ ++ err = 0; ++ goto out; /* success */ ++ ++ ++out_dir: ++ remove_proc_entry(AUFS_PLINK_MAINT_DIR, NULL); ++out: ++ return err; ++} +diff -Nurp linux-5.4/fs/aufs/rdu.c linux-5.4-aufs/fs/aufs/rdu.c +--- linux-5.4/fs/aufs/rdu.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/rdu.c 2019-11-28 01:25:59.067925618 +0200 +@@ -0,0 +1,371 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * readdir in userspace. ++ */ ++ ++#include ++#include ++#include ++#include "aufs.h" ++ ++/* bits for struct aufs_rdu.flags */ ++#define AuRdu_CALLED 1 ++#define AuRdu_CONT (1 << 1) ++#define AuRdu_FULL (1 << 2) ++#define au_ftest_rdu(flags, name) ((flags) & AuRdu_##name) ++#define au_fset_rdu(flags, name) \ ++ do { (flags) |= AuRdu_##name; } while (0) ++#define au_fclr_rdu(flags, name) \ ++ do { (flags) &= ~AuRdu_##name; } while (0) ++ ++struct au_rdu_arg { ++ struct dir_context ctx; ++ struct aufs_rdu *rdu; ++ union au_rdu_ent_ul ent; ++ unsigned long end; ++ ++ struct super_block *sb; ++ int err; ++}; ++ ++static int au_rdu_fill(struct dir_context *ctx, const char *name, int nlen, ++ loff_t offset, u64 h_ino, unsigned int d_type) ++{ ++ int err, len; ++ struct au_rdu_arg *arg = container_of(ctx, struct au_rdu_arg, ctx); ++ struct aufs_rdu *rdu = arg->rdu; ++ struct au_rdu_ent ent; ++ ++ err = 0; ++ arg->err = 0; ++ au_fset_rdu(rdu->cookie.flags, CALLED); ++ len = au_rdu_len(nlen); ++ if (arg->ent.ul + len < arg->end) { ++ ent.ino = h_ino; ++ ent.bindex = rdu->cookie.bindex; ++ ent.type = d_type; ++ ent.nlen = nlen; ++ if (unlikely(nlen > AUFS_MAX_NAMELEN)) ++ ent.type = DT_UNKNOWN; ++ ++ /* unnecessary to support mmap_sem since this is a dir */ ++ err = -EFAULT; ++ if (copy_to_user(arg->ent.e, &ent, sizeof(ent))) ++ goto out; ++ if (copy_to_user(arg->ent.e->name, name, nlen)) ++ goto out; ++ /* the terminating NULL */ ++ if (__put_user(0, arg->ent.e->name + nlen)) ++ goto out; ++ err = 0; ++ /* AuDbg("%p, %.*s\n", arg->ent.p, nlen, name); */ ++ arg->ent.ul += len; ++ rdu->rent++; ++ } else { ++ err = -EFAULT; ++ au_fset_rdu(rdu->cookie.flags, FULL); ++ rdu->full = 1; ++ rdu->tail = arg->ent; ++ } ++ ++out: ++ /* AuTraceErr(err); */ ++ return err; ++} ++ ++static int au_rdu_do(struct file *h_file, struct au_rdu_arg *arg) ++{ ++ int err; ++ loff_t offset; ++ struct au_rdu_cookie *cookie = &arg->rdu->cookie; ++ ++ /* we don't have to care (FMODE_32BITHASH | FMODE_64BITHASH) for ext4 */ ++ offset = vfsub_llseek(h_file, cookie->h_pos, SEEK_SET); ++ err = offset; ++ if (unlikely(offset != cookie->h_pos)) ++ goto out; ++ ++ err = 0; ++ do { ++ arg->err = 0; ++ au_fclr_rdu(cookie->flags, CALLED); ++ /* smp_mb(); */ ++ err = vfsub_iterate_dir(h_file, &arg->ctx); ++ if (err >= 0) ++ err = arg->err; ++ } while (!err ++ && au_ftest_rdu(cookie->flags, CALLED) ++ && !au_ftest_rdu(cookie->flags, FULL)); ++ cookie->h_pos = h_file->f_pos; ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++static int au_rdu(struct file *file, struct aufs_rdu *rdu) ++{ ++ int err; ++ aufs_bindex_t bbot; ++ struct au_rdu_arg arg = { ++ .ctx = { ++ .actor = au_rdu_fill ++ } ++ }; ++ struct dentry *dentry; ++ struct inode *inode; ++ struct file *h_file; ++ struct au_rdu_cookie *cookie = &rdu->cookie; ++ ++ /* VERIFY_WRITE */ ++ err = !access_ok(rdu->ent.e, rdu->sz); ++ if (unlikely(err)) { ++ err = -EFAULT; ++ AuTraceErr(err); ++ goto out; ++ } ++ rdu->rent = 0; ++ rdu->tail = rdu->ent; ++ rdu->full = 0; ++ arg.rdu = rdu; ++ arg.ent = rdu->ent; ++ arg.end = arg.ent.ul; ++ arg.end += rdu->sz; ++ ++ err = -ENOTDIR; ++ if (unlikely(!file->f_op->iterate && !file->f_op->iterate_shared)) ++ goto out; ++ ++ err = security_file_permission(file, MAY_READ); ++ AuTraceErr(err); ++ if (unlikely(err)) ++ goto out; ++ ++ dentry = file->f_path.dentry; ++ inode = d_inode(dentry); ++ inode_lock_shared(inode); ++ ++ arg.sb = inode->i_sb; ++ err = si_read_lock(arg.sb, AuLock_FLUSH | AuLock_NOPLM); ++ if (unlikely(err)) ++ goto out_mtx; ++ err = au_alive_dir(dentry); ++ if (unlikely(err)) ++ goto out_si; ++ /* todo: reval? */ ++ fi_read_lock(file); ++ ++ err = -EAGAIN; ++ if (unlikely(au_ftest_rdu(cookie->flags, CONT) ++ && cookie->generation != au_figen(file))) ++ goto out_unlock; ++ ++ err = 0; ++ if (!rdu->blk) { ++ rdu->blk = au_sbi(arg.sb)->si_rdblk; ++ if (!rdu->blk) ++ rdu->blk = au_dir_size(file, /*dentry*/NULL); ++ } ++ bbot = au_fbtop(file); ++ if (cookie->bindex < bbot) ++ cookie->bindex = bbot; ++ bbot = au_fbbot_dir(file); ++ /* AuDbg("b%d, b%d\n", cookie->bindex, bbot); */ ++ for (; !err && cookie->bindex <= bbot; ++ cookie->bindex++, cookie->h_pos = 0) { ++ h_file = au_hf_dir(file, cookie->bindex); ++ if (!h_file) ++ continue; ++ ++ au_fclr_rdu(cookie->flags, FULL); ++ err = au_rdu_do(h_file, &arg); ++ AuTraceErr(err); ++ if (unlikely(au_ftest_rdu(cookie->flags, FULL) || err)) ++ break; ++ } ++ AuDbg("rent %llu\n", rdu->rent); ++ ++ if (!err && !au_ftest_rdu(cookie->flags, CONT)) { ++ rdu->shwh = !!au_opt_test(au_sbi(arg.sb)->si_mntflags, SHWH); ++ au_fset_rdu(cookie->flags, CONT); ++ cookie->generation = au_figen(file); ++ } ++ ++ ii_read_lock_child(inode); ++ fsstack_copy_attr_atime(inode, au_h_iptr(inode, au_ibtop(inode))); ++ ii_read_unlock(inode); ++ ++out_unlock: ++ fi_read_unlock(file); ++out_si: ++ si_read_unlock(arg.sb); ++out_mtx: ++ inode_unlock_shared(inode); ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++static int au_rdu_ino(struct file *file, struct aufs_rdu *rdu) ++{ ++ int err; ++ ino_t ino; ++ unsigned long long nent; ++ union au_rdu_ent_ul *u; ++ struct au_rdu_ent ent; ++ struct super_block *sb; ++ ++ err = 0; ++ nent = rdu->nent; ++ u = &rdu->ent; ++ sb = file->f_path.dentry->d_sb; ++ si_read_lock(sb, AuLock_FLUSH); ++ while (nent-- > 0) { ++ /* unnecessary to support mmap_sem since this is a dir */ ++ err = copy_from_user(&ent, u->e, sizeof(ent)); ++ if (!err) ++ /* VERIFY_WRITE */ ++ err = !access_ok(&u->e->ino, sizeof(ino)); ++ if (unlikely(err)) { ++ err = -EFAULT; ++ AuTraceErr(err); ++ break; ++ } ++ ++ /* AuDbg("b%d, i%llu\n", ent.bindex, ent.ino); */ ++ if (!ent.wh) ++ err = au_ino(sb, ent.bindex, ent.ino, ent.type, &ino); ++ else ++ err = au_wh_ino(sb, ent.bindex, ent.ino, ent.type, ++ &ino); ++ if (unlikely(err)) { ++ AuTraceErr(err); ++ break; ++ } ++ ++ err = __put_user(ino, &u->e->ino); ++ if (unlikely(err)) { ++ err = -EFAULT; ++ AuTraceErr(err); ++ break; ++ } ++ u->ul += au_rdu_len(ent.nlen); ++ } ++ si_read_unlock(sb); ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int au_rdu_verify(struct aufs_rdu *rdu) ++{ ++ AuDbg("rdu{%llu, %p, %u | %u | %llu, %u, %u | " ++ "%llu, b%d, 0x%x, g%u}\n", ++ rdu->sz, rdu->ent.e, rdu->verify[AufsCtlRduV_SZ], ++ rdu->blk, ++ rdu->rent, rdu->shwh, rdu->full, ++ rdu->cookie.h_pos, rdu->cookie.bindex, rdu->cookie.flags, ++ rdu->cookie.generation); ++ ++ if (rdu->verify[AufsCtlRduV_SZ] == sizeof(*rdu)) ++ return 0; ++ ++ AuDbg("%u:%u\n", ++ rdu->verify[AufsCtlRduV_SZ], (unsigned int)sizeof(*rdu)); ++ return -EINVAL; ++} ++ ++long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ++{ ++ long err, e; ++ struct aufs_rdu rdu; ++ void __user *p = (void __user *)arg; ++ ++ err = copy_from_user(&rdu, p, sizeof(rdu)); ++ if (unlikely(err)) { ++ err = -EFAULT; ++ AuTraceErr(err); ++ goto out; ++ } ++ err = au_rdu_verify(&rdu); ++ if (unlikely(err)) ++ goto out; ++ ++ switch (cmd) { ++ case AUFS_CTL_RDU: ++ err = au_rdu(file, &rdu); ++ if (unlikely(err)) ++ break; ++ ++ e = copy_to_user(p, &rdu, sizeof(rdu)); ++ if (unlikely(e)) { ++ err = -EFAULT; ++ AuTraceErr(err); ++ } ++ break; ++ case AUFS_CTL_RDU_INO: ++ err = au_rdu_ino(file, &rdu); ++ break; ++ ++ default: ++ /* err = -ENOTTY; */ ++ err = -EINVAL; ++ } ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++#ifdef CONFIG_COMPAT ++long au_rdu_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ++{ ++ long err, e; ++ struct aufs_rdu rdu; ++ void __user *p = compat_ptr(arg); ++ ++ /* todo: get_user()? */ ++ err = copy_from_user(&rdu, p, sizeof(rdu)); ++ if (unlikely(err)) { ++ err = -EFAULT; ++ AuTraceErr(err); ++ goto out; ++ } ++ rdu.ent.e = compat_ptr(rdu.ent.ul); ++ err = au_rdu_verify(&rdu); ++ if (unlikely(err)) ++ goto out; ++ ++ switch (cmd) { ++ case AUFS_CTL_RDU: ++ err = au_rdu(file, &rdu); ++ if (unlikely(err)) ++ break; ++ ++ rdu.ent.ul = ptr_to_compat(rdu.ent.e); ++ rdu.tail.ul = ptr_to_compat(rdu.tail.e); ++ e = copy_to_user(p, &rdu, sizeof(rdu)); ++ if (unlikely(e)) { ++ err = -EFAULT; ++ AuTraceErr(err); ++ } ++ break; ++ case AUFS_CTL_RDU_INO: ++ err = au_rdu_ino(file, &rdu); ++ break; ++ ++ default: ++ /* err = -ENOTTY; */ ++ err = -EINVAL; ++ } ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++#endif +diff -Nurp linux-5.4/fs/aufs/rwsem.h linux-5.4-aufs/fs/aufs/rwsem.h +--- linux-5.4/fs/aufs/rwsem.h 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/rwsem.h 2019-11-28 01:25:59.067925618 +0200 +@@ -0,0 +1,60 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * simple read-write semaphore wrappers ++ */ ++ ++#ifndef __AUFS_RWSEM_H__ ++#define __AUFS_RWSEM_H__ ++ ++#ifdef __KERNEL__ ++ ++#include "debug.h" ++ ++/* in the future, the name 'au_rwsem' will be totally gone */ ++#define au_rwsem rw_semaphore ++ ++/* to debug easier, do not make them inlined functions */ ++#define AuRwMustNoWaiters(rw) AuDebugOn(rwsem_is_contended(rw)) ++/* rwsem_is_locked() is unusable */ ++#define AuRwMustReadLock(rw) AuDebugOn(!lockdep_recursing(current) \ ++ && debug_locks \ ++ && !lockdep_is_held_type(rw, 1)) ++#define AuRwMustWriteLock(rw) AuDebugOn(!lockdep_recursing(current) \ ++ && debug_locks \ ++ && !lockdep_is_held_type(rw, 0)) ++#define AuRwMustAnyLock(rw) AuDebugOn(!lockdep_recursing(current) \ ++ && debug_locks \ ++ && !lockdep_is_held(rw)) ++#define AuRwDestroy(rw) AuDebugOn(!lockdep_recursing(current) \ ++ && debug_locks \ ++ && lockdep_is_held(rw)) ++ ++#define au_rw_init(rw) init_rwsem(rw) ++ ++#define au_rw_init_wlock(rw) do { \ ++ au_rw_init(rw); \ ++ down_write(rw); \ ++ } while (0) ++ ++#define au_rw_init_wlock_nested(rw, lsc) do { \ ++ au_rw_init(rw); \ ++ down_write_nested(rw, lsc); \ ++ } while (0) ++ ++#define au_rw_read_lock(rw) down_read(rw) ++#define au_rw_read_lock_nested(rw, lsc) down_read_nested(rw, lsc) ++#define au_rw_read_unlock(rw) up_read(rw) ++#define au_rw_dgrade_lock(rw) downgrade_write(rw) ++#define au_rw_write_lock(rw) down_write(rw) ++#define au_rw_write_lock_nested(rw, lsc) down_write_nested(rw, lsc) ++#define au_rw_write_unlock(rw) up_write(rw) ++/* why is not _nested version defined? */ ++#define au_rw_read_trylock(rw) down_read_trylock(rw) ++#define au_rw_write_trylock(rw) down_write_trylock(rw) ++ ++#endif /* __KERNEL__ */ ++#endif /* __AUFS_RWSEM_H__ */ +diff -Nurp linux-5.4/fs/aufs/sbinfo.c linux-5.4-aufs/fs/aufs/sbinfo.c +--- linux-5.4/fs/aufs/sbinfo.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/sbinfo.c 2019-11-28 01:25:59.067925618 +0200 +@@ -0,0 +1,301 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * superblock private data ++ */ ++ ++#include ++#include "aufs.h" ++ ++/* ++ * they are necessary regardless sysfs is disabled. ++ */ ++void au_si_free(struct kobject *kobj) ++{ ++ int i; ++ struct au_sbinfo *sbinfo; ++ char *locked __maybe_unused; /* debug only */ ++ ++ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj); ++ for (i = 0; i < AuPlink_NHASH; i++) ++ AuDebugOn(!hlist_bl_empty(sbinfo->si_plink + i)); ++ AuDebugOn(atomic_read(&sbinfo->si_nowait.nw_len)); ++ ++ AuLCntZero(au_lcnt_read(&sbinfo->si_ninodes, /*do_rev*/0)); ++ au_lcnt_fin(&sbinfo->si_ninodes, /*do_sync*/0); ++ AuLCntZero(au_lcnt_read(&sbinfo->si_nfiles, /*do_rev*/0)); ++ au_lcnt_fin(&sbinfo->si_nfiles, /*do_sync*/0); ++ ++ dbgaufs_si_fin(sbinfo); ++ au_rw_write_lock(&sbinfo->si_rwsem); ++ au_br_free(sbinfo); ++ au_rw_write_unlock(&sbinfo->si_rwsem); ++ ++ au_kfree_try_rcu(sbinfo->si_branch); ++ mutex_destroy(&sbinfo->si_xib_mtx); ++ AuRwDestroy(&sbinfo->si_rwsem); ++ ++ au_lcnt_wait_for_fin(&sbinfo->si_ninodes); ++ /* si_nfiles is waited too */ ++ au_kfree_rcu(sbinfo); ++} ++ ++int au_si_alloc(struct super_block *sb) ++{ ++ int err, i; ++ struct au_sbinfo *sbinfo; ++ ++ err = -ENOMEM; ++ sbinfo = kzalloc(sizeof(*sbinfo), GFP_NOFS); ++ if (unlikely(!sbinfo)) ++ goto out; ++ ++ /* will be reallocated separately */ ++ sbinfo->si_branch = kzalloc(sizeof(*sbinfo->si_branch), GFP_NOFS); ++ if (unlikely(!sbinfo->si_branch)) ++ goto out_sbinfo; ++ ++ err = sysaufs_si_init(sbinfo); ++ if (!err) { ++ dbgaufs_si_null(sbinfo); ++ err = dbgaufs_si_init(sbinfo); ++ if (unlikely(err)) ++ kobject_put(&sbinfo->si_kobj); ++ } ++ if (unlikely(err)) ++ goto out_br; ++ ++ au_nwt_init(&sbinfo->si_nowait); ++ au_rw_init_wlock(&sbinfo->si_rwsem); ++ ++ au_lcnt_init(&sbinfo->si_ninodes, /*release*/NULL); ++ au_lcnt_init(&sbinfo->si_nfiles, /*release*/NULL); ++ ++ sbinfo->si_bbot = -1; ++ sbinfo->si_last_br_id = AUFS_BRANCH_MAX / 2; ++ ++ sbinfo->si_wbr_copyup = AuWbrCopyup_Def; ++ sbinfo->si_wbr_create = AuWbrCreate_Def; ++ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + sbinfo->si_wbr_copyup; ++ sbinfo->si_wbr_create_ops = au_wbr_create_ops + sbinfo->si_wbr_create; ++ ++ au_fhsm_init(sbinfo); ++ ++ sbinfo->si_mntflags = au_opts_plink(AuOpt_Def); ++ ++ sbinfo->si_xino_jiffy = jiffies; ++ sbinfo->si_xino_expire ++ = msecs_to_jiffies(AUFS_XINO_DEF_SEC * MSEC_PER_SEC); ++ mutex_init(&sbinfo->si_xib_mtx); ++ /* leave si_xib_last_pindex and si_xib_next_bit */ ++ ++ INIT_HLIST_BL_HEAD(&sbinfo->si_aopen); ++ ++ sbinfo->si_rdcache = msecs_to_jiffies(AUFS_RDCACHE_DEF * MSEC_PER_SEC); ++ sbinfo->si_rdblk = AUFS_RDBLK_DEF; ++ sbinfo->si_rdhash = AUFS_RDHASH_DEF; ++ sbinfo->si_dirwh = AUFS_DIRWH_DEF; ++ ++ for (i = 0; i < AuPlink_NHASH; i++) ++ INIT_HLIST_BL_HEAD(sbinfo->si_plink + i); ++ init_waitqueue_head(&sbinfo->si_plink_wq); ++ spin_lock_init(&sbinfo->si_plink_maint_lock); ++ ++ INIT_HLIST_BL_HEAD(&sbinfo->si_files); ++ ++ /* with getattr by default */ ++ sbinfo->si_iop_array = aufs_iop; ++ ++ /* leave other members for sysaufs and si_mnt. */ ++ sbinfo->si_sb = sb; ++ sb->s_fs_info = sbinfo; ++ si_pid_set(sb); ++ return 0; /* success */ ++ ++out_br: ++ au_kfree_try_rcu(sbinfo->si_branch); ++out_sbinfo: ++ au_kfree_rcu(sbinfo); ++out: ++ return err; ++} ++ ++int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr, int may_shrink) ++{ ++ int err, sz; ++ struct au_branch **brp; ++ ++ AuRwMustWriteLock(&sbinfo->si_rwsem); ++ ++ err = -ENOMEM; ++ sz = sizeof(*brp) * (sbinfo->si_bbot + 1); ++ if (unlikely(!sz)) ++ sz = sizeof(*brp); ++ brp = au_kzrealloc(sbinfo->si_branch, sz, sizeof(*brp) * nbr, GFP_NOFS, ++ may_shrink); ++ if (brp) { ++ sbinfo->si_branch = brp; ++ err = 0; ++ } ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++unsigned int au_sigen_inc(struct super_block *sb) ++{ ++ unsigned int gen; ++ struct inode *inode; ++ ++ SiMustWriteLock(sb); ++ ++ gen = ++au_sbi(sb)->si_generation; ++ au_update_digen(sb->s_root); ++ inode = d_inode(sb->s_root); ++ au_update_iigen(inode, /*half*/0); ++ inode_inc_iversion(inode); ++ return gen; ++} ++ ++aufs_bindex_t au_new_br_id(struct super_block *sb) ++{ ++ aufs_bindex_t br_id; ++ int i; ++ struct au_sbinfo *sbinfo; ++ ++ SiMustWriteLock(sb); ++ ++ sbinfo = au_sbi(sb); ++ for (i = 0; i <= AUFS_BRANCH_MAX; i++) { ++ br_id = ++sbinfo->si_last_br_id; ++ AuDebugOn(br_id < 0); ++ if (br_id && au_br_index(sb, br_id) < 0) ++ return br_id; ++ } ++ ++ return -1; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* it is ok that new 'nwt' tasks are appended while we are sleeping */ ++int si_read_lock(struct super_block *sb, int flags) ++{ ++ int err; ++ ++ err = 0; ++ if (au_ftest_lock(flags, FLUSH)) ++ au_nwt_flush(&au_sbi(sb)->si_nowait); ++ ++ si_noflush_read_lock(sb); ++ err = au_plink_maint(sb, flags); ++ if (unlikely(err)) ++ si_read_unlock(sb); ++ ++ return err; ++} ++ ++int si_write_lock(struct super_block *sb, int flags) ++{ ++ int err; ++ ++ if (au_ftest_lock(flags, FLUSH)) ++ au_nwt_flush(&au_sbi(sb)->si_nowait); ++ ++ si_noflush_write_lock(sb); ++ err = au_plink_maint(sb, flags); ++ if (unlikely(err)) ++ si_write_unlock(sb); ++ ++ return err; ++} ++ ++/* dentry and super_block lock. call at entry point */ ++int aufs_read_lock(struct dentry *dentry, int flags) ++{ ++ int err; ++ struct super_block *sb; ++ ++ sb = dentry->d_sb; ++ err = si_read_lock(sb, flags); ++ if (unlikely(err)) ++ goto out; ++ ++ if (au_ftest_lock(flags, DW)) ++ di_write_lock_child(dentry); ++ else ++ di_read_lock_child(dentry, flags); ++ ++ if (au_ftest_lock(flags, GEN)) { ++ err = au_digen_test(dentry, au_sigen(sb)); ++ if (!au_opt_test(au_mntflags(sb), UDBA_NONE)) ++ AuDebugOn(!err && au_dbrange_test(dentry)); ++ else if (!err) ++ err = au_dbrange_test(dentry); ++ if (unlikely(err)) ++ aufs_read_unlock(dentry, flags); ++ } ++ ++out: ++ return err; ++} ++ ++void aufs_read_unlock(struct dentry *dentry, int flags) ++{ ++ if (au_ftest_lock(flags, DW)) ++ di_write_unlock(dentry); ++ else ++ di_read_unlock(dentry, flags); ++ si_read_unlock(dentry->d_sb); ++} ++ ++void aufs_write_lock(struct dentry *dentry) ++{ ++ si_write_lock(dentry->d_sb, AuLock_FLUSH | AuLock_NOPLMW); ++ di_write_lock_child(dentry); ++} ++ ++void aufs_write_unlock(struct dentry *dentry) ++{ ++ di_write_unlock(dentry); ++ si_write_unlock(dentry->d_sb); ++} ++ ++int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags) ++{ ++ int err; ++ unsigned int sigen; ++ struct super_block *sb; ++ ++ sb = d1->d_sb; ++ err = si_read_lock(sb, flags); ++ if (unlikely(err)) ++ goto out; ++ ++ di_write_lock2_child(d1, d2, au_ftest_lock(flags, DIRS)); ++ ++ if (au_ftest_lock(flags, GEN)) { ++ sigen = au_sigen(sb); ++ err = au_digen_test(d1, sigen); ++ AuDebugOn(!err && au_dbrange_test(d1)); ++ if (!err) { ++ err = au_digen_test(d2, sigen); ++ AuDebugOn(!err && au_dbrange_test(d2)); ++ } ++ if (unlikely(err)) ++ aufs_read_and_write_unlock2(d1, d2); ++ } ++ ++out: ++ return err; ++} ++ ++void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2) ++{ ++ di_write_unlock2(d1, d2); ++ si_read_unlock(d1->d_sb); ++} +diff -Nurp linux-5.4/fs/aufs/super.c linux-5.4-aufs/fs/aufs/super.c +--- linux-5.4/fs/aufs/super.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/super.c 2019-11-28 01:25:59.067925618 +0200 +@@ -0,0 +1,1034 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * mount and super_block operations ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include "aufs.h" ++ ++/* ++ * super_operations ++ */ ++static struct inode *aufs_alloc_inode(struct super_block *sb __maybe_unused) ++{ ++ struct au_icntnr *c; ++ ++ c = au_cache_alloc_icntnr(); ++ if (c) { ++ au_icntnr_init(c); ++ inode_set_iversion(&c->vfs_inode, 1); /* sigen(sb); */ ++ c->iinfo.ii_hinode = NULL; ++ return &c->vfs_inode; ++ } ++ return NULL; ++} ++ ++static void aufs_destroy_inode(struct inode *inode) ++{ ++ if (!au_is_bad_inode(inode)) ++ au_iinfo_fin(inode); ++} ++ ++static void aufs_free_inode(struct inode *inode) ++{ ++ au_cache_free_icntnr(container_of(inode, struct au_icntnr, vfs_inode)); ++} ++ ++struct inode *au_iget_locked(struct super_block *sb, ino_t ino) ++{ ++ struct inode *inode; ++ int err; ++ ++ inode = iget_locked(sb, ino); ++ if (unlikely(!inode)) { ++ inode = ERR_PTR(-ENOMEM); ++ goto out; ++ } ++ if (!(inode->i_state & I_NEW)) ++ goto out; ++ ++ err = au_xigen_new(inode); ++ if (!err) ++ err = au_iinfo_init(inode); ++ if (!err) ++ inode_inc_iversion(inode); ++ else { ++ iget_failed(inode); ++ inode = ERR_PTR(err); ++ } ++ ++out: ++ /* never return NULL */ ++ AuDebugOn(!inode); ++ AuTraceErrPtr(inode); ++ return inode; ++} ++ ++/* lock free root dinfo */ ++static int au_show_brs(struct seq_file *seq, struct super_block *sb) ++{ ++ int err; ++ aufs_bindex_t bindex, bbot; ++ struct path path; ++ struct au_hdentry *hdp; ++ struct au_branch *br; ++ au_br_perm_str_t perm; ++ ++ err = 0; ++ bbot = au_sbbot(sb); ++ bindex = 0; ++ hdp = au_hdentry(au_di(sb->s_root), bindex); ++ for (; !err && bindex <= bbot; bindex++, hdp++) { ++ br = au_sbr(sb, bindex); ++ path.mnt = au_br_mnt(br); ++ path.dentry = hdp->hd_dentry; ++ err = au_seq_path(seq, &path); ++ if (!err) { ++ au_optstr_br_perm(&perm, br->br_perm); ++ seq_printf(seq, "=%s", perm.a); ++ if (bindex != bbot) ++ seq_putc(seq, ':'); ++ } ++ } ++ if (unlikely(err || seq_has_overflowed(seq))) ++ err = -E2BIG; ++ ++ return err; ++} ++ ++static void au_gen_fmt(char *fmt, int len __maybe_unused, const char *pat, ++ const char *append) ++{ ++ char *p; ++ ++ p = fmt; ++ while (*pat != ':') ++ *p++ = *pat++; ++ *p++ = *pat++; ++ strcpy(p, append); ++ AuDebugOn(strlen(fmt) >= len); ++} ++ ++static void au_show_wbr_create(struct seq_file *m, int v, ++ struct au_sbinfo *sbinfo) ++{ ++ const char *pat; ++ char fmt[32]; ++ struct au_wbr_mfs *mfs; ++ ++ AuRwMustAnyLock(&sbinfo->si_rwsem); ++ ++ seq_puts(m, ",create="); ++ pat = au_optstr_wbr_create(v); ++ mfs = &sbinfo->si_wbr_mfs; ++ switch (v) { ++ case AuWbrCreate_TDP: ++ case AuWbrCreate_RR: ++ case AuWbrCreate_MFS: ++ case AuWbrCreate_PMFS: ++ seq_puts(m, pat); ++ break; ++ case AuWbrCreate_MFSRR: ++ case AuWbrCreate_TDMFS: ++ case AuWbrCreate_PMFSRR: ++ au_gen_fmt(fmt, sizeof(fmt), pat, "%llu"); ++ seq_printf(m, fmt, mfs->mfsrr_watermark); ++ break; ++ case AuWbrCreate_MFSV: ++ case AuWbrCreate_PMFSV: ++ au_gen_fmt(fmt, sizeof(fmt), pat, "%lu"); ++ seq_printf(m, fmt, ++ jiffies_to_msecs(mfs->mfs_expire) ++ / MSEC_PER_SEC); ++ break; ++ case AuWbrCreate_MFSRRV: ++ case AuWbrCreate_TDMFSV: ++ case AuWbrCreate_PMFSRRV: ++ au_gen_fmt(fmt, sizeof(fmt), pat, "%llu:%lu"); ++ seq_printf(m, fmt, mfs->mfsrr_watermark, ++ jiffies_to_msecs(mfs->mfs_expire) / MSEC_PER_SEC); ++ break; ++ default: ++ BUG(); ++ } ++} ++ ++static int au_show_xino(struct seq_file *seq, struct super_block *sb) ++{ ++#ifdef CONFIG_SYSFS ++ return 0; ++#else ++ int err; ++ const int len = sizeof(AUFS_XINO_FNAME) - 1; ++ aufs_bindex_t bindex, brid; ++ struct qstr *name; ++ struct file *f; ++ struct dentry *d, *h_root; ++ struct au_branch *br; ++ ++ AuRwMustAnyLock(&sbinfo->si_rwsem); ++ ++ err = 0; ++ f = au_sbi(sb)->si_xib; ++ if (!f) ++ goto out; ++ ++ /* stop printing the default xino path on the first writable branch */ ++ h_root = NULL; ++ bindex = au_xi_root(sb, f->f_path.dentry); ++ if (bindex >= 0) { ++ br = au_sbr_sb(sb, bindex); ++ h_root = au_br_dentry(br); ++ } ++ ++ d = f->f_path.dentry; ++ name = &d->d_name; ++ /* safe ->d_parent because the file is unlinked */ ++ if (d->d_parent == h_root ++ && name->len == len ++ && !memcmp(name->name, AUFS_XINO_FNAME, len)) ++ goto out; ++ ++ seq_puts(seq, ",xino="); ++ err = au_xino_path(seq, f); ++ ++out: ++ return err; ++#endif ++} ++ ++/* seq_file will re-call me in case of too long string */ ++static int aufs_show_options(struct seq_file *m, struct dentry *dentry) ++{ ++ int err; ++ unsigned int mnt_flags, v; ++ struct super_block *sb; ++ struct au_sbinfo *sbinfo; ++ ++#define AuBool(name, str) do { \ ++ v = au_opt_test(mnt_flags, name); \ ++ if (v != au_opt_test(AuOpt_Def, name)) \ ++ seq_printf(m, ",%s" #str, v ? "" : "no"); \ ++} while (0) ++ ++#define AuStr(name, str) do { \ ++ v = mnt_flags & AuOptMask_##name; \ ++ if (v != (AuOpt_Def & AuOptMask_##name)) \ ++ seq_printf(m, "," #str "=%s", au_optstr_##str(v)); \ ++} while (0) ++ ++#define AuUInt(name, str, val) do { \ ++ if (val != AUFS_##name##_DEF) \ ++ seq_printf(m, "," #str "=%u", val); \ ++} while (0) ++ ++ sb = dentry->d_sb; ++ if (sb->s_flags & SB_POSIXACL) ++ seq_puts(m, ",acl"); ++#if 0 ++ if (sb->s_flags & SB_I_VERSION) ++ seq_puts(m, ",i_version"); ++#endif ++ ++ /* lock free root dinfo */ ++ si_noflush_read_lock(sb); ++ sbinfo = au_sbi(sb); ++ seq_printf(m, ",si=%lx", sysaufs_si_id(sbinfo)); ++ ++ mnt_flags = au_mntflags(sb); ++ if (au_opt_test(mnt_flags, XINO)) { ++ err = au_show_xino(m, sb); ++ if (unlikely(err)) ++ goto out; ++ } else ++ seq_puts(m, ",noxino"); ++ ++ AuBool(TRUNC_XINO, trunc_xino); ++ AuStr(UDBA, udba); ++ AuBool(SHWH, shwh); ++ AuBool(PLINK, plink); ++ AuBool(DIO, dio); ++ AuBool(DIRPERM1, dirperm1); ++ ++ v = sbinfo->si_wbr_create; ++ if (v != AuWbrCreate_Def) ++ au_show_wbr_create(m, v, sbinfo); ++ ++ v = sbinfo->si_wbr_copyup; ++ if (v != AuWbrCopyup_Def) ++ seq_printf(m, ",cpup=%s", au_optstr_wbr_copyup(v)); ++ ++ v = au_opt_test(mnt_flags, ALWAYS_DIROPQ); ++ if (v != au_opt_test(AuOpt_Def, ALWAYS_DIROPQ)) ++ seq_printf(m, ",diropq=%c", v ? 'a' : 'w'); ++ ++ AuUInt(DIRWH, dirwh, sbinfo->si_dirwh); ++ ++ v = jiffies_to_msecs(sbinfo->si_rdcache) / MSEC_PER_SEC; ++ AuUInt(RDCACHE, rdcache, v); ++ ++ AuUInt(RDBLK, rdblk, sbinfo->si_rdblk); ++ AuUInt(RDHASH, rdhash, sbinfo->si_rdhash); ++ ++ au_fhsm_show(m, sbinfo); ++ ++ AuBool(DIRREN, dirren); ++ AuBool(SUM, sum); ++ /* AuBool(SUM_W, wsum); */ ++ AuBool(WARN_PERM, warn_perm); ++ AuBool(VERBOSE, verbose); ++ ++out: ++ /* be sure to print "br:" last */ ++ if (!sysaufs_brs) { ++ seq_puts(m, ",br:"); ++ au_show_brs(m, sb); ++ } ++ si_read_unlock(sb); ++ return 0; ++ ++#undef AuBool ++#undef AuStr ++#undef AuUInt ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* sum mode which returns the summation for statfs(2) */ ++ ++static u64 au_add_till_max(u64 a, u64 b) ++{ ++ u64 old; ++ ++ old = a; ++ a += b; ++ if (old <= a) ++ return a; ++ return ULLONG_MAX; ++} ++ ++static u64 au_mul_till_max(u64 a, long mul) ++{ ++ u64 old; ++ ++ old = a; ++ a *= mul; ++ if (old <= a) ++ return a; ++ return ULLONG_MAX; ++} ++ ++static int au_statfs_sum(struct super_block *sb, struct kstatfs *buf) ++{ ++ int err; ++ long bsize, factor; ++ u64 blocks, bfree, bavail, files, ffree; ++ aufs_bindex_t bbot, bindex, i; ++ unsigned char shared; ++ struct path h_path; ++ struct super_block *h_sb; ++ ++ err = 0; ++ bsize = LONG_MAX; ++ files = 0; ++ ffree = 0; ++ blocks = 0; ++ bfree = 0; ++ bavail = 0; ++ bbot = au_sbbot(sb); ++ for (bindex = 0; bindex <= bbot; bindex++) { ++ h_path.mnt = au_sbr_mnt(sb, bindex); ++ h_sb = h_path.mnt->mnt_sb; ++ shared = 0; ++ for (i = 0; !shared && i < bindex; i++) ++ shared = (au_sbr_sb(sb, i) == h_sb); ++ if (shared) ++ continue; ++ ++ /* sb->s_root for NFS is unreliable */ ++ h_path.dentry = h_path.mnt->mnt_root; ++ err = vfs_statfs(&h_path, buf); ++ if (unlikely(err)) ++ goto out; ++ ++ if (bsize > buf->f_bsize) { ++ /* ++ * we will reduce bsize, so we have to expand blocks ++ * etc. to match them again ++ */ ++ factor = (bsize / buf->f_bsize); ++ blocks = au_mul_till_max(blocks, factor); ++ bfree = au_mul_till_max(bfree, factor); ++ bavail = au_mul_till_max(bavail, factor); ++ bsize = buf->f_bsize; ++ } ++ ++ factor = (buf->f_bsize / bsize); ++ blocks = au_add_till_max(blocks, ++ au_mul_till_max(buf->f_blocks, factor)); ++ bfree = au_add_till_max(bfree, ++ au_mul_till_max(buf->f_bfree, factor)); ++ bavail = au_add_till_max(bavail, ++ au_mul_till_max(buf->f_bavail, factor)); ++ files = au_add_till_max(files, buf->f_files); ++ ffree = au_add_till_max(ffree, buf->f_ffree); ++ } ++ ++ buf->f_bsize = bsize; ++ buf->f_blocks = blocks; ++ buf->f_bfree = bfree; ++ buf->f_bavail = bavail; ++ buf->f_files = files; ++ buf->f_ffree = ffree; ++ buf->f_frsize = 0; ++ ++out: ++ return err; ++} ++ ++static int aufs_statfs(struct dentry *dentry, struct kstatfs *buf) ++{ ++ int err; ++ struct path h_path; ++ struct super_block *sb; ++ ++ /* lock free root dinfo */ ++ sb = dentry->d_sb; ++ si_noflush_read_lock(sb); ++ if (!au_opt_test(au_mntflags(sb), SUM)) { ++ /* sb->s_root for NFS is unreliable */ ++ h_path.mnt = au_sbr_mnt(sb, 0); ++ h_path.dentry = h_path.mnt->mnt_root; ++ err = vfs_statfs(&h_path, buf); ++ } else ++ err = au_statfs_sum(sb, buf); ++ si_read_unlock(sb); ++ ++ if (!err) { ++ buf->f_type = AUFS_SUPER_MAGIC; ++ buf->f_namelen = AUFS_MAX_NAMELEN; ++ memset(&buf->f_fsid, 0, sizeof(buf->f_fsid)); ++ } ++ /* buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1; */ ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int aufs_sync_fs(struct super_block *sb, int wait) ++{ ++ int err, e; ++ aufs_bindex_t bbot, bindex; ++ struct au_branch *br; ++ struct super_block *h_sb; ++ ++ err = 0; ++ si_noflush_read_lock(sb); ++ bbot = au_sbbot(sb); ++ for (bindex = 0; bindex <= bbot; bindex++) { ++ br = au_sbr(sb, bindex); ++ if (!au_br_writable(br->br_perm)) ++ continue; ++ ++ h_sb = au_sbr_sb(sb, bindex); ++ e = vfsub_sync_filesystem(h_sb, wait); ++ if (unlikely(e && !err)) ++ err = e; ++ /* go on even if an error happens */ ++ } ++ si_read_unlock(sb); ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* final actions when unmounting a file system */ ++static void aufs_put_super(struct super_block *sb) ++{ ++ struct au_sbinfo *sbinfo; ++ ++ sbinfo = au_sbi(sb); ++ if (sbinfo) ++ kobject_put(&sbinfo->si_kobj); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++void *au_array_alloc(unsigned long long *hint, au_arraycb_t cb, ++ struct super_block *sb, void *arg) ++{ ++ void *array; ++ unsigned long long n, sz; ++ ++ array = NULL; ++ n = 0; ++ if (!*hint) ++ goto out; ++ ++ if (*hint > ULLONG_MAX / sizeof(array)) { ++ array = ERR_PTR(-EMFILE); ++ pr_err("hint %llu\n", *hint); ++ goto out; ++ } ++ ++ sz = sizeof(array) * *hint; ++ array = kzalloc(sz, GFP_NOFS); ++ if (unlikely(!array)) ++ array = vzalloc(sz); ++ if (unlikely(!array)) { ++ array = ERR_PTR(-ENOMEM); ++ goto out; ++ } ++ ++ n = cb(sb, array, *hint, arg); ++ AuDebugOn(n > *hint); ++ ++out: ++ *hint = n; ++ return array; ++} ++ ++static unsigned long long au_iarray_cb(struct super_block *sb, void *a, ++ unsigned long long max __maybe_unused, ++ void *arg) ++{ ++ unsigned long long n; ++ struct inode **p, *inode; ++ struct list_head *head; ++ ++ n = 0; ++ p = a; ++ head = arg; ++ spin_lock(&sb->s_inode_list_lock); ++ list_for_each_entry(inode, head, i_sb_list) { ++ if (!au_is_bad_inode(inode) ++ && au_ii(inode)->ii_btop >= 0) { ++ spin_lock(&inode->i_lock); ++ if (atomic_read(&inode->i_count)) { ++ au_igrab(inode); ++ *p++ = inode; ++ n++; ++ AuDebugOn(n > max); ++ } ++ spin_unlock(&inode->i_lock); ++ } ++ } ++ spin_unlock(&sb->s_inode_list_lock); ++ ++ return n; ++} ++ ++struct inode **au_iarray_alloc(struct super_block *sb, unsigned long long *max) ++{ ++ struct au_sbinfo *sbi; ++ ++ sbi = au_sbi(sb); ++ *max = au_lcnt_read(&sbi->si_ninodes, /*do_rev*/1); ++ return au_array_alloc(max, au_iarray_cb, sb, &sb->s_inodes); ++} ++ ++void au_iarray_free(struct inode **a, unsigned long long max) ++{ ++ unsigned long long ull; ++ ++ for (ull = 0; ull < max; ull++) ++ iput(a[ull]); ++ kvfree(a); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * refresh dentry and inode at remount time. ++ */ ++/* todo: consolidate with simple_reval_dpath() and au_reval_for_attr() */ ++static int au_do_refresh(struct dentry *dentry, unsigned int dir_flags, ++ struct dentry *parent) ++{ ++ int err; ++ ++ di_write_lock_child(dentry); ++ di_read_lock_parent(parent, AuLock_IR); ++ err = au_refresh_dentry(dentry, parent); ++ if (!err && dir_flags) ++ au_hn_reset(d_inode(dentry), dir_flags); ++ di_read_unlock(parent, AuLock_IR); ++ di_write_unlock(dentry); ++ ++ return err; ++} ++ ++static int au_do_refresh_d(struct dentry *dentry, unsigned int sigen, ++ struct au_sbinfo *sbinfo, ++ const unsigned int dir_flags, unsigned int do_idop) ++{ ++ int err; ++ struct dentry *parent; ++ ++ err = 0; ++ parent = dget_parent(dentry); ++ if (!au_digen_test(parent, sigen) && au_digen_test(dentry, sigen)) { ++ if (d_really_is_positive(dentry)) { ++ if (!d_is_dir(dentry)) ++ err = au_do_refresh(dentry, /*dir_flags*/0, ++ parent); ++ else { ++ err = au_do_refresh(dentry, dir_flags, parent); ++ if (unlikely(err)) ++ au_fset_si(sbinfo, FAILED_REFRESH_DIR); ++ } ++ } else ++ err = au_do_refresh(dentry, /*dir_flags*/0, parent); ++ AuDbgDentry(dentry); ++ } ++ dput(parent); ++ ++ if (!err) { ++ if (do_idop) ++ au_refresh_dop(dentry, /*force_reval*/0); ++ } else ++ au_refresh_dop(dentry, /*force_reval*/1); ++ ++ AuTraceErr(err); ++ return err; ++} ++ ++static int au_refresh_d(struct super_block *sb, unsigned int do_idop) ++{ ++ int err, i, j, ndentry, e; ++ unsigned int sigen; ++ struct au_dcsub_pages dpages; ++ struct au_dpage *dpage; ++ struct dentry **dentries, *d; ++ struct au_sbinfo *sbinfo; ++ struct dentry *root = sb->s_root; ++ const unsigned int dir_flags = au_hi_flags(d_inode(root), /*isdir*/1); ++ ++ if (do_idop) ++ au_refresh_dop(root, /*force_reval*/0); ++ ++ err = au_dpages_init(&dpages, GFP_NOFS); ++ if (unlikely(err)) ++ goto out; ++ err = au_dcsub_pages(&dpages, root, NULL, NULL); ++ if (unlikely(err)) ++ goto out_dpages; ++ ++ sigen = au_sigen(sb); ++ sbinfo = au_sbi(sb); ++ for (i = 0; i < dpages.ndpage; i++) { ++ dpage = dpages.dpages + i; ++ dentries = dpage->dentries; ++ ndentry = dpage->ndentry; ++ for (j = 0; j < ndentry; j++) { ++ d = dentries[j]; ++ e = au_do_refresh_d(d, sigen, sbinfo, dir_flags, ++ do_idop); ++ if (unlikely(e && !err)) ++ err = e; ++ /* go on even err */ ++ } ++ } ++ ++out_dpages: ++ au_dpages_free(&dpages); ++out: ++ return err; ++} ++ ++static int au_refresh_i(struct super_block *sb, unsigned int do_idop) ++{ ++ int err, e; ++ unsigned int sigen; ++ unsigned long long max, ull; ++ struct inode *inode, **array; ++ ++ array = au_iarray_alloc(sb, &max); ++ err = PTR_ERR(array); ++ if (IS_ERR(array)) ++ goto out; ++ ++ err = 0; ++ sigen = au_sigen(sb); ++ for (ull = 0; ull < max; ull++) { ++ inode = array[ull]; ++ if (unlikely(!inode)) ++ break; ++ ++ e = 0; ++ ii_write_lock_child(inode); ++ if (au_iigen(inode, NULL) != sigen) { ++ e = au_refresh_hinode_self(inode); ++ if (unlikely(e)) { ++ au_refresh_iop(inode, /*force_getattr*/1); ++ pr_err("error %d, i%lu\n", e, inode->i_ino); ++ if (!err) ++ err = e; ++ /* go on even if err */ ++ } ++ } ++ if (!e && do_idop) ++ au_refresh_iop(inode, /*force_getattr*/0); ++ ii_write_unlock(inode); ++ } ++ ++ au_iarray_free(array, max); ++ ++out: ++ return err; ++} ++ ++static void au_remount_refresh(struct super_block *sb, unsigned int do_idop) ++{ ++ int err, e; ++ unsigned int udba; ++ aufs_bindex_t bindex, bbot; ++ struct dentry *root; ++ struct inode *inode; ++ struct au_branch *br; ++ struct au_sbinfo *sbi; ++ ++ au_sigen_inc(sb); ++ sbi = au_sbi(sb); ++ au_fclr_si(sbi, FAILED_REFRESH_DIR); ++ ++ root = sb->s_root; ++ DiMustNoWaiters(root); ++ inode = d_inode(root); ++ IiMustNoWaiters(inode); ++ ++ udba = au_opt_udba(sb); ++ bbot = au_sbbot(sb); ++ for (bindex = 0; bindex <= bbot; bindex++) { ++ br = au_sbr(sb, bindex); ++ err = au_hnotify_reset_br(udba, br, br->br_perm); ++ if (unlikely(err)) ++ AuIOErr("hnotify failed on br %d, %d, ignored\n", ++ bindex, err); ++ /* go on even if err */ ++ } ++ au_hn_reset(inode, au_hi_flags(inode, /*isdir*/1)); ++ ++ if (do_idop) { ++ if (au_ftest_si(sbi, NO_DREVAL)) { ++ AuDebugOn(sb->s_d_op == &aufs_dop_noreval); ++ sb->s_d_op = &aufs_dop_noreval; ++ AuDebugOn(sbi->si_iop_array == aufs_iop_nogetattr); ++ sbi->si_iop_array = aufs_iop_nogetattr; ++ } else { ++ AuDebugOn(sb->s_d_op == &aufs_dop); ++ sb->s_d_op = &aufs_dop; ++ AuDebugOn(sbi->si_iop_array == aufs_iop); ++ sbi->si_iop_array = aufs_iop; ++ } ++ pr_info("reset to %ps and %ps\n", ++ sb->s_d_op, sbi->si_iop_array); ++ } ++ ++ di_write_unlock(root); ++ err = au_refresh_d(sb, do_idop); ++ e = au_refresh_i(sb, do_idop); ++ if (unlikely(e && !err)) ++ err = e; ++ /* aufs_write_lock() calls ..._child() */ ++ di_write_lock_child(root); ++ ++ au_cpup_attr_all(inode, /*force*/1); ++ ++ if (unlikely(err)) ++ AuIOErr("refresh failed, ignored, %d\n", err); ++} ++ ++/* stop extra interpretation of errno in mount(8), and strange error messages */ ++static int cvt_err(int err) ++{ ++ AuTraceErr(err); ++ ++ switch (err) { ++ case -ENOENT: ++ case -ENOTDIR: ++ case -EEXIST: ++ case -EIO: ++ err = -EINVAL; ++ } ++ return err; ++} ++ ++static int aufs_remount_fs(struct super_block *sb, int *flags, char *data) ++{ ++ int err, do_dx; ++ unsigned int mntflags; ++ struct au_opts opts = { ++ .opt = NULL ++ }; ++ struct dentry *root; ++ struct inode *inode; ++ struct au_sbinfo *sbinfo; ++ ++ err = 0; ++ root = sb->s_root; ++ if (!data || !*data) { ++ err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM); ++ if (!err) { ++ di_write_lock_child(root); ++ err = au_opts_verify(sb, *flags, /*pending*/0); ++ aufs_write_unlock(root); ++ } ++ goto out; ++ } ++ ++ err = -ENOMEM; ++ opts.opt = (void *)__get_free_page(GFP_NOFS); ++ if (unlikely(!opts.opt)) ++ goto out; ++ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt); ++ opts.flags = AuOpts_REMOUNT; ++ opts.sb_flags = *flags; ++ ++ /* parse it before aufs lock */ ++ err = au_opts_parse(sb, data, &opts); ++ if (unlikely(err)) ++ goto out_opts; ++ ++ sbinfo = au_sbi(sb); ++ inode = d_inode(root); ++ inode_lock(inode); ++ err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM); ++ if (unlikely(err)) ++ goto out_mtx; ++ di_write_lock_child(root); ++ ++ /* au_opts_remount() may return an error */ ++ err = au_opts_remount(sb, &opts); ++ au_opts_free(&opts); ++ ++ if (au_ftest_opts(opts.flags, REFRESH)) ++ au_remount_refresh(sb, au_ftest_opts(opts.flags, REFRESH_IDOP)); ++ ++ if (au_ftest_opts(opts.flags, REFRESH_DYAOP)) { ++ mntflags = au_mntflags(sb); ++ do_dx = !!au_opt_test(mntflags, DIO); ++ au_dy_arefresh(do_dx); ++ } ++ ++ au_fhsm_wrote_all(sb, /*force*/1); /* ?? */ ++ aufs_write_unlock(root); ++ ++out_mtx: ++ inode_unlock(inode); ++out_opts: ++ free_page((unsigned long)opts.opt); ++out: ++ err = cvt_err(err); ++ AuTraceErr(err); ++ return err; ++} ++ ++static const struct super_operations aufs_sop = { ++ .alloc_inode = aufs_alloc_inode, ++ .destroy_inode = aufs_destroy_inode, ++ .free_inode = aufs_free_inode, ++ /* always deleting, no clearing */ ++ .drop_inode = generic_delete_inode, ++ .show_options = aufs_show_options, ++ .statfs = aufs_statfs, ++ .put_super = aufs_put_super, ++ .sync_fs = aufs_sync_fs, ++ .remount_fs = aufs_remount_fs ++}; ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int alloc_root(struct super_block *sb) ++{ ++ int err; ++ struct inode *inode; ++ struct dentry *root; ++ ++ err = -ENOMEM; ++ inode = au_iget_locked(sb, AUFS_ROOT_INO); ++ err = PTR_ERR(inode); ++ if (IS_ERR(inode)) ++ goto out; ++ ++ inode->i_op = aufs_iop + AuIop_DIR; /* with getattr by default */ ++ inode->i_fop = &aufs_dir_fop; ++ inode->i_mode = S_IFDIR; ++ set_nlink(inode, 2); ++ unlock_new_inode(inode); ++ ++ root = d_make_root(inode); ++ if (unlikely(!root)) ++ goto out; ++ err = PTR_ERR(root); ++ if (IS_ERR(root)) ++ goto out; ++ ++ err = au_di_init(root); ++ if (!err) { ++ sb->s_root = root; ++ return 0; /* success */ ++ } ++ dput(root); ++ ++out: ++ return err; ++} ++ ++static int aufs_fill_super(struct super_block *sb, void *raw_data, ++ int silent __maybe_unused) ++{ ++ int err; ++ struct au_opts opts = { ++ .opt = NULL ++ }; ++ struct au_sbinfo *sbinfo; ++ struct dentry *root; ++ struct inode *inode; ++ char *arg = raw_data; ++ ++ if (unlikely(!arg || !*arg)) { ++ err = -EINVAL; ++ pr_err("no arg\n"); ++ goto out; ++ } ++ ++ err = -ENOMEM; ++ opts.opt = (void *)__get_free_page(GFP_NOFS); ++ if (unlikely(!opts.opt)) ++ goto out; ++ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt); ++ opts.sb_flags = sb->s_flags; ++ ++ err = au_si_alloc(sb); ++ if (unlikely(err)) ++ goto out_opts; ++ sbinfo = au_sbi(sb); ++ ++ /* all timestamps always follow the ones on the branch */ ++ sb->s_flags |= SB_NOATIME | SB_NODIRATIME; ++ sb->s_flags |= SB_I_VERSION; /* do we really need this? */ ++ sb->s_op = &aufs_sop; ++ sb->s_d_op = &aufs_dop; ++ sb->s_magic = AUFS_SUPER_MAGIC; ++ sb->s_maxbytes = 0; ++ sb->s_stack_depth = 1; ++ au_export_init(sb); ++ au_xattr_init(sb); ++ ++ err = alloc_root(sb); ++ if (unlikely(err)) { ++ si_write_unlock(sb); ++ goto out_info; ++ } ++ root = sb->s_root; ++ inode = d_inode(root); ++ ++ /* ++ * actually we can parse options regardless aufs lock here. ++ * but at remount time, parsing must be done before aufs lock. ++ * so we follow the same rule. ++ */ ++ ii_write_lock_parent(inode); ++ aufs_write_unlock(root); ++ err = au_opts_parse(sb, arg, &opts); ++ if (unlikely(err)) ++ goto out_root; ++ ++ /* lock vfs_inode first, then aufs. */ ++ inode_lock(inode); ++ aufs_write_lock(root); ++ err = au_opts_mount(sb, &opts); ++ au_opts_free(&opts); ++ if (!err && au_ftest_si(sbinfo, NO_DREVAL)) { ++ sb->s_d_op = &aufs_dop_noreval; ++ pr_info("%ps\n", sb->s_d_op); ++ au_refresh_dop(root, /*force_reval*/0); ++ sbinfo->si_iop_array = aufs_iop_nogetattr; ++ au_refresh_iop(inode, /*force_getattr*/0); ++ } ++ aufs_write_unlock(root); ++ inode_unlock(inode); ++ if (!err) ++ goto out_opts; /* success */ ++ ++out_root: ++ dput(root); ++ sb->s_root = NULL; ++out_info: ++ kobject_put(&sbinfo->si_kobj); ++ sb->s_fs_info = NULL; ++out_opts: ++ free_page((unsigned long)opts.opt); ++out: ++ AuTraceErr(err); ++ err = cvt_err(err); ++ AuTraceErr(err); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static struct dentry *aufs_mount(struct file_system_type *fs_type, int flags, ++ const char *dev_name __maybe_unused, ++ void *raw_data) ++{ ++ struct dentry *root; ++ ++ /* all timestamps always follow the ones on the branch */ ++ /* mnt->mnt_flags |= MNT_NOATIME | MNT_NODIRATIME; */ ++ root = mount_nodev(fs_type, flags, raw_data, aufs_fill_super); ++ if (IS_ERR(root)) ++ goto out; ++ ++ au_sbilist_add(root->d_sb); ++ ++out: ++ return root; ++} ++ ++static void aufs_kill_sb(struct super_block *sb) ++{ ++ struct au_sbinfo *sbinfo; ++ ++ sbinfo = au_sbi(sb); ++ if (sbinfo) { ++ au_sbilist_del(sb); ++ aufs_write_lock(sb->s_root); ++ au_fhsm_fin(sb); ++ if (sbinfo->si_wbr_create_ops->fin) ++ sbinfo->si_wbr_create_ops->fin(sb); ++ if (au_opt_test(sbinfo->si_mntflags, UDBA_HNOTIFY)) { ++ au_opt_set_udba(sbinfo->si_mntflags, UDBA_NONE); ++ au_remount_refresh(sb, /*do_idop*/0); ++ } ++ if (au_opt_test(sbinfo->si_mntflags, PLINK)) ++ au_plink_put(sb, /*verbose*/1); ++ au_xino_clr(sb); ++ au_dr_opt_flush(sb); ++ sbinfo->si_sb = NULL; ++ aufs_write_unlock(sb->s_root); ++ au_nwt_flush(&sbinfo->si_nowait); ++ } ++ kill_anon_super(sb); ++} ++ ++struct file_system_type aufs_fs_type = { ++ .name = AUFS_FSTYPE, ++ /* a race between rename and others */ ++ .fs_flags = FS_RENAME_DOES_D_MOVE, ++ .mount = aufs_mount, ++ .kill_sb = aufs_kill_sb, ++ /* no need to __module_get() and module_put(). */ ++ .owner = THIS_MODULE, ++}; +diff -Nurp linux-5.4/fs/aufs/super.h linux-5.4-aufs/fs/aufs/super.h +--- linux-5.4/fs/aufs/super.h 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/super.h 2019-11-28 01:25:59.068925618 +0200 +@@ -0,0 +1,576 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * super_block operations ++ */ ++ ++#ifndef __AUFS_SUPER_H__ ++#define __AUFS_SUPER_H__ ++ ++#ifdef __KERNEL__ ++ ++#include ++#include ++#include "hbl.h" ++#include "lcnt.h" ++#include "rwsem.h" ++#include "wkq.h" ++ ++/* policies to select one among multiple writable branches */ ++struct au_wbr_copyup_operations { ++ int (*copyup)(struct dentry *dentry); ++}; ++ ++#define AuWbr_DIR 1 /* target is a dir */ ++#define AuWbr_PARENT (1 << 1) /* always require a parent */ ++ ++#define au_ftest_wbr(flags, name) ((flags) & AuWbr_##name) ++#define au_fset_wbr(flags, name) { (flags) |= AuWbr_##name; } ++#define au_fclr_wbr(flags, name) { (flags) &= ~AuWbr_##name; } ++ ++struct au_wbr_create_operations { ++ int (*create)(struct dentry *dentry, unsigned int flags); ++ int (*init)(struct super_block *sb); ++ int (*fin)(struct super_block *sb); ++}; ++ ++struct au_wbr_mfs { ++ struct mutex mfs_lock; /* protect this structure */ ++ unsigned long mfs_jiffy; ++ unsigned long mfs_expire; ++ aufs_bindex_t mfs_bindex; ++ ++ unsigned long long mfsrr_bytes; ++ unsigned long long mfsrr_watermark; ++}; ++ ++#define AuPlink_NHASH 100 ++static inline int au_plink_hash(ino_t ino) ++{ ++ return ino % AuPlink_NHASH; ++} ++ ++/* File-based Hierarchical Storage Management */ ++struct au_fhsm { ++#ifdef CONFIG_AUFS_FHSM ++ /* allow only one process who can receive the notification */ ++ spinlock_t fhsm_spin; ++ pid_t fhsm_pid; ++ wait_queue_head_t fhsm_wqh; ++ atomic_t fhsm_readable; ++ ++ /* these are protected by si_rwsem */ ++ unsigned long fhsm_expire; ++ aufs_bindex_t fhsm_bottom; ++#endif ++}; ++ ++struct au_branch; ++struct au_sbinfo { ++ /* nowait tasks in the system-wide workqueue */ ++ struct au_nowait_tasks si_nowait; ++ ++ /* ++ * tried sb->s_umount, but failed due to the dependency between i_mutex. ++ * rwsem for au_sbinfo is necessary. ++ */ ++ struct au_rwsem si_rwsem; ++ ++ /* ++ * dirty approach to protect sb->sb_inodes and ->s_files (gone) from ++ * remount. ++ */ ++ au_lcnt_t si_ninodes, si_nfiles; ++ ++ /* branch management */ ++ unsigned int si_generation; ++ ++ /* see AuSi_ flags */ ++ unsigned char au_si_status; ++ ++ aufs_bindex_t si_bbot; ++ ++ /* dirty trick to keep br_id plus */ ++ unsigned int si_last_br_id : ++ sizeof(aufs_bindex_t) * BITS_PER_BYTE - 1; ++ struct au_branch **si_branch; ++ ++ /* policy to select a writable branch */ ++ unsigned char si_wbr_copyup; ++ unsigned char si_wbr_create; ++ struct au_wbr_copyup_operations *si_wbr_copyup_ops; ++ struct au_wbr_create_operations *si_wbr_create_ops; ++ ++ /* round robin */ ++ atomic_t si_wbr_rr_next; ++ ++ /* most free space */ ++ struct au_wbr_mfs si_wbr_mfs; ++ ++ /* File-based Hierarchical Storage Management */ ++ struct au_fhsm si_fhsm; ++ ++ /* mount flags */ ++ /* include/asm-ia64/siginfo.h defines a macro named si_flags */ ++ unsigned int si_mntflags; ++ ++ /* external inode number (bitmap and translation table) */ ++ vfs_readf_t si_xread; ++ vfs_writef_t si_xwrite; ++ loff_t si_ximaxent; /* max entries in a xino */ ++ ++ struct file *si_xib; ++ struct mutex si_xib_mtx; /* protect xib members */ ++ unsigned long *si_xib_buf; ++ unsigned long si_xib_last_pindex; ++ int si_xib_next_bit; ++ ++ unsigned long si_xino_jiffy; ++ unsigned long si_xino_expire; ++ /* reserved for future use */ ++ /* unsigned long long si_xib_limit; */ /* Max xib file size */ ++ ++#ifdef CONFIG_AUFS_EXPORT ++ /* i_generation */ ++ /* todo: make xigen file an array to support many inode numbers */ ++ struct file *si_xigen; ++ atomic_t si_xigen_next; ++#endif ++ ++ /* dirty trick to support atomic_open */ ++ struct hlist_bl_head si_aopen; ++ ++ /* vdir parameters */ ++ unsigned long si_rdcache; /* max cache time in jiffies */ ++ unsigned int si_rdblk; /* deblk size */ ++ unsigned int si_rdhash; /* hash size */ ++ ++ /* ++ * If the number of whiteouts are larger than si_dirwh, leave all of ++ * them after au_whtmp_ren to reduce the cost of rmdir(2). ++ * future fsck.aufs or kernel thread will remove them later. ++ * Otherwise, remove all whiteouts and the dir in rmdir(2). ++ */ ++ unsigned int si_dirwh; ++ ++ /* pseudo_link list */ ++ struct hlist_bl_head si_plink[AuPlink_NHASH]; ++ wait_queue_head_t si_plink_wq; ++ spinlock_t si_plink_maint_lock; ++ pid_t si_plink_maint_pid; ++ ++ /* file list */ ++ struct hlist_bl_head si_files; ++ ++ /* with/without getattr, brother of sb->s_d_op */ ++ struct inode_operations *si_iop_array; ++ ++ /* ++ * sysfs and lifetime management. ++ * this is not a small structure and it may be a waste of memory in case ++ * of sysfs is disabled, particularly when many aufs-es are mounted. ++ * but using sysfs is majority. ++ */ ++ struct kobject si_kobj; ++#ifdef CONFIG_DEBUG_FS ++ struct dentry *si_dbgaufs; ++ struct dentry *si_dbgaufs_plink; ++ struct dentry *si_dbgaufs_xib; ++#ifdef CONFIG_AUFS_EXPORT ++ struct dentry *si_dbgaufs_xigen; ++#endif ++#endif ++ ++#ifdef CONFIG_AUFS_SBILIST ++ struct hlist_bl_node si_list; ++#endif ++ ++ /* dirty, necessary for unmounting, sysfs and sysrq */ ++ struct super_block *si_sb; ++}; ++ ++/* sbinfo status flags */ ++/* ++ * set true when refresh_dirs() failed at remount time. ++ * then try refreshing dirs at access time again. ++ * if it is false, refreshing dirs at access time is unnecessary ++ */ ++#define AuSi_FAILED_REFRESH_DIR 1 ++#define AuSi_FHSM (1 << 1) /* fhsm is active now */ ++#define AuSi_NO_DREVAL (1 << 2) /* disable all d_revalidate */ ++ ++#ifndef CONFIG_AUFS_FHSM ++#undef AuSi_FHSM ++#define AuSi_FHSM 0 ++#endif ++ ++static inline unsigned char au_do_ftest_si(struct au_sbinfo *sbi, ++ unsigned int flag) ++{ ++ AuRwMustAnyLock(&sbi->si_rwsem); ++ return sbi->au_si_status & flag; ++} ++#define au_ftest_si(sbinfo, name) au_do_ftest_si(sbinfo, AuSi_##name) ++#define au_fset_si(sbinfo, name) do { \ ++ AuRwMustWriteLock(&(sbinfo)->si_rwsem); \ ++ (sbinfo)->au_si_status |= AuSi_##name; \ ++} while (0) ++#define au_fclr_si(sbinfo, name) do { \ ++ AuRwMustWriteLock(&(sbinfo)->si_rwsem); \ ++ (sbinfo)->au_si_status &= ~AuSi_##name; \ ++} while (0) ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* policy to select one among writable branches */ ++#define AuWbrCopyup(sbinfo, ...) \ ++ ((sbinfo)->si_wbr_copyup_ops->copyup(__VA_ARGS__)) ++#define AuWbrCreate(sbinfo, ...) \ ++ ((sbinfo)->si_wbr_create_ops->create(__VA_ARGS__)) ++ ++/* flags for si_read_lock()/aufs_read_lock()/di_read_lock() */ ++#define AuLock_DW 1 /* write-lock dentry */ ++#define AuLock_IR (1 << 1) /* read-lock inode */ ++#define AuLock_IW (1 << 2) /* write-lock inode */ ++#define AuLock_FLUSH (1 << 3) /* wait for 'nowait' tasks */ ++#define AuLock_DIRS (1 << 4) /* target is a pair of dirs */ ++ /* except RENAME_EXCHANGE */ ++#define AuLock_NOPLM (1 << 5) /* return err in plm mode */ ++#define AuLock_NOPLMW (1 << 6) /* wait for plm mode ends */ ++#define AuLock_GEN (1 << 7) /* test digen/iigen */ ++#define au_ftest_lock(flags, name) ((flags) & AuLock_##name) ++#define au_fset_lock(flags, name) \ ++ do { (flags) |= AuLock_##name; } while (0) ++#define au_fclr_lock(flags, name) \ ++ do { (flags) &= ~AuLock_##name; } while (0) ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* super.c */ ++extern struct file_system_type aufs_fs_type; ++struct inode *au_iget_locked(struct super_block *sb, ino_t ino); ++typedef unsigned long long (*au_arraycb_t)(struct super_block *sb, void *array, ++ unsigned long long max, void *arg); ++void *au_array_alloc(unsigned long long *hint, au_arraycb_t cb, ++ struct super_block *sb, void *arg); ++struct inode **au_iarray_alloc(struct super_block *sb, unsigned long long *max); ++void au_iarray_free(struct inode **a, unsigned long long max); ++ ++/* sbinfo.c */ ++void au_si_free(struct kobject *kobj); ++int au_si_alloc(struct super_block *sb); ++int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr, int may_shrink); ++ ++unsigned int au_sigen_inc(struct super_block *sb); ++aufs_bindex_t au_new_br_id(struct super_block *sb); ++ ++int si_read_lock(struct super_block *sb, int flags); ++int si_write_lock(struct super_block *sb, int flags); ++int aufs_read_lock(struct dentry *dentry, int flags); ++void aufs_read_unlock(struct dentry *dentry, int flags); ++void aufs_write_lock(struct dentry *dentry); ++void aufs_write_unlock(struct dentry *dentry); ++int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags); ++void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2); ++ ++/* wbr_policy.c */ ++extern struct au_wbr_copyup_operations au_wbr_copyup_ops[]; ++extern struct au_wbr_create_operations au_wbr_create_ops[]; ++int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst); ++int au_wbr_nonopq(struct dentry *dentry, aufs_bindex_t bindex); ++int au_wbr_do_copyup_bu(struct dentry *dentry, aufs_bindex_t btop); ++ ++/* mvdown.c */ ++int au_mvdown(struct dentry *dentry, struct aufs_mvdown __user *arg); ++ ++#ifdef CONFIG_AUFS_FHSM ++/* fhsm.c */ ++ ++static inline pid_t au_fhsm_pid(struct au_fhsm *fhsm) ++{ ++ pid_t pid; ++ ++ spin_lock(&fhsm->fhsm_spin); ++ pid = fhsm->fhsm_pid; ++ spin_unlock(&fhsm->fhsm_spin); ++ ++ return pid; ++} ++ ++void au_fhsm_wrote(struct super_block *sb, aufs_bindex_t bindex, int force); ++void au_fhsm_wrote_all(struct super_block *sb, int force); ++int au_fhsm_fd(struct super_block *sb, int oflags); ++int au_fhsm_br_alloc(struct au_branch *br); ++void au_fhsm_set_bottom(struct super_block *sb, aufs_bindex_t bindex); ++void au_fhsm_fin(struct super_block *sb); ++void au_fhsm_init(struct au_sbinfo *sbinfo); ++void au_fhsm_set(struct au_sbinfo *sbinfo, unsigned int sec); ++void au_fhsm_show(struct seq_file *seq, struct au_sbinfo *sbinfo); ++#else ++AuStubVoid(au_fhsm_wrote, struct super_block *sb, aufs_bindex_t bindex, ++ int force) ++AuStubVoid(au_fhsm_wrote_all, struct super_block *sb, int force) ++AuStub(int, au_fhsm_fd, return -EOPNOTSUPP, struct super_block *sb, int oflags) ++AuStub(pid_t, au_fhsm_pid, return 0, struct au_fhsm *fhsm) ++AuStubInt0(au_fhsm_br_alloc, struct au_branch *br) ++AuStubVoid(au_fhsm_set_bottom, struct super_block *sb, aufs_bindex_t bindex) ++AuStubVoid(au_fhsm_fin, struct super_block *sb) ++AuStubVoid(au_fhsm_init, struct au_sbinfo *sbinfo) ++AuStubVoid(au_fhsm_set, struct au_sbinfo *sbinfo, unsigned int sec) ++AuStubVoid(au_fhsm_show, struct seq_file *seq, struct au_sbinfo *sbinfo) ++#endif ++ ++/* ---------------------------------------------------------------------- */ ++ ++static inline struct au_sbinfo *au_sbi(struct super_block *sb) ++{ ++ return sb->s_fs_info; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++#ifdef CONFIG_AUFS_EXPORT ++int au_test_nfsd(void); ++void au_export_init(struct super_block *sb); ++void au_xigen_inc(struct inode *inode); ++int au_xigen_new(struct inode *inode); ++int au_xigen_set(struct super_block *sb, struct path *path); ++void au_xigen_clr(struct super_block *sb); ++ ++static inline int au_busy_or_stale(void) ++{ ++ if (!au_test_nfsd()) ++ return -EBUSY; ++ return -ESTALE; ++} ++#else ++AuStubInt0(au_test_nfsd, void) ++AuStubVoid(au_export_init, struct super_block *sb) ++AuStubVoid(au_xigen_inc, struct inode *inode) ++AuStubInt0(au_xigen_new, struct inode *inode) ++AuStubInt0(au_xigen_set, struct super_block *sb, struct path *path) ++AuStubVoid(au_xigen_clr, struct super_block *sb) ++AuStub(int, au_busy_or_stale, return -EBUSY, void) ++#endif /* CONFIG_AUFS_EXPORT */ ++ ++/* ---------------------------------------------------------------------- */ ++ ++#ifdef CONFIG_AUFS_SBILIST ++/* module.c */ ++extern struct hlist_bl_head au_sbilist; ++ ++static inline void au_sbilist_init(void) ++{ ++ INIT_HLIST_BL_HEAD(&au_sbilist); ++} ++ ++static inline void au_sbilist_add(struct super_block *sb) ++{ ++ au_hbl_add(&au_sbi(sb)->si_list, &au_sbilist); ++} ++ ++static inline void au_sbilist_del(struct super_block *sb) ++{ ++ au_hbl_del(&au_sbi(sb)->si_list, &au_sbilist); ++} ++ ++#ifdef CONFIG_AUFS_MAGIC_SYSRQ ++static inline void au_sbilist_lock(void) ++{ ++ hlist_bl_lock(&au_sbilist); ++} ++ ++static inline void au_sbilist_unlock(void) ++{ ++ hlist_bl_unlock(&au_sbilist); ++} ++#define AuGFP_SBILIST GFP_ATOMIC ++#else ++AuStubVoid(au_sbilist_lock, void) ++AuStubVoid(au_sbilist_unlock, void) ++#define AuGFP_SBILIST GFP_NOFS ++#endif /* CONFIG_AUFS_MAGIC_SYSRQ */ ++#else ++AuStubVoid(au_sbilist_init, void) ++AuStubVoid(au_sbilist_add, struct super_block *sb) ++AuStubVoid(au_sbilist_del, struct super_block *sb) ++AuStubVoid(au_sbilist_lock, void) ++AuStubVoid(au_sbilist_unlock, void) ++#define AuGFP_SBILIST GFP_NOFS ++#endif ++ ++/* ---------------------------------------------------------------------- */ ++ ++static inline void dbgaufs_si_null(struct au_sbinfo *sbinfo) ++{ ++ /* ++ * This function is a dynamic '__init' function actually, ++ * so the tiny check for si_rwsem is unnecessary. ++ */ ++ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */ ++#ifdef CONFIG_DEBUG_FS ++ sbinfo->si_dbgaufs = NULL; ++ sbinfo->si_dbgaufs_plink = NULL; ++ sbinfo->si_dbgaufs_xib = NULL; ++#ifdef CONFIG_AUFS_EXPORT ++ sbinfo->si_dbgaufs_xigen = NULL; ++#endif ++#endif ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* current->atomic_flags */ ++/* this value should never corrupt the ones defined in linux/sched.h */ ++#define PFA_AUFS 0x10 ++ ++TASK_PFA_TEST(AUFS, test_aufs) /* task_test_aufs */ ++TASK_PFA_SET(AUFS, aufs) /* task_set_aufs */ ++TASK_PFA_CLEAR(AUFS, aufs) /* task_clear_aufs */ ++ ++static inline int si_pid_test(struct super_block *sb) ++{ ++ return !!task_test_aufs(current); ++} ++ ++static inline void si_pid_clr(struct super_block *sb) ++{ ++ AuDebugOn(!task_test_aufs(current)); ++ task_clear_aufs(current); ++} ++ ++static inline void si_pid_set(struct super_block *sb) ++{ ++ AuDebugOn(task_test_aufs(current)); ++ task_set_aufs(current); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* lock superblock. mainly for entry point functions */ ++#define __si_read_lock(sb) au_rw_read_lock(&au_sbi(sb)->si_rwsem) ++#define __si_write_lock(sb) au_rw_write_lock(&au_sbi(sb)->si_rwsem) ++#define __si_read_trylock(sb) au_rw_read_trylock(&au_sbi(sb)->si_rwsem) ++#define __si_write_trylock(sb) au_rw_write_trylock(&au_sbi(sb)->si_rwsem) ++/* ++#define __si_read_trylock_nested(sb) \ ++ au_rw_read_trylock_nested(&au_sbi(sb)->si_rwsem) ++#define __si_write_trylock_nested(sb) \ ++ au_rw_write_trylock_nested(&au_sbi(sb)->si_rwsem) ++*/ ++ ++#define __si_read_unlock(sb) au_rw_read_unlock(&au_sbi(sb)->si_rwsem) ++#define __si_write_unlock(sb) au_rw_write_unlock(&au_sbi(sb)->si_rwsem) ++#define __si_downgrade_lock(sb) au_rw_dgrade_lock(&au_sbi(sb)->si_rwsem) ++ ++#define SiMustNoWaiters(sb) AuRwMustNoWaiters(&au_sbi(sb)->si_rwsem) ++#define SiMustAnyLock(sb) AuRwMustAnyLock(&au_sbi(sb)->si_rwsem) ++#define SiMustWriteLock(sb) AuRwMustWriteLock(&au_sbi(sb)->si_rwsem) ++ ++static inline void si_noflush_read_lock(struct super_block *sb) ++{ ++ __si_read_lock(sb); ++ si_pid_set(sb); ++} ++ ++static inline int si_noflush_read_trylock(struct super_block *sb) ++{ ++ int locked; ++ ++ locked = __si_read_trylock(sb); ++ if (locked) ++ si_pid_set(sb); ++ return locked; ++} ++ ++static inline void si_noflush_write_lock(struct super_block *sb) ++{ ++ __si_write_lock(sb); ++ si_pid_set(sb); ++} ++ ++static inline int si_noflush_write_trylock(struct super_block *sb) ++{ ++ int locked; ++ ++ locked = __si_write_trylock(sb); ++ if (locked) ++ si_pid_set(sb); ++ return locked; ++} ++ ++#if 0 /* reserved */ ++static inline int si_read_trylock(struct super_block *sb, int flags) ++{ ++ if (au_ftest_lock(flags, FLUSH)) ++ au_nwt_flush(&au_sbi(sb)->si_nowait); ++ return si_noflush_read_trylock(sb); ++} ++#endif ++ ++static inline void si_read_unlock(struct super_block *sb) ++{ ++ si_pid_clr(sb); ++ __si_read_unlock(sb); ++} ++ ++#if 0 /* reserved */ ++static inline int si_write_trylock(struct super_block *sb, int flags) ++{ ++ if (au_ftest_lock(flags, FLUSH)) ++ au_nwt_flush(&au_sbi(sb)->si_nowait); ++ return si_noflush_write_trylock(sb); ++} ++#endif ++ ++static inline void si_write_unlock(struct super_block *sb) ++{ ++ si_pid_clr(sb); ++ __si_write_unlock(sb); ++} ++ ++#if 0 /* reserved */ ++static inline void si_downgrade_lock(struct super_block *sb) ++{ ++ __si_downgrade_lock(sb); ++} ++#endif ++ ++/* ---------------------------------------------------------------------- */ ++ ++static inline aufs_bindex_t au_sbbot(struct super_block *sb) ++{ ++ SiMustAnyLock(sb); ++ return au_sbi(sb)->si_bbot; ++} ++ ++static inline unsigned int au_mntflags(struct super_block *sb) ++{ ++ SiMustAnyLock(sb); ++ return au_sbi(sb)->si_mntflags; ++} ++ ++static inline unsigned int au_sigen(struct super_block *sb) ++{ ++ SiMustAnyLock(sb); ++ return au_sbi(sb)->si_generation; ++} ++ ++static inline struct au_branch *au_sbr(struct super_block *sb, ++ aufs_bindex_t bindex) ++{ ++ SiMustAnyLock(sb); ++ return au_sbi(sb)->si_branch[0 + bindex]; ++} ++ ++static inline loff_t au_xi_maxent(struct super_block *sb) ++{ ++ SiMustAnyLock(sb); ++ return au_sbi(sb)->si_ximaxent; ++} ++ ++#endif /* __KERNEL__ */ ++#endif /* __AUFS_SUPER_H__ */ +diff -Nurp linux-5.4/fs/aufs/sysaufs.c linux-5.4-aufs/fs/aufs/sysaufs.c +--- linux-5.4/fs/aufs/sysaufs.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/sysaufs.c 2019-11-28 01:25:59.068925618 +0200 +@@ -0,0 +1,80 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * sysfs interface and lifetime management ++ * they are necessary regardless sysfs is disabled. ++ */ ++ ++#include ++#include "aufs.h" ++ ++unsigned long sysaufs_si_mask; ++struct kset *sysaufs_kset; ++ ++#define AuSiAttr(_name) { \ ++ .attr = { .name = __stringify(_name), .mode = 0444 }, \ ++ .show = sysaufs_si_##_name, \ ++} ++ ++static struct sysaufs_si_attr sysaufs_si_attr_xi_path = AuSiAttr(xi_path); ++struct attribute *sysaufs_si_attrs[] = { ++ &sysaufs_si_attr_xi_path.attr, ++ NULL, ++}; ++ ++static const struct sysfs_ops au_sbi_ops = { ++ .show = sysaufs_si_show ++}; ++ ++static struct kobj_type au_sbi_ktype = { ++ .release = au_si_free, ++ .sysfs_ops = &au_sbi_ops, ++ .default_attrs = sysaufs_si_attrs ++}; ++ ++/* ---------------------------------------------------------------------- */ ++ ++int sysaufs_si_init(struct au_sbinfo *sbinfo) ++{ ++ int err; ++ ++ sbinfo->si_kobj.kset = sysaufs_kset; ++ /* cf. sysaufs_name() */ ++ err = kobject_init_and_add ++ (&sbinfo->si_kobj, &au_sbi_ktype, /*&sysaufs_kset->kobj*/NULL, ++ SysaufsSiNamePrefix "%lx", sysaufs_si_id(sbinfo)); ++ ++ return err; ++} ++ ++void sysaufs_fin(void) ++{ ++ sysfs_remove_group(&sysaufs_kset->kobj, sysaufs_attr_group); ++ kset_unregister(sysaufs_kset); ++} ++ ++int __init sysaufs_init(void) ++{ ++ int err; ++ ++ do { ++ get_random_bytes(&sysaufs_si_mask, sizeof(sysaufs_si_mask)); ++ } while (!sysaufs_si_mask); ++ ++ err = -EINVAL; ++ sysaufs_kset = kset_create_and_add(AUFS_NAME, NULL, fs_kobj); ++ if (unlikely(!sysaufs_kset)) ++ goto out; ++ err = PTR_ERR(sysaufs_kset); ++ if (IS_ERR(sysaufs_kset)) ++ goto out; ++ err = sysfs_create_group(&sysaufs_kset->kobj, sysaufs_attr_group); ++ if (unlikely(err)) ++ kset_unregister(sysaufs_kset); ++ ++out: ++ return err; ++} +diff -Nurp linux-5.4/fs/aufs/sysaufs.h linux-5.4-aufs/fs/aufs/sysaufs.h +--- linux-5.4/fs/aufs/sysaufs.h 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/sysaufs.h 2019-11-28 01:25:59.068925618 +0200 +@@ -0,0 +1,89 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * sysfs interface and mount lifetime management ++ */ ++ ++#ifndef __SYSAUFS_H__ ++#define __SYSAUFS_H__ ++ ++#ifdef __KERNEL__ ++ ++#include ++#include "module.h" ++ ++struct super_block; ++struct au_sbinfo; ++ ++struct sysaufs_si_attr { ++ struct attribute attr; ++ int (*show)(struct seq_file *seq, struct super_block *sb); ++}; ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* sysaufs.c */ ++extern unsigned long sysaufs_si_mask; ++extern struct kset *sysaufs_kset; ++extern struct attribute *sysaufs_si_attrs[]; ++int sysaufs_si_init(struct au_sbinfo *sbinfo); ++int __init sysaufs_init(void); ++void sysaufs_fin(void); ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* some people doesn't like to show a pointer in kernel */ ++static inline unsigned long sysaufs_si_id(struct au_sbinfo *sbinfo) ++{ ++ return sysaufs_si_mask ^ (unsigned long)sbinfo; ++} ++ ++#define SysaufsSiNamePrefix "si_" ++#define SysaufsSiNameLen (sizeof(SysaufsSiNamePrefix) + 16) ++static inline void sysaufs_name(struct au_sbinfo *sbinfo, char *name) ++{ ++ snprintf(name, SysaufsSiNameLen, SysaufsSiNamePrefix "%lx", ++ sysaufs_si_id(sbinfo)); ++} ++ ++struct au_branch; ++#ifdef CONFIG_SYSFS ++/* sysfs.c */ ++extern struct attribute_group *sysaufs_attr_group; ++ ++int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb); ++ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr, ++ char *buf); ++long au_brinfo_ioctl(struct file *file, unsigned long arg); ++#ifdef CONFIG_COMPAT ++long au_brinfo_compat_ioctl(struct file *file, unsigned long arg); ++#endif ++ ++void sysaufs_br_init(struct au_branch *br); ++void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex); ++void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex); ++ ++#define sysaufs_brs_init() do {} while (0) ++ ++#else ++#define sysaufs_attr_group NULL ++ ++AuStubInt0(sysaufs_si_xi_path, struct seq_file *seq, struct super_block *sb) ++AuStub(ssize_t, sysaufs_si_show, return 0, struct kobject *kobj, ++ struct attribute *attr, char *buf) ++AuStubVoid(sysaufs_br_init, struct au_branch *br) ++AuStubVoid(sysaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex) ++AuStubVoid(sysaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex) ++ ++static inline void sysaufs_brs_init(void) ++{ ++ sysaufs_brs = 0; ++} ++ ++#endif /* CONFIG_SYSFS */ ++ ++#endif /* __KERNEL__ */ ++#endif /* __SYSAUFS_H__ */ +diff -Nurp linux-5.4/fs/aufs/sysfs.c linux-5.4-aufs/fs/aufs/sysfs.c +--- linux-5.4/fs/aufs/sysfs.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/sysfs.c 2019-11-28 01:25:59.068925618 +0200 +@@ -0,0 +1,338 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * sysfs interface ++ */ ++ ++#include ++#include ++#include "aufs.h" ++ ++static struct attribute *au_attr[] = { ++ NULL, /* need to NULL terminate the list of attributes */ ++}; ++ ++static struct attribute_group sysaufs_attr_group_body = { ++ .attrs = au_attr ++}; ++ ++struct attribute_group *sysaufs_attr_group = &sysaufs_attr_group_body; ++ ++/* ---------------------------------------------------------------------- */ ++ ++int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb) ++{ ++ int err; ++ ++ SiMustAnyLock(sb); ++ ++ err = 0; ++ if (au_opt_test(au_mntflags(sb), XINO)) { ++ err = au_xino_path(seq, au_sbi(sb)->si_xib); ++ seq_putc(seq, '\n'); ++ } ++ return err; ++} ++ ++/* ++ * the lifetime of branch is independent from the entry under sysfs. ++ * sysfs handles the lifetime of the entry, and never call ->show() after it is ++ * unlinked. ++ */ ++static int sysaufs_si_br(struct seq_file *seq, struct super_block *sb, ++ aufs_bindex_t bindex, int idx) ++{ ++ int err; ++ struct path path; ++ struct dentry *root; ++ struct au_branch *br; ++ au_br_perm_str_t perm; ++ ++ AuDbg("b%d\n", bindex); ++ ++ err = 0; ++ root = sb->s_root; ++ di_read_lock_parent(root, !AuLock_IR); ++ br = au_sbr(sb, bindex); ++ ++ switch (idx) { ++ case AuBrSysfs_BR: ++ path.mnt = au_br_mnt(br); ++ path.dentry = au_h_dptr(root, bindex); ++ err = au_seq_path(seq, &path); ++ if (!err) { ++ au_optstr_br_perm(&perm, br->br_perm); ++ seq_printf(seq, "=%s\n", perm.a); ++ } ++ break; ++ case AuBrSysfs_BRID: ++ seq_printf(seq, "%d\n", br->br_id); ++ break; ++ } ++ di_read_unlock(root, !AuLock_IR); ++ if (unlikely(err || seq_has_overflowed(seq))) ++ err = -E2BIG; ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static struct seq_file *au_seq(char *p, ssize_t len) ++{ ++ struct seq_file *seq; ++ ++ seq = kzalloc(sizeof(*seq), GFP_NOFS); ++ if (seq) { ++ /* mutex_init(&seq.lock); */ ++ seq->buf = p; ++ seq->size = len; ++ return seq; /* success */ ++ } ++ ++ seq = ERR_PTR(-ENOMEM); ++ return seq; ++} ++ ++#define SysaufsBr_PREFIX "br" ++#define SysaufsBrid_PREFIX "brid" ++ ++/* todo: file size may exceed PAGE_SIZE */ ++ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr, ++ char *buf) ++{ ++ ssize_t err; ++ int idx; ++ long l; ++ aufs_bindex_t bbot; ++ struct au_sbinfo *sbinfo; ++ struct super_block *sb; ++ struct seq_file *seq; ++ char *name; ++ struct attribute **cattr; ++ ++ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj); ++ sb = sbinfo->si_sb; ++ ++ /* ++ * prevent a race condition between sysfs and aufs. ++ * for instance, sysfs_file_read() calls sysfs_get_active_two() which ++ * prohibits maintaining the sysfs entries. ++ * hew we acquire read lock after sysfs_get_active_two(). ++ * on the other hand, the remount process may maintain the sysfs/aufs ++ * entries after acquiring write lock. ++ * it can cause a deadlock. ++ * simply we gave up processing read here. ++ */ ++ err = -EBUSY; ++ if (unlikely(!si_noflush_read_trylock(sb))) ++ goto out; ++ ++ seq = au_seq(buf, PAGE_SIZE); ++ err = PTR_ERR(seq); ++ if (IS_ERR(seq)) ++ goto out_unlock; ++ ++ name = (void *)attr->name; ++ cattr = sysaufs_si_attrs; ++ while (*cattr) { ++ if (!strcmp(name, (*cattr)->name)) { ++ err = container_of(*cattr, struct sysaufs_si_attr, attr) ++ ->show(seq, sb); ++ goto out_seq; ++ } ++ cattr++; ++ } ++ ++ if (!strncmp(name, SysaufsBrid_PREFIX, ++ sizeof(SysaufsBrid_PREFIX) - 1)) { ++ idx = AuBrSysfs_BRID; ++ name += sizeof(SysaufsBrid_PREFIX) - 1; ++ } else if (!strncmp(name, SysaufsBr_PREFIX, ++ sizeof(SysaufsBr_PREFIX) - 1)) { ++ idx = AuBrSysfs_BR; ++ name += sizeof(SysaufsBr_PREFIX) - 1; ++ } else ++ BUG(); ++ ++ err = kstrtol(name, 10, &l); ++ if (!err) { ++ bbot = au_sbbot(sb); ++ if (l <= bbot) ++ err = sysaufs_si_br(seq, sb, (aufs_bindex_t)l, idx); ++ else ++ err = -ENOENT; ++ } ++ ++out_seq: ++ if (!err) { ++ err = seq->count; ++ /* sysfs limit */ ++ if (unlikely(err == PAGE_SIZE)) ++ err = -EFBIG; ++ } ++ au_kfree_rcu(seq); ++out_unlock: ++ si_read_unlock(sb); ++out: ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int au_brinfo(struct super_block *sb, union aufs_brinfo __user *arg) ++{ ++ int err; ++ int16_t brid; ++ aufs_bindex_t bindex, bbot; ++ size_t sz; ++ char *buf; ++ struct seq_file *seq; ++ struct au_branch *br; ++ ++ si_read_lock(sb, AuLock_FLUSH); ++ bbot = au_sbbot(sb); ++ err = bbot + 1; ++ if (!arg) ++ goto out; ++ ++ err = -ENOMEM; ++ buf = (void *)__get_free_page(GFP_NOFS); ++ if (unlikely(!buf)) ++ goto out; ++ ++ seq = au_seq(buf, PAGE_SIZE); ++ err = PTR_ERR(seq); ++ if (IS_ERR(seq)) ++ goto out_buf; ++ ++ sz = sizeof(*arg) - offsetof(union aufs_brinfo, path); ++ for (bindex = 0; bindex <= bbot; bindex++, arg++) { ++ /* VERIFY_WRITE */ ++ err = !access_ok(arg, sizeof(*arg)); ++ if (unlikely(err)) ++ break; ++ ++ br = au_sbr(sb, bindex); ++ brid = br->br_id; ++ BUILD_BUG_ON(sizeof(brid) != sizeof(arg->id)); ++ err = __put_user(brid, &arg->id); ++ if (unlikely(err)) ++ break; ++ ++ BUILD_BUG_ON(sizeof(br->br_perm) != sizeof(arg->perm)); ++ err = __put_user(br->br_perm, &arg->perm); ++ if (unlikely(err)) ++ break; ++ ++ err = au_seq_path(seq, &br->br_path); ++ if (unlikely(err)) ++ break; ++ seq_putc(seq, '\0'); ++ if (!seq_has_overflowed(seq)) { ++ err = copy_to_user(arg->path, seq->buf, seq->count); ++ seq->count = 0; ++ if (unlikely(err)) ++ break; ++ } else { ++ err = -E2BIG; ++ goto out_seq; ++ } ++ } ++ if (unlikely(err)) ++ err = -EFAULT; ++ ++out_seq: ++ au_kfree_rcu(seq); ++out_buf: ++ free_page((unsigned long)buf); ++out: ++ si_read_unlock(sb); ++ return err; ++} ++ ++long au_brinfo_ioctl(struct file *file, unsigned long arg) ++{ ++ return au_brinfo(file->f_path.dentry->d_sb, (void __user *)arg); ++} ++ ++#ifdef CONFIG_COMPAT ++long au_brinfo_compat_ioctl(struct file *file, unsigned long arg) ++{ ++ return au_brinfo(file->f_path.dentry->d_sb, compat_ptr(arg)); ++} ++#endif ++ ++/* ---------------------------------------------------------------------- */ ++ ++void sysaufs_br_init(struct au_branch *br) ++{ ++ int i; ++ struct au_brsysfs *br_sysfs; ++ struct attribute *attr; ++ ++ br_sysfs = br->br_sysfs; ++ for (i = 0; i < ARRAY_SIZE(br->br_sysfs); i++) { ++ attr = &br_sysfs->attr; ++ sysfs_attr_init(attr); ++ attr->name = br_sysfs->name; ++ attr->mode = 0444; ++ br_sysfs++; ++ } ++} ++ ++void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex) ++{ ++ struct au_branch *br; ++ struct kobject *kobj; ++ struct au_brsysfs *br_sysfs; ++ int i; ++ aufs_bindex_t bbot; ++ ++ if (!sysaufs_brs) ++ return; ++ ++ kobj = &au_sbi(sb)->si_kobj; ++ bbot = au_sbbot(sb); ++ for (; bindex <= bbot; bindex++) { ++ br = au_sbr(sb, bindex); ++ br_sysfs = br->br_sysfs; ++ for (i = 0; i < ARRAY_SIZE(br->br_sysfs); i++) { ++ sysfs_remove_file(kobj, &br_sysfs->attr); ++ br_sysfs++; ++ } ++ } ++} ++ ++void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex) ++{ ++ int err, i; ++ aufs_bindex_t bbot; ++ struct kobject *kobj; ++ struct au_branch *br; ++ struct au_brsysfs *br_sysfs; ++ ++ if (!sysaufs_brs) ++ return; ++ ++ kobj = &au_sbi(sb)->si_kobj; ++ bbot = au_sbbot(sb); ++ for (; bindex <= bbot; bindex++) { ++ br = au_sbr(sb, bindex); ++ br_sysfs = br->br_sysfs; ++ snprintf(br_sysfs[AuBrSysfs_BR].name, sizeof(br_sysfs->name), ++ SysaufsBr_PREFIX "%d", bindex); ++ snprintf(br_sysfs[AuBrSysfs_BRID].name, sizeof(br_sysfs->name), ++ SysaufsBrid_PREFIX "%d", bindex); ++ for (i = 0; i < ARRAY_SIZE(br->br_sysfs); i++) { ++ err = sysfs_create_file(kobj, &br_sysfs->attr); ++ if (unlikely(err)) ++ pr_warn("failed %s under sysfs(%d)\n", ++ br_sysfs->name, err); ++ br_sysfs++; ++ } ++ } ++} +diff -Nurp linux-5.4/fs/aufs/sysrq.c linux-5.4-aufs/fs/aufs/sysrq.c +--- linux-5.4/fs/aufs/sysrq.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/sysrq.c 2019-11-28 01:25:59.068925618 +0200 +@@ -0,0 +1,147 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * magic sysrq handler ++ */ ++ ++/* #include */ ++#include ++#include "aufs.h" ++ ++/* ---------------------------------------------------------------------- */ ++ ++static void sysrq_sb(struct super_block *sb) ++{ ++ char *plevel; ++ struct au_sbinfo *sbinfo; ++ struct file *file; ++ struct hlist_bl_head *files; ++ struct hlist_bl_node *pos; ++ struct au_finfo *finfo; ++ ++ plevel = au_plevel; ++ au_plevel = KERN_WARNING; ++ ++ /* since we define pr_fmt, call printk directly */ ++#define pr(str) printk(KERN_WARNING AUFS_NAME ": " str) ++ ++ sbinfo = au_sbi(sb); ++ printk(KERN_WARNING "si=%lx\n", sysaufs_si_id(sbinfo)); ++ pr("superblock\n"); ++ au_dpri_sb(sb); ++ ++#if 0 ++ pr("root dentry\n"); ++ au_dpri_dentry(sb->s_root); ++ pr("root inode\n"); ++ au_dpri_inode(d_inode(sb->s_root)); ++#endif ++ ++#if 0 ++ do { ++ int err, i, j, ndentry; ++ struct au_dcsub_pages dpages; ++ struct au_dpage *dpage; ++ ++ err = au_dpages_init(&dpages, GFP_ATOMIC); ++ if (unlikely(err)) ++ break; ++ err = au_dcsub_pages(&dpages, sb->s_root, NULL, NULL); ++ if (!err) ++ for (i = 0; i < dpages.ndpage; i++) { ++ dpage = dpages.dpages + i; ++ ndentry = dpage->ndentry; ++ for (j = 0; j < ndentry; j++) ++ au_dpri_dentry(dpage->dentries[j]); ++ } ++ au_dpages_free(&dpages); ++ } while (0); ++#endif ++ ++#if 1 ++ { ++ struct inode *i; ++ ++ pr("isolated inode\n"); ++ spin_lock(&sb->s_inode_list_lock); ++ list_for_each_entry(i, &sb->s_inodes, i_sb_list) { ++ spin_lock(&i->i_lock); ++ if (1 || hlist_empty(&i->i_dentry)) ++ au_dpri_inode(i); ++ spin_unlock(&i->i_lock); ++ } ++ spin_unlock(&sb->s_inode_list_lock); ++ } ++#endif ++ pr("files\n"); ++ files = &au_sbi(sb)->si_files; ++ hlist_bl_lock(files); ++ hlist_bl_for_each_entry(finfo, pos, files, fi_hlist) { ++ umode_t mode; ++ ++ file = finfo->fi_file; ++ mode = file_inode(file)->i_mode; ++ if (!special_file(mode)) ++ au_dpri_file(file); ++ } ++ hlist_bl_unlock(files); ++ pr("done\n"); ++ ++#undef pr ++ au_plevel = plevel; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* module parameter */ ++static char *aufs_sysrq_key = "a"; ++module_param_named(sysrq, aufs_sysrq_key, charp, 0444); ++MODULE_PARM_DESC(sysrq, "MagicSysRq key for " AUFS_NAME); ++ ++static void au_sysrq(int key __maybe_unused) ++{ ++ struct au_sbinfo *sbinfo; ++ struct hlist_bl_node *pos; ++ ++ lockdep_off(); ++ au_sbilist_lock(); ++ hlist_bl_for_each_entry(sbinfo, pos, &au_sbilist, si_list) ++ sysrq_sb(sbinfo->si_sb); ++ au_sbilist_unlock(); ++ lockdep_on(); ++} ++ ++static struct sysrq_key_op au_sysrq_op = { ++ .handler = au_sysrq, ++ .help_msg = "Aufs", ++ .action_msg = "Aufs", ++ .enable_mask = SYSRQ_ENABLE_DUMP ++}; ++ ++/* ---------------------------------------------------------------------- */ ++ ++int __init au_sysrq_init(void) ++{ ++ int err; ++ char key; ++ ++ err = -1; ++ key = *aufs_sysrq_key; ++ if ('a' <= key && key <= 'z') ++ err = register_sysrq_key(key, &au_sysrq_op); ++ if (unlikely(err)) ++ pr_err("err %d, sysrq=%c\n", err, key); ++ return err; ++} ++ ++void au_sysrq_fin(void) ++{ ++ int err; ++ ++ err = unregister_sysrq_key(*aufs_sysrq_key, &au_sysrq_op); ++ if (unlikely(err)) ++ pr_err("err %d (ignored)\n", err); ++} +diff -Nurp linux-5.4/fs/aufs/wbr_policy.c linux-5.4-aufs/fs/aufs/wbr_policy.c +--- linux-5.4/fs/aufs/wbr_policy.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/wbr_policy.c 2019-11-28 01:25:59.068925618 +0200 +@@ -0,0 +1,817 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * policies for selecting one among multiple writable branches ++ */ ++ ++#include ++#include "aufs.h" ++ ++/* subset of cpup_attr() */ ++static noinline_for_stack ++int au_cpdown_attr(struct path *h_path, struct dentry *h_src) ++{ ++ int err, sbits; ++ struct iattr ia; ++ struct inode *h_isrc; ++ ++ h_isrc = d_inode(h_src); ++ ia.ia_valid = ATTR_FORCE | ATTR_MODE | ATTR_UID | ATTR_GID; ++ ia.ia_mode = h_isrc->i_mode; ++ ia.ia_uid = h_isrc->i_uid; ++ ia.ia_gid = h_isrc->i_gid; ++ sbits = !!(ia.ia_mode & (S_ISUID | S_ISGID)); ++ au_cpup_attr_flags(d_inode(h_path->dentry), h_isrc->i_flags); ++ /* no delegation since it is just created */ ++ err = vfsub_sio_notify_change(h_path, &ia, /*delegated*/NULL); ++ ++ /* is this nfs only? */ ++ if (!err && sbits && au_test_nfs(h_path->dentry->d_sb)) { ++ ia.ia_valid = ATTR_FORCE | ATTR_MODE; ++ ia.ia_mode = h_isrc->i_mode; ++ err = vfsub_sio_notify_change(h_path, &ia, /*delegated*/NULL); ++ } ++ ++ return err; ++} ++ ++#define AuCpdown_PARENT_OPQ 1 ++#define AuCpdown_WHED (1 << 1) ++#define AuCpdown_MADE_DIR (1 << 2) ++#define AuCpdown_DIROPQ (1 << 3) ++#define au_ftest_cpdown(flags, name) ((flags) & AuCpdown_##name) ++#define au_fset_cpdown(flags, name) \ ++ do { (flags) |= AuCpdown_##name; } while (0) ++#define au_fclr_cpdown(flags, name) \ ++ do { (flags) &= ~AuCpdown_##name; } while (0) ++ ++static int au_cpdown_dir_opq(struct dentry *dentry, aufs_bindex_t bdst, ++ unsigned int *flags) ++{ ++ int err; ++ struct dentry *opq_dentry; ++ ++ opq_dentry = au_diropq_create(dentry, bdst); ++ err = PTR_ERR(opq_dentry); ++ if (IS_ERR(opq_dentry)) ++ goto out; ++ dput(opq_dentry); ++ au_fset_cpdown(*flags, DIROPQ); ++ ++out: ++ return err; ++} ++ ++static int au_cpdown_dir_wh(struct dentry *dentry, struct dentry *h_parent, ++ struct inode *dir, aufs_bindex_t bdst) ++{ ++ int err; ++ struct path h_path; ++ struct au_branch *br; ++ ++ br = au_sbr(dentry->d_sb, bdst); ++ h_path.dentry = au_wh_lkup(h_parent, &dentry->d_name, br); ++ err = PTR_ERR(h_path.dentry); ++ if (IS_ERR(h_path.dentry)) ++ goto out; ++ ++ err = 0; ++ if (d_is_positive(h_path.dentry)) { ++ h_path.mnt = au_br_mnt(br); ++ err = au_wh_unlink_dentry(au_h_iptr(dir, bdst), &h_path, ++ dentry); ++ } ++ dput(h_path.dentry); ++ ++out: ++ return err; ++} ++ ++static int au_cpdown_dir(struct dentry *dentry, aufs_bindex_t bdst, ++ struct au_pin *pin, ++ struct dentry *h_parent, void *arg) ++{ ++ int err, rerr; ++ aufs_bindex_t bopq, btop; ++ struct path h_path; ++ struct dentry *parent; ++ struct inode *h_dir, *h_inode, *inode, *dir; ++ unsigned int *flags = arg; ++ ++ btop = au_dbtop(dentry); ++ /* dentry is di-locked */ ++ parent = dget_parent(dentry); ++ dir = d_inode(parent); ++ h_dir = d_inode(h_parent); ++ AuDebugOn(h_dir != au_h_iptr(dir, bdst)); ++ IMustLock(h_dir); ++ ++ err = au_lkup_neg(dentry, bdst, /*wh*/0); ++ if (unlikely(err < 0)) ++ goto out; ++ h_path.dentry = au_h_dptr(dentry, bdst); ++ h_path.mnt = au_sbr_mnt(dentry->d_sb, bdst); ++ err = vfsub_sio_mkdir(au_h_iptr(dir, bdst), &h_path, 0755); ++ if (unlikely(err)) ++ goto out_put; ++ au_fset_cpdown(*flags, MADE_DIR); ++ ++ bopq = au_dbdiropq(dentry); ++ au_fclr_cpdown(*flags, WHED); ++ au_fclr_cpdown(*flags, DIROPQ); ++ if (au_dbwh(dentry) == bdst) ++ au_fset_cpdown(*flags, WHED); ++ if (!au_ftest_cpdown(*flags, PARENT_OPQ) && bopq <= bdst) ++ au_fset_cpdown(*flags, PARENT_OPQ); ++ h_inode = d_inode(h_path.dentry); ++ inode_lock_nested(h_inode, AuLsc_I_CHILD); ++ if (au_ftest_cpdown(*flags, WHED)) { ++ err = au_cpdown_dir_opq(dentry, bdst, flags); ++ if (unlikely(err)) { ++ inode_unlock(h_inode); ++ goto out_dir; ++ } ++ } ++ ++ err = au_cpdown_attr(&h_path, au_h_dptr(dentry, btop)); ++ inode_unlock(h_inode); ++ if (unlikely(err)) ++ goto out_opq; ++ ++ if (au_ftest_cpdown(*flags, WHED)) { ++ err = au_cpdown_dir_wh(dentry, h_parent, dir, bdst); ++ if (unlikely(err)) ++ goto out_opq; ++ } ++ ++ inode = d_inode(dentry); ++ if (au_ibbot(inode) < bdst) ++ au_set_ibbot(inode, bdst); ++ au_set_h_iptr(inode, bdst, au_igrab(h_inode), ++ au_hi_flags(inode, /*isdir*/1)); ++ au_fhsm_wrote(dentry->d_sb, bdst, /*force*/0); ++ goto out; /* success */ ++ ++ /* revert */ ++out_opq: ++ if (au_ftest_cpdown(*flags, DIROPQ)) { ++ inode_lock_nested(h_inode, AuLsc_I_CHILD); ++ rerr = au_diropq_remove(dentry, bdst); ++ inode_unlock(h_inode); ++ if (unlikely(rerr)) { ++ AuIOErr("failed removing diropq for %pd b%d (%d)\n", ++ dentry, bdst, rerr); ++ err = -EIO; ++ goto out; ++ } ++ } ++out_dir: ++ if (au_ftest_cpdown(*flags, MADE_DIR)) { ++ rerr = vfsub_sio_rmdir(au_h_iptr(dir, bdst), &h_path); ++ if (unlikely(rerr)) { ++ AuIOErr("failed removing %pd b%d (%d)\n", ++ dentry, bdst, rerr); ++ err = -EIO; ++ } ++ } ++out_put: ++ au_set_h_dptr(dentry, bdst, NULL); ++ if (au_dbbot(dentry) == bdst) ++ au_update_dbbot(dentry); ++out: ++ dput(parent); ++ return err; ++} ++ ++int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst) ++{ ++ int err; ++ unsigned int flags; ++ ++ flags = 0; ++ err = au_cp_dirs(dentry, bdst, au_cpdown_dir, &flags); ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* policies for create */ ++ ++int au_wbr_nonopq(struct dentry *dentry, aufs_bindex_t bindex) ++{ ++ int err, i, j, ndentry; ++ aufs_bindex_t bopq; ++ struct au_dcsub_pages dpages; ++ struct au_dpage *dpage; ++ struct dentry **dentries, *parent, *d; ++ ++ err = au_dpages_init(&dpages, GFP_NOFS); ++ if (unlikely(err)) ++ goto out; ++ parent = dget_parent(dentry); ++ err = au_dcsub_pages_rev_aufs(&dpages, parent, /*do_include*/0); ++ if (unlikely(err)) ++ goto out_free; ++ ++ err = bindex; ++ for (i = 0; i < dpages.ndpage; i++) { ++ dpage = dpages.dpages + i; ++ dentries = dpage->dentries; ++ ndentry = dpage->ndentry; ++ for (j = 0; j < ndentry; j++) { ++ d = dentries[j]; ++ di_read_lock_parent2(d, !AuLock_IR); ++ bopq = au_dbdiropq(d); ++ di_read_unlock(d, !AuLock_IR); ++ if (bopq >= 0 && bopq < err) ++ err = bopq; ++ } ++ } ++ ++out_free: ++ dput(parent); ++ au_dpages_free(&dpages); ++out: ++ return err; ++} ++ ++static int au_wbr_bu(struct super_block *sb, aufs_bindex_t bindex) ++{ ++ for (; bindex >= 0; bindex--) ++ if (!au_br_rdonly(au_sbr(sb, bindex))) ++ return bindex; ++ return -EROFS; ++} ++ ++/* top down parent */ ++static int au_wbr_create_tdp(struct dentry *dentry, ++ unsigned int flags __maybe_unused) ++{ ++ int err; ++ aufs_bindex_t btop, bindex; ++ struct super_block *sb; ++ struct dentry *parent, *h_parent; ++ ++ sb = dentry->d_sb; ++ btop = au_dbtop(dentry); ++ err = btop; ++ if (!au_br_rdonly(au_sbr(sb, btop))) ++ goto out; ++ ++ err = -EROFS; ++ parent = dget_parent(dentry); ++ for (bindex = au_dbtop(parent); bindex < btop; bindex++) { ++ h_parent = au_h_dptr(parent, bindex); ++ if (!h_parent || d_is_negative(h_parent)) ++ continue; ++ ++ if (!au_br_rdonly(au_sbr(sb, bindex))) { ++ err = bindex; ++ break; ++ } ++ } ++ dput(parent); ++ ++ /* bottom up here */ ++ if (unlikely(err < 0)) { ++ err = au_wbr_bu(sb, btop - 1); ++ if (err >= 0) ++ err = au_wbr_nonopq(dentry, err); ++ } ++ ++out: ++ AuDbg("b%d\n", err); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* an exception for the policy other than tdp */ ++static int au_wbr_create_exp(struct dentry *dentry) ++{ ++ int err; ++ aufs_bindex_t bwh, bdiropq; ++ struct dentry *parent; ++ ++ err = -1; ++ bwh = au_dbwh(dentry); ++ parent = dget_parent(dentry); ++ bdiropq = au_dbdiropq(parent); ++ if (bwh >= 0) { ++ if (bdiropq >= 0) ++ err = min(bdiropq, bwh); ++ else ++ err = bwh; ++ AuDbg("%d\n", err); ++ } else if (bdiropq >= 0) { ++ err = bdiropq; ++ AuDbg("%d\n", err); ++ } ++ dput(parent); ++ ++ if (err >= 0) ++ err = au_wbr_nonopq(dentry, err); ++ ++ if (err >= 0 && au_br_rdonly(au_sbr(dentry->d_sb, err))) ++ err = -1; ++ ++ AuDbg("%d\n", err); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* round robin */ ++static int au_wbr_create_init_rr(struct super_block *sb) ++{ ++ int err; ++ ++ err = au_wbr_bu(sb, au_sbbot(sb)); ++ atomic_set(&au_sbi(sb)->si_wbr_rr_next, -err); /* less important */ ++ /* smp_mb(); */ ++ ++ AuDbg("b%d\n", err); ++ return err; ++} ++ ++static int au_wbr_create_rr(struct dentry *dentry, unsigned int flags) ++{ ++ int err, nbr; ++ unsigned int u; ++ aufs_bindex_t bindex, bbot; ++ struct super_block *sb; ++ atomic_t *next; ++ ++ err = au_wbr_create_exp(dentry); ++ if (err >= 0) ++ goto out; ++ ++ sb = dentry->d_sb; ++ next = &au_sbi(sb)->si_wbr_rr_next; ++ bbot = au_sbbot(sb); ++ nbr = bbot + 1; ++ for (bindex = 0; bindex <= bbot; bindex++) { ++ if (!au_ftest_wbr(flags, DIR)) { ++ err = atomic_dec_return(next) + 1; ++ /* modulo for 0 is meaningless */ ++ if (unlikely(!err)) ++ err = atomic_dec_return(next) + 1; ++ } else ++ err = atomic_read(next); ++ AuDbg("%d\n", err); ++ u = err; ++ err = u % nbr; ++ AuDbg("%d\n", err); ++ if (!au_br_rdonly(au_sbr(sb, err))) ++ break; ++ err = -EROFS; ++ } ++ ++ if (err >= 0) ++ err = au_wbr_nonopq(dentry, err); ++ ++out: ++ AuDbg("%d\n", err); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* most free space */ ++static void au_mfs(struct dentry *dentry, struct dentry *parent) ++{ ++ struct super_block *sb; ++ struct au_branch *br; ++ struct au_wbr_mfs *mfs; ++ struct dentry *h_parent; ++ aufs_bindex_t bindex, bbot; ++ int err; ++ unsigned long long b, bavail; ++ struct path h_path; ++ /* reduce the stack usage */ ++ struct kstatfs *st; ++ ++ st = kmalloc(sizeof(*st), GFP_NOFS); ++ if (unlikely(!st)) { ++ AuWarn1("failed updating mfs(%d), ignored\n", -ENOMEM); ++ return; ++ } ++ ++ bavail = 0; ++ sb = dentry->d_sb; ++ mfs = &au_sbi(sb)->si_wbr_mfs; ++ MtxMustLock(&mfs->mfs_lock); ++ mfs->mfs_bindex = -EROFS; ++ mfs->mfsrr_bytes = 0; ++ if (!parent) { ++ bindex = 0; ++ bbot = au_sbbot(sb); ++ } else { ++ bindex = au_dbtop(parent); ++ bbot = au_dbtaildir(parent); ++ } ++ ++ for (; bindex <= bbot; bindex++) { ++ if (parent) { ++ h_parent = au_h_dptr(parent, bindex); ++ if (!h_parent || d_is_negative(h_parent)) ++ continue; ++ } ++ br = au_sbr(sb, bindex); ++ if (au_br_rdonly(br)) ++ continue; ++ ++ /* sb->s_root for NFS is unreliable */ ++ h_path.mnt = au_br_mnt(br); ++ h_path.dentry = h_path.mnt->mnt_root; ++ err = vfs_statfs(&h_path, st); ++ if (unlikely(err)) { ++ AuWarn1("failed statfs, b%d, %d\n", bindex, err); ++ continue; ++ } ++ ++ /* when the available size is equal, select the lower one */ ++ BUILD_BUG_ON(sizeof(b) < sizeof(st->f_bavail) ++ || sizeof(b) < sizeof(st->f_bsize)); ++ b = st->f_bavail * st->f_bsize; ++ br->br_wbr->wbr_bytes = b; ++ if (b >= bavail) { ++ bavail = b; ++ mfs->mfs_bindex = bindex; ++ mfs->mfs_jiffy = jiffies; ++ } ++ } ++ ++ mfs->mfsrr_bytes = bavail; ++ AuDbg("b%d\n", mfs->mfs_bindex); ++ au_kfree_rcu(st); ++} ++ ++static int au_wbr_create_mfs(struct dentry *dentry, unsigned int flags) ++{ ++ int err; ++ struct dentry *parent; ++ struct super_block *sb; ++ struct au_wbr_mfs *mfs; ++ ++ err = au_wbr_create_exp(dentry); ++ if (err >= 0) ++ goto out; ++ ++ sb = dentry->d_sb; ++ parent = NULL; ++ if (au_ftest_wbr(flags, PARENT)) ++ parent = dget_parent(dentry); ++ mfs = &au_sbi(sb)->si_wbr_mfs; ++ mutex_lock(&mfs->mfs_lock); ++ if (time_after(jiffies, mfs->mfs_jiffy + mfs->mfs_expire) ++ || mfs->mfs_bindex < 0 ++ || au_br_rdonly(au_sbr(sb, mfs->mfs_bindex))) ++ au_mfs(dentry, parent); ++ mutex_unlock(&mfs->mfs_lock); ++ err = mfs->mfs_bindex; ++ dput(parent); ++ ++ if (err >= 0) ++ err = au_wbr_nonopq(dentry, err); ++ ++out: ++ AuDbg("b%d\n", err); ++ return err; ++} ++ ++static int au_wbr_create_init_mfs(struct super_block *sb) ++{ ++ struct au_wbr_mfs *mfs; ++ ++ mfs = &au_sbi(sb)->si_wbr_mfs; ++ mutex_init(&mfs->mfs_lock); ++ mfs->mfs_jiffy = 0; ++ mfs->mfs_bindex = -EROFS; ++ ++ return 0; ++} ++ ++static int au_wbr_create_fin_mfs(struct super_block *sb __maybe_unused) ++{ ++ mutex_destroy(&au_sbi(sb)->si_wbr_mfs.mfs_lock); ++ return 0; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* top down regardless parent, and then mfs */ ++static int au_wbr_create_tdmfs(struct dentry *dentry, ++ unsigned int flags __maybe_unused) ++{ ++ int err; ++ aufs_bindex_t bwh, btail, bindex, bfound, bmfs; ++ unsigned long long watermark; ++ struct super_block *sb; ++ struct au_wbr_mfs *mfs; ++ struct au_branch *br; ++ struct dentry *parent; ++ ++ sb = dentry->d_sb; ++ mfs = &au_sbi(sb)->si_wbr_mfs; ++ mutex_lock(&mfs->mfs_lock); ++ if (time_after(jiffies, mfs->mfs_jiffy + mfs->mfs_expire) ++ || mfs->mfs_bindex < 0) ++ au_mfs(dentry, /*parent*/NULL); ++ watermark = mfs->mfsrr_watermark; ++ bmfs = mfs->mfs_bindex; ++ mutex_unlock(&mfs->mfs_lock); ++ ++ /* another style of au_wbr_create_exp() */ ++ bwh = au_dbwh(dentry); ++ parent = dget_parent(dentry); ++ btail = au_dbtaildir(parent); ++ if (bwh >= 0 && bwh < btail) ++ btail = bwh; ++ ++ err = au_wbr_nonopq(dentry, btail); ++ if (unlikely(err < 0)) ++ goto out; ++ btail = err; ++ bfound = -1; ++ for (bindex = 0; bindex <= btail; bindex++) { ++ br = au_sbr(sb, bindex); ++ if (au_br_rdonly(br)) ++ continue; ++ if (br->br_wbr->wbr_bytes > watermark) { ++ bfound = bindex; ++ break; ++ } ++ } ++ err = bfound; ++ if (err < 0) ++ err = bmfs; ++ ++out: ++ dput(parent); ++ AuDbg("b%d\n", err); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* most free space and then round robin */ ++static int au_wbr_create_mfsrr(struct dentry *dentry, unsigned int flags) ++{ ++ int err; ++ struct au_wbr_mfs *mfs; ++ ++ err = au_wbr_create_mfs(dentry, flags); ++ if (err >= 0) { ++ mfs = &au_sbi(dentry->d_sb)->si_wbr_mfs; ++ mutex_lock(&mfs->mfs_lock); ++ if (mfs->mfsrr_bytes < mfs->mfsrr_watermark) ++ err = au_wbr_create_rr(dentry, flags); ++ mutex_unlock(&mfs->mfs_lock); ++ } ++ ++ AuDbg("b%d\n", err); ++ return err; ++} ++ ++static int au_wbr_create_init_mfsrr(struct super_block *sb) ++{ ++ int err; ++ ++ au_wbr_create_init_mfs(sb); /* ignore */ ++ err = au_wbr_create_init_rr(sb); ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* top down parent and most free space */ ++static int au_wbr_create_pmfs(struct dentry *dentry, unsigned int flags) ++{ ++ int err, e2; ++ unsigned long long b; ++ aufs_bindex_t bindex, btop, bbot; ++ struct super_block *sb; ++ struct dentry *parent, *h_parent; ++ struct au_branch *br; ++ ++ err = au_wbr_create_tdp(dentry, flags); ++ if (unlikely(err < 0)) ++ goto out; ++ parent = dget_parent(dentry); ++ btop = au_dbtop(parent); ++ bbot = au_dbtaildir(parent); ++ if (btop == bbot) ++ goto out_parent; /* success */ ++ ++ e2 = au_wbr_create_mfs(dentry, flags); ++ if (e2 < 0) ++ goto out_parent; /* success */ ++ ++ /* when the available size is equal, select upper one */ ++ sb = dentry->d_sb; ++ br = au_sbr(sb, err); ++ b = br->br_wbr->wbr_bytes; ++ AuDbg("b%d, %llu\n", err, b); ++ ++ for (bindex = btop; bindex <= bbot; bindex++) { ++ h_parent = au_h_dptr(parent, bindex); ++ if (!h_parent || d_is_negative(h_parent)) ++ continue; ++ ++ br = au_sbr(sb, bindex); ++ if (!au_br_rdonly(br) && br->br_wbr->wbr_bytes > b) { ++ b = br->br_wbr->wbr_bytes; ++ err = bindex; ++ AuDbg("b%d, %llu\n", err, b); ++ } ++ } ++ ++ if (err >= 0) ++ err = au_wbr_nonopq(dentry, err); ++ ++out_parent: ++ dput(parent); ++out: ++ AuDbg("b%d\n", err); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * - top down parent ++ * - most free space with parent ++ * - most free space round-robin regardless parent ++ */ ++static int au_wbr_create_pmfsrr(struct dentry *dentry, unsigned int flags) ++{ ++ int err; ++ unsigned long long watermark; ++ struct super_block *sb; ++ struct au_branch *br; ++ struct au_wbr_mfs *mfs; ++ ++ err = au_wbr_create_pmfs(dentry, flags | AuWbr_PARENT); ++ if (unlikely(err < 0)) ++ goto out; ++ ++ sb = dentry->d_sb; ++ br = au_sbr(sb, err); ++ mfs = &au_sbi(sb)->si_wbr_mfs; ++ mutex_lock(&mfs->mfs_lock); ++ watermark = mfs->mfsrr_watermark; ++ mutex_unlock(&mfs->mfs_lock); ++ if (br->br_wbr->wbr_bytes < watermark) ++ /* regardless the parent dir */ ++ err = au_wbr_create_mfsrr(dentry, flags); ++ ++out: ++ AuDbg("b%d\n", err); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* policies for copyup */ ++ ++/* top down parent */ ++static int au_wbr_copyup_tdp(struct dentry *dentry) ++{ ++ return au_wbr_create_tdp(dentry, /*flags, anything is ok*/0); ++} ++ ++/* bottom up parent */ ++static int au_wbr_copyup_bup(struct dentry *dentry) ++{ ++ int err; ++ aufs_bindex_t bindex, btop; ++ struct dentry *parent, *h_parent; ++ struct super_block *sb; ++ ++ err = -EROFS; ++ sb = dentry->d_sb; ++ parent = dget_parent(dentry); ++ btop = au_dbtop(parent); ++ for (bindex = au_dbtop(dentry); bindex >= btop; bindex--) { ++ h_parent = au_h_dptr(parent, bindex); ++ if (!h_parent || d_is_negative(h_parent)) ++ continue; ++ ++ if (!au_br_rdonly(au_sbr(sb, bindex))) { ++ err = bindex; ++ break; ++ } ++ } ++ dput(parent); ++ ++ /* bottom up here */ ++ if (unlikely(err < 0)) ++ err = au_wbr_bu(sb, btop - 1); ++ ++ AuDbg("b%d\n", err); ++ return err; ++} ++ ++/* bottom up */ ++int au_wbr_do_copyup_bu(struct dentry *dentry, aufs_bindex_t btop) ++{ ++ int err; ++ ++ err = au_wbr_bu(dentry->d_sb, btop); ++ AuDbg("b%d\n", err); ++ if (err > btop) ++ err = au_wbr_nonopq(dentry, err); ++ ++ AuDbg("b%d\n", err); ++ return err; ++} ++ ++static int au_wbr_copyup_bu(struct dentry *dentry) ++{ ++ int err; ++ aufs_bindex_t btop; ++ ++ btop = au_dbtop(dentry); ++ err = au_wbr_do_copyup_bu(dentry, btop); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++struct au_wbr_copyup_operations au_wbr_copyup_ops[] = { ++ [AuWbrCopyup_TDP] = { ++ .copyup = au_wbr_copyup_tdp ++ }, ++ [AuWbrCopyup_BUP] = { ++ .copyup = au_wbr_copyup_bup ++ }, ++ [AuWbrCopyup_BU] = { ++ .copyup = au_wbr_copyup_bu ++ } ++}; ++ ++struct au_wbr_create_operations au_wbr_create_ops[] = { ++ [AuWbrCreate_TDP] = { ++ .create = au_wbr_create_tdp ++ }, ++ [AuWbrCreate_RR] = { ++ .create = au_wbr_create_rr, ++ .init = au_wbr_create_init_rr ++ }, ++ [AuWbrCreate_MFS] = { ++ .create = au_wbr_create_mfs, ++ .init = au_wbr_create_init_mfs, ++ .fin = au_wbr_create_fin_mfs ++ }, ++ [AuWbrCreate_MFSV] = { ++ .create = au_wbr_create_mfs, ++ .init = au_wbr_create_init_mfs, ++ .fin = au_wbr_create_fin_mfs ++ }, ++ [AuWbrCreate_MFSRR] = { ++ .create = au_wbr_create_mfsrr, ++ .init = au_wbr_create_init_mfsrr, ++ .fin = au_wbr_create_fin_mfs ++ }, ++ [AuWbrCreate_MFSRRV] = { ++ .create = au_wbr_create_mfsrr, ++ .init = au_wbr_create_init_mfsrr, ++ .fin = au_wbr_create_fin_mfs ++ }, ++ [AuWbrCreate_TDMFS] = { ++ .create = au_wbr_create_tdmfs, ++ .init = au_wbr_create_init_mfs, ++ .fin = au_wbr_create_fin_mfs ++ }, ++ [AuWbrCreate_TDMFSV] = { ++ .create = au_wbr_create_tdmfs, ++ .init = au_wbr_create_init_mfs, ++ .fin = au_wbr_create_fin_mfs ++ }, ++ [AuWbrCreate_PMFS] = { ++ .create = au_wbr_create_pmfs, ++ .init = au_wbr_create_init_mfs, ++ .fin = au_wbr_create_fin_mfs ++ }, ++ [AuWbrCreate_PMFSV] = { ++ .create = au_wbr_create_pmfs, ++ .init = au_wbr_create_init_mfs, ++ .fin = au_wbr_create_fin_mfs ++ }, ++ [AuWbrCreate_PMFSRR] = { ++ .create = au_wbr_create_pmfsrr, ++ .init = au_wbr_create_init_mfsrr, ++ .fin = au_wbr_create_fin_mfs ++ }, ++ [AuWbrCreate_PMFSRRV] = { ++ .create = au_wbr_create_pmfsrr, ++ .init = au_wbr_create_init_mfsrr, ++ .fin = au_wbr_create_fin_mfs ++ } ++}; +diff -Nurp linux-5.4/fs/aufs/vdir.c linux-5.4-aufs/fs/aufs/vdir.c +--- linux-5.4/fs/aufs/vdir.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/vdir.c 2019-11-28 01:25:59.068925618 +0200 +@@ -0,0 +1,883 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * virtual or vertical directory ++ */ ++ ++#include ++#include "aufs.h" ++ ++static unsigned int calc_size(int nlen) ++{ ++ return ALIGN(sizeof(struct au_vdir_de) + nlen, sizeof(ino_t)); ++} ++ ++static int set_deblk_end(union au_vdir_deblk_p *p, ++ union au_vdir_deblk_p *deblk_end) ++{ ++ if (calc_size(0) <= deblk_end->deblk - p->deblk) { ++ p->de->de_str.len = 0; ++ /* smp_mb(); */ ++ return 0; ++ } ++ return -1; /* error */ ++} ++ ++/* returns true or false */ ++static int is_deblk_end(union au_vdir_deblk_p *p, ++ union au_vdir_deblk_p *deblk_end) ++{ ++ if (calc_size(0) <= deblk_end->deblk - p->deblk) ++ return !p->de->de_str.len; ++ return 1; ++} ++ ++static unsigned char *last_deblk(struct au_vdir *vdir) ++{ ++ return vdir->vd_deblk[vdir->vd_nblk - 1]; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* estimate the appropriate size for name hash table */ ++unsigned int au_rdhash_est(loff_t sz) ++{ ++ unsigned int n; ++ ++ n = UINT_MAX; ++ sz >>= 10; ++ if (sz < n) ++ n = sz; ++ if (sz < AUFS_RDHASH_DEF) ++ n = AUFS_RDHASH_DEF; ++ /* pr_info("n %u\n", n); */ ++ return n; ++} ++ ++/* ++ * the allocated memory has to be freed by ++ * au_nhash_wh_free() or au_nhash_de_free(). ++ */ ++int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp) ++{ ++ struct hlist_head *head; ++ unsigned int u; ++ size_t sz; ++ ++ sz = sizeof(*nhash->nh_head) * num_hash; ++ head = kmalloc(sz, gfp); ++ if (head) { ++ nhash->nh_num = num_hash; ++ nhash->nh_head = head; ++ for (u = 0; u < num_hash; u++) ++ INIT_HLIST_HEAD(head++); ++ return 0; /* success */ ++ } ++ ++ return -ENOMEM; ++} ++ ++static void nhash_count(struct hlist_head *head) ++{ ++#if 0 ++ unsigned long n; ++ struct hlist_node *pos; ++ ++ n = 0; ++ hlist_for_each(pos, head) ++ n++; ++ pr_info("%lu\n", n); ++#endif ++} ++ ++static void au_nhash_wh_do_free(struct hlist_head *head) ++{ ++ struct au_vdir_wh *pos; ++ struct hlist_node *node; ++ ++ hlist_for_each_entry_safe(pos, node, head, wh_hash) ++ au_kfree_rcu(pos); ++} ++ ++static void au_nhash_de_do_free(struct hlist_head *head) ++{ ++ struct au_vdir_dehstr *pos; ++ struct hlist_node *node; ++ ++ hlist_for_each_entry_safe(pos, node, head, hash) ++ au_cache_free_vdir_dehstr(pos); ++} ++ ++static void au_nhash_do_free(struct au_nhash *nhash, ++ void (*free)(struct hlist_head *head)) ++{ ++ unsigned int n; ++ struct hlist_head *head; ++ ++ n = nhash->nh_num; ++ if (!n) ++ return; ++ ++ head = nhash->nh_head; ++ while (n-- > 0) { ++ nhash_count(head); ++ free(head++); ++ } ++ au_kfree_try_rcu(nhash->nh_head); ++} ++ ++void au_nhash_wh_free(struct au_nhash *whlist) ++{ ++ au_nhash_do_free(whlist, au_nhash_wh_do_free); ++} ++ ++static void au_nhash_de_free(struct au_nhash *delist) ++{ ++ au_nhash_do_free(delist, au_nhash_de_do_free); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt, ++ int limit) ++{ ++ int num; ++ unsigned int u, n; ++ struct hlist_head *head; ++ struct au_vdir_wh *pos; ++ ++ num = 0; ++ n = whlist->nh_num; ++ head = whlist->nh_head; ++ for (u = 0; u < n; u++, head++) ++ hlist_for_each_entry(pos, head, wh_hash) ++ if (pos->wh_bindex == btgt && ++num > limit) ++ return 1; ++ return 0; ++} ++ ++static struct hlist_head *au_name_hash(struct au_nhash *nhash, ++ unsigned char *name, ++ unsigned int len) ++{ ++ unsigned int v; ++ /* const unsigned int magic_bit = 12; */ ++ ++ AuDebugOn(!nhash->nh_num || !nhash->nh_head); ++ ++ v = 0; ++ if (len > 8) ++ len = 8; ++ while (len--) ++ v += *name++; ++ /* v = hash_long(v, magic_bit); */ ++ v %= nhash->nh_num; ++ return nhash->nh_head + v; ++} ++ ++static int au_nhash_test_name(struct au_vdir_destr *str, const char *name, ++ int nlen) ++{ ++ return str->len == nlen && !memcmp(str->name, name, nlen); ++} ++ ++/* returns found or not */ ++int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen) ++{ ++ struct hlist_head *head; ++ struct au_vdir_wh *pos; ++ struct au_vdir_destr *str; ++ ++ head = au_name_hash(whlist, name, nlen); ++ hlist_for_each_entry(pos, head, wh_hash) { ++ str = &pos->wh_str; ++ AuDbg("%.*s\n", str->len, str->name); ++ if (au_nhash_test_name(str, name, nlen)) ++ return 1; ++ } ++ return 0; ++} ++ ++/* returns found(true) or not */ ++static int test_known(struct au_nhash *delist, char *name, int nlen) ++{ ++ struct hlist_head *head; ++ struct au_vdir_dehstr *pos; ++ struct au_vdir_destr *str; ++ ++ head = au_name_hash(delist, name, nlen); ++ hlist_for_each_entry(pos, head, hash) { ++ str = pos->str; ++ AuDbg("%.*s\n", str->len, str->name); ++ if (au_nhash_test_name(str, name, nlen)) ++ return 1; ++ } ++ return 0; ++} ++ ++static void au_shwh_init_wh(struct au_vdir_wh *wh, ino_t ino, ++ unsigned char d_type) ++{ ++#ifdef CONFIG_AUFS_SHWH ++ wh->wh_ino = ino; ++ wh->wh_type = d_type; ++#endif ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino, ++ unsigned int d_type, aufs_bindex_t bindex, ++ unsigned char shwh) ++{ ++ int err; ++ struct au_vdir_destr *str; ++ struct au_vdir_wh *wh; ++ ++ AuDbg("%.*s\n", nlen, name); ++ AuDebugOn(!whlist->nh_num || !whlist->nh_head); ++ ++ err = -ENOMEM; ++ wh = kmalloc(sizeof(*wh) + nlen, GFP_NOFS); ++ if (unlikely(!wh)) ++ goto out; ++ ++ err = 0; ++ wh->wh_bindex = bindex; ++ if (shwh) ++ au_shwh_init_wh(wh, ino, d_type); ++ str = &wh->wh_str; ++ str->len = nlen; ++ memcpy(str->name, name, nlen); ++ hlist_add_head(&wh->wh_hash, au_name_hash(whlist, name, nlen)); ++ /* smp_mb(); */ ++ ++out: ++ return err; ++} ++ ++static int append_deblk(struct au_vdir *vdir) ++{ ++ int err; ++ unsigned long ul; ++ const unsigned int deblk_sz = vdir->vd_deblk_sz; ++ union au_vdir_deblk_p p, deblk_end; ++ unsigned char **o; ++ ++ err = -ENOMEM; ++ o = au_krealloc(vdir->vd_deblk, sizeof(*o) * (vdir->vd_nblk + 1), ++ GFP_NOFS, /*may_shrink*/0); ++ if (unlikely(!o)) ++ goto out; ++ ++ vdir->vd_deblk = o; ++ p.deblk = kmalloc(deblk_sz, GFP_NOFS); ++ if (p.deblk) { ++ ul = vdir->vd_nblk++; ++ vdir->vd_deblk[ul] = p.deblk; ++ vdir->vd_last.ul = ul; ++ vdir->vd_last.p.deblk = p.deblk; ++ deblk_end.deblk = p.deblk + deblk_sz; ++ err = set_deblk_end(&p, &deblk_end); ++ } ++ ++out: ++ return err; ++} ++ ++static int append_de(struct au_vdir *vdir, char *name, int nlen, ino_t ino, ++ unsigned int d_type, struct au_nhash *delist) ++{ ++ int err; ++ unsigned int sz; ++ const unsigned int deblk_sz = vdir->vd_deblk_sz; ++ union au_vdir_deblk_p p, *room, deblk_end; ++ struct au_vdir_dehstr *dehstr; ++ ++ p.deblk = last_deblk(vdir); ++ deblk_end.deblk = p.deblk + deblk_sz; ++ room = &vdir->vd_last.p; ++ AuDebugOn(room->deblk < p.deblk || deblk_end.deblk <= room->deblk ++ || !is_deblk_end(room, &deblk_end)); ++ ++ sz = calc_size(nlen); ++ if (unlikely(sz > deblk_end.deblk - room->deblk)) { ++ err = append_deblk(vdir); ++ if (unlikely(err)) ++ goto out; ++ ++ p.deblk = last_deblk(vdir); ++ deblk_end.deblk = p.deblk + deblk_sz; ++ /* smp_mb(); */ ++ AuDebugOn(room->deblk != p.deblk); ++ } ++ ++ err = -ENOMEM; ++ dehstr = au_cache_alloc_vdir_dehstr(); ++ if (unlikely(!dehstr)) ++ goto out; ++ ++ dehstr->str = &room->de->de_str; ++ hlist_add_head(&dehstr->hash, au_name_hash(delist, name, nlen)); ++ room->de->de_ino = ino; ++ room->de->de_type = d_type; ++ room->de->de_str.len = nlen; ++ memcpy(room->de->de_str.name, name, nlen); ++ ++ err = 0; ++ room->deblk += sz; ++ if (unlikely(set_deblk_end(room, &deblk_end))) ++ err = append_deblk(vdir); ++ /* smp_mb(); */ ++ ++out: ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++void au_vdir_free(struct au_vdir *vdir) ++{ ++ unsigned char **deblk; ++ ++ deblk = vdir->vd_deblk; ++ while (vdir->vd_nblk--) ++ au_kfree_try_rcu(*deblk++); ++ au_kfree_try_rcu(vdir->vd_deblk); ++ au_cache_free_vdir(vdir); ++} ++ ++static struct au_vdir *alloc_vdir(struct file *file) ++{ ++ struct au_vdir *vdir; ++ struct super_block *sb; ++ int err; ++ ++ sb = file->f_path.dentry->d_sb; ++ SiMustAnyLock(sb); ++ ++ err = -ENOMEM; ++ vdir = au_cache_alloc_vdir(); ++ if (unlikely(!vdir)) ++ goto out; ++ ++ vdir->vd_deblk = kzalloc(sizeof(*vdir->vd_deblk), GFP_NOFS); ++ if (unlikely(!vdir->vd_deblk)) ++ goto out_free; ++ ++ vdir->vd_deblk_sz = au_sbi(sb)->si_rdblk; ++ if (!vdir->vd_deblk_sz) { ++ /* estimate the appropriate size for deblk */ ++ vdir->vd_deblk_sz = au_dir_size(file, /*dentry*/NULL); ++ /* pr_info("vd_deblk_sz %u\n", vdir->vd_deblk_sz); */ ++ } ++ vdir->vd_nblk = 0; ++ vdir->vd_version = 0; ++ vdir->vd_jiffy = 0; ++ err = append_deblk(vdir); ++ if (!err) ++ return vdir; /* success */ ++ ++ au_kfree_try_rcu(vdir->vd_deblk); ++ ++out_free: ++ au_cache_free_vdir(vdir); ++out: ++ vdir = ERR_PTR(err); ++ return vdir; ++} ++ ++static int reinit_vdir(struct au_vdir *vdir) ++{ ++ int err; ++ union au_vdir_deblk_p p, deblk_end; ++ ++ while (vdir->vd_nblk > 1) { ++ au_kfree_try_rcu(vdir->vd_deblk[vdir->vd_nblk - 1]); ++ /* vdir->vd_deblk[vdir->vd_nblk - 1] = NULL; */ ++ vdir->vd_nblk--; ++ } ++ p.deblk = vdir->vd_deblk[0]; ++ deblk_end.deblk = p.deblk + vdir->vd_deblk_sz; ++ err = set_deblk_end(&p, &deblk_end); ++ /* keep vd_dblk_sz */ ++ vdir->vd_last.ul = 0; ++ vdir->vd_last.p.deblk = vdir->vd_deblk[0]; ++ vdir->vd_version = 0; ++ vdir->vd_jiffy = 0; ++ /* smp_mb(); */ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++#define AuFillVdir_CALLED 1 ++#define AuFillVdir_WHABLE (1 << 1) ++#define AuFillVdir_SHWH (1 << 2) ++#define au_ftest_fillvdir(flags, name) ((flags) & AuFillVdir_##name) ++#define au_fset_fillvdir(flags, name) \ ++ do { (flags) |= AuFillVdir_##name; } while (0) ++#define au_fclr_fillvdir(flags, name) \ ++ do { (flags) &= ~AuFillVdir_##name; } while (0) ++ ++#ifndef CONFIG_AUFS_SHWH ++#undef AuFillVdir_SHWH ++#define AuFillVdir_SHWH 0 ++#endif ++ ++struct fillvdir_arg { ++ struct dir_context ctx; ++ struct file *file; ++ struct au_vdir *vdir; ++ struct au_nhash delist; ++ struct au_nhash whlist; ++ aufs_bindex_t bindex; ++ unsigned int flags; ++ int err; ++}; ++ ++static int fillvdir(struct dir_context *ctx, const char *__name, int nlen, ++ loff_t offset __maybe_unused, u64 h_ino, ++ unsigned int d_type) ++{ ++ struct fillvdir_arg *arg = container_of(ctx, struct fillvdir_arg, ctx); ++ char *name = (void *)__name; ++ struct super_block *sb; ++ ino_t ino; ++ const unsigned char shwh = !!au_ftest_fillvdir(arg->flags, SHWH); ++ ++ arg->err = 0; ++ sb = arg->file->f_path.dentry->d_sb; ++ au_fset_fillvdir(arg->flags, CALLED); ++ /* smp_mb(); */ ++ if (nlen <= AUFS_WH_PFX_LEN ++ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) { ++ if (test_known(&arg->delist, name, nlen) ++ || au_nhash_test_known_wh(&arg->whlist, name, nlen)) ++ goto out; /* already exists or whiteouted */ ++ ++ arg->err = au_ino(sb, arg->bindex, h_ino, d_type, &ino); ++ if (!arg->err) { ++ if (unlikely(nlen > AUFS_MAX_NAMELEN)) ++ d_type = DT_UNKNOWN; ++ arg->err = append_de(arg->vdir, name, nlen, ino, ++ d_type, &arg->delist); ++ } ++ } else if (au_ftest_fillvdir(arg->flags, WHABLE)) { ++ name += AUFS_WH_PFX_LEN; ++ nlen -= AUFS_WH_PFX_LEN; ++ if (au_nhash_test_known_wh(&arg->whlist, name, nlen)) ++ goto out; /* already whiteouted */ ++ ++ ino = 0; /* just to suppress a warning */ ++ if (shwh) ++ arg->err = au_wh_ino(sb, arg->bindex, h_ino, d_type, ++ &ino); ++ if (!arg->err) { ++ if (nlen <= AUFS_MAX_NAMELEN + AUFS_WH_PFX_LEN) ++ d_type = DT_UNKNOWN; ++ arg->err = au_nhash_append_wh ++ (&arg->whlist, name, nlen, ino, d_type, ++ arg->bindex, shwh); ++ } ++ } ++ ++out: ++ if (!arg->err) ++ arg->vdir->vd_jiffy = jiffies; ++ /* smp_mb(); */ ++ AuTraceErr(arg->err); ++ return arg->err; ++} ++ ++static int au_handle_shwh(struct super_block *sb, struct au_vdir *vdir, ++ struct au_nhash *whlist, struct au_nhash *delist) ++{ ++#ifdef CONFIG_AUFS_SHWH ++ int err; ++ unsigned int nh, u; ++ struct hlist_head *head; ++ struct au_vdir_wh *pos; ++ struct hlist_node *n; ++ char *p, *o; ++ struct au_vdir_destr *destr; ++ ++ AuDebugOn(!au_opt_test(au_mntflags(sb), SHWH)); ++ ++ err = -ENOMEM; ++ o = p = (void *)__get_free_page(GFP_NOFS); ++ if (unlikely(!p)) ++ goto out; ++ ++ err = 0; ++ nh = whlist->nh_num; ++ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN); ++ p += AUFS_WH_PFX_LEN; ++ for (u = 0; u < nh; u++) { ++ head = whlist->nh_head + u; ++ hlist_for_each_entry_safe(pos, n, head, wh_hash) { ++ destr = &pos->wh_str; ++ memcpy(p, destr->name, destr->len); ++ err = append_de(vdir, o, destr->len + AUFS_WH_PFX_LEN, ++ pos->wh_ino, pos->wh_type, delist); ++ if (unlikely(err)) ++ break; ++ } ++ } ++ ++ free_page((unsigned long)o); ++ ++out: ++ AuTraceErr(err); ++ return err; ++#else ++ return 0; ++#endif ++} ++ ++static int au_do_read_vdir(struct fillvdir_arg *arg) ++{ ++ int err; ++ unsigned int rdhash; ++ loff_t offset; ++ aufs_bindex_t bbot, bindex, btop; ++ unsigned char shwh; ++ struct file *hf, *file; ++ struct super_block *sb; ++ ++ file = arg->file; ++ sb = file->f_path.dentry->d_sb; ++ SiMustAnyLock(sb); ++ ++ rdhash = au_sbi(sb)->si_rdhash; ++ if (!rdhash) ++ rdhash = au_rdhash_est(au_dir_size(file, /*dentry*/NULL)); ++ err = au_nhash_alloc(&arg->delist, rdhash, GFP_NOFS); ++ if (unlikely(err)) ++ goto out; ++ err = au_nhash_alloc(&arg->whlist, rdhash, GFP_NOFS); ++ if (unlikely(err)) ++ goto out_delist; ++ ++ err = 0; ++ arg->flags = 0; ++ shwh = 0; ++ if (au_opt_test(au_mntflags(sb), SHWH)) { ++ shwh = 1; ++ au_fset_fillvdir(arg->flags, SHWH); ++ } ++ btop = au_fbtop(file); ++ bbot = au_fbbot_dir(file); ++ for (bindex = btop; !err && bindex <= bbot; bindex++) { ++ hf = au_hf_dir(file, bindex); ++ if (!hf) ++ continue; ++ ++ offset = vfsub_llseek(hf, 0, SEEK_SET); ++ err = offset; ++ if (unlikely(offset)) ++ break; ++ ++ arg->bindex = bindex; ++ au_fclr_fillvdir(arg->flags, WHABLE); ++ if (shwh ++ || (bindex != bbot ++ && au_br_whable(au_sbr_perm(sb, bindex)))) ++ au_fset_fillvdir(arg->flags, WHABLE); ++ do { ++ arg->err = 0; ++ au_fclr_fillvdir(arg->flags, CALLED); ++ /* smp_mb(); */ ++ err = vfsub_iterate_dir(hf, &arg->ctx); ++ if (err >= 0) ++ err = arg->err; ++ } while (!err && au_ftest_fillvdir(arg->flags, CALLED)); ++ ++ /* ++ * dir_relax() may be good for concurrency, but aufs should not ++ * use it since it will cause a lockdep problem. ++ */ ++ } ++ ++ if (!err && shwh) ++ err = au_handle_shwh(sb, arg->vdir, &arg->whlist, &arg->delist); ++ ++ au_nhash_wh_free(&arg->whlist); ++ ++out_delist: ++ au_nhash_de_free(&arg->delist); ++out: ++ return err; ++} ++ ++static int read_vdir(struct file *file, int may_read) ++{ ++ int err; ++ unsigned long expire; ++ unsigned char do_read; ++ struct fillvdir_arg arg = { ++ .ctx = { ++ .actor = fillvdir ++ } ++ }; ++ struct inode *inode; ++ struct au_vdir *vdir, *allocated; ++ ++ err = 0; ++ inode = file_inode(file); ++ IMustLock(inode); ++ IiMustWriteLock(inode); ++ SiMustAnyLock(inode->i_sb); ++ ++ allocated = NULL; ++ do_read = 0; ++ expire = au_sbi(inode->i_sb)->si_rdcache; ++ vdir = au_ivdir(inode); ++ if (!vdir) { ++ do_read = 1; ++ vdir = alloc_vdir(file); ++ err = PTR_ERR(vdir); ++ if (IS_ERR(vdir)) ++ goto out; ++ err = 0; ++ allocated = vdir; ++ } else if (may_read ++ && (!inode_eq_iversion(inode, vdir->vd_version) ++ || time_after(jiffies, vdir->vd_jiffy + expire))) { ++ do_read = 1; ++ err = reinit_vdir(vdir); ++ if (unlikely(err)) ++ goto out; ++ } ++ ++ if (!do_read) ++ return 0; /* success */ ++ ++ arg.file = file; ++ arg.vdir = vdir; ++ err = au_do_read_vdir(&arg); ++ if (!err) { ++ /* file->f_pos = 0; */ /* todo: ctx->pos? */ ++ vdir->vd_version = inode_query_iversion(inode); ++ vdir->vd_last.ul = 0; ++ vdir->vd_last.p.deblk = vdir->vd_deblk[0]; ++ if (allocated) ++ au_set_ivdir(inode, allocated); ++ } else if (allocated) ++ au_vdir_free(allocated); ++ ++out: ++ return err; ++} ++ ++static int copy_vdir(struct au_vdir *tgt, struct au_vdir *src) ++{ ++ int err, rerr; ++ unsigned long ul, n; ++ const unsigned int deblk_sz = src->vd_deblk_sz; ++ ++ AuDebugOn(tgt->vd_nblk != 1); ++ ++ err = -ENOMEM; ++ if (tgt->vd_nblk < src->vd_nblk) { ++ unsigned char **p; ++ ++ p = au_krealloc(tgt->vd_deblk, sizeof(*p) * src->vd_nblk, ++ GFP_NOFS, /*may_shrink*/0); ++ if (unlikely(!p)) ++ goto out; ++ tgt->vd_deblk = p; ++ } ++ ++ if (tgt->vd_deblk_sz != deblk_sz) { ++ unsigned char *p; ++ ++ tgt->vd_deblk_sz = deblk_sz; ++ p = au_krealloc(tgt->vd_deblk[0], deblk_sz, GFP_NOFS, ++ /*may_shrink*/1); ++ if (unlikely(!p)) ++ goto out; ++ tgt->vd_deblk[0] = p; ++ } ++ memcpy(tgt->vd_deblk[0], src->vd_deblk[0], deblk_sz); ++ tgt->vd_version = src->vd_version; ++ tgt->vd_jiffy = src->vd_jiffy; ++ ++ n = src->vd_nblk; ++ for (ul = 1; ul < n; ul++) { ++ tgt->vd_deblk[ul] = kmemdup(src->vd_deblk[ul], deblk_sz, ++ GFP_NOFS); ++ if (unlikely(!tgt->vd_deblk[ul])) ++ goto out; ++ tgt->vd_nblk++; ++ } ++ tgt->vd_nblk = n; ++ tgt->vd_last.ul = tgt->vd_last.ul; ++ tgt->vd_last.p.deblk = tgt->vd_deblk[tgt->vd_last.ul]; ++ tgt->vd_last.p.deblk += src->vd_last.p.deblk ++ - src->vd_deblk[src->vd_last.ul]; ++ /* smp_mb(); */ ++ return 0; /* success */ ++ ++out: ++ rerr = reinit_vdir(tgt); ++ BUG_ON(rerr); ++ return err; ++} ++ ++int au_vdir_init(struct file *file) ++{ ++ int err; ++ struct inode *inode; ++ struct au_vdir *vdir_cache, *allocated; ++ ++ /* test file->f_pos here instead of ctx->pos */ ++ err = read_vdir(file, !file->f_pos); ++ if (unlikely(err)) ++ goto out; ++ ++ allocated = NULL; ++ vdir_cache = au_fvdir_cache(file); ++ if (!vdir_cache) { ++ vdir_cache = alloc_vdir(file); ++ err = PTR_ERR(vdir_cache); ++ if (IS_ERR(vdir_cache)) ++ goto out; ++ allocated = vdir_cache; ++ } else if (!file->f_pos && vdir_cache->vd_version != file->f_version) { ++ /* test file->f_pos here instead of ctx->pos */ ++ err = reinit_vdir(vdir_cache); ++ if (unlikely(err)) ++ goto out; ++ } else ++ return 0; /* success */ ++ ++ inode = file_inode(file); ++ err = copy_vdir(vdir_cache, au_ivdir(inode)); ++ if (!err) { ++ file->f_version = inode_query_iversion(inode); ++ if (allocated) ++ au_set_fvdir_cache(file, allocated); ++ } else if (allocated) ++ au_vdir_free(allocated); ++ ++out: ++ return err; ++} ++ ++static loff_t calc_offset(struct au_vdir *vdir) ++{ ++ loff_t offset; ++ union au_vdir_deblk_p p; ++ ++ p.deblk = vdir->vd_deblk[vdir->vd_last.ul]; ++ offset = vdir->vd_last.p.deblk - p.deblk; ++ offset += vdir->vd_deblk_sz * vdir->vd_last.ul; ++ return offset; ++} ++ ++/* returns true or false */ ++static int seek_vdir(struct file *file, struct dir_context *ctx) ++{ ++ int valid; ++ unsigned int deblk_sz; ++ unsigned long ul, n; ++ loff_t offset; ++ union au_vdir_deblk_p p, deblk_end; ++ struct au_vdir *vdir_cache; ++ ++ valid = 1; ++ vdir_cache = au_fvdir_cache(file); ++ offset = calc_offset(vdir_cache); ++ AuDbg("offset %lld\n", offset); ++ if (ctx->pos == offset) ++ goto out; ++ ++ vdir_cache->vd_last.ul = 0; ++ vdir_cache->vd_last.p.deblk = vdir_cache->vd_deblk[0]; ++ if (!ctx->pos) ++ goto out; ++ ++ valid = 0; ++ deblk_sz = vdir_cache->vd_deblk_sz; ++ ul = div64_u64(ctx->pos, deblk_sz); ++ AuDbg("ul %lu\n", ul); ++ if (ul >= vdir_cache->vd_nblk) ++ goto out; ++ ++ n = vdir_cache->vd_nblk; ++ for (; ul < n; ul++) { ++ p.deblk = vdir_cache->vd_deblk[ul]; ++ deblk_end.deblk = p.deblk + deblk_sz; ++ offset = ul; ++ offset *= deblk_sz; ++ while (!is_deblk_end(&p, &deblk_end) && offset < ctx->pos) { ++ unsigned int l; ++ ++ l = calc_size(p.de->de_str.len); ++ offset += l; ++ p.deblk += l; ++ } ++ if (!is_deblk_end(&p, &deblk_end)) { ++ valid = 1; ++ vdir_cache->vd_last.ul = ul; ++ vdir_cache->vd_last.p = p; ++ break; ++ } ++ } ++ ++out: ++ /* smp_mb(); */ ++ if (!valid) ++ AuDbg("valid %d\n", !valid); ++ return valid; ++} ++ ++int au_vdir_fill_de(struct file *file, struct dir_context *ctx) ++{ ++ unsigned int l, deblk_sz; ++ union au_vdir_deblk_p deblk_end; ++ struct au_vdir *vdir_cache; ++ struct au_vdir_de *de; ++ ++ if (!seek_vdir(file, ctx)) ++ return 0; ++ ++ vdir_cache = au_fvdir_cache(file); ++ deblk_sz = vdir_cache->vd_deblk_sz; ++ while (1) { ++ deblk_end.deblk = vdir_cache->vd_deblk[vdir_cache->vd_last.ul]; ++ deblk_end.deblk += deblk_sz; ++ while (!is_deblk_end(&vdir_cache->vd_last.p, &deblk_end)) { ++ de = vdir_cache->vd_last.p.de; ++ AuDbg("%.*s, off%lld, i%lu, dt%d\n", ++ de->de_str.len, de->de_str.name, ctx->pos, ++ (unsigned long)de->de_ino, de->de_type); ++ if (unlikely(!dir_emit(ctx, de->de_str.name, ++ de->de_str.len, de->de_ino, ++ de->de_type))) { ++ /* todo: ignore the error caused by udba? */ ++ /* return err; */ ++ return 0; ++ } ++ ++ l = calc_size(de->de_str.len); ++ vdir_cache->vd_last.p.deblk += l; ++ ctx->pos += l; ++ } ++ if (vdir_cache->vd_last.ul < vdir_cache->vd_nblk - 1) { ++ vdir_cache->vd_last.ul++; ++ vdir_cache->vd_last.p.deblk ++ = vdir_cache->vd_deblk[vdir_cache->vd_last.ul]; ++ ctx->pos = deblk_sz * vdir_cache->vd_last.ul; ++ continue; ++ } ++ break; ++ } ++ ++ /* smp_mb(); */ ++ return 0; ++} +diff -Nurp linux-5.4/fs/aufs/vfsub.c linux-5.4-aufs/fs/aufs/vfsub.c +--- linux-5.4/fs/aufs/vfsub.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/vfsub.c 2019-11-28 01:25:59.068925618 +0200 +@@ -0,0 +1,889 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * sub-routines for VFS ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include "aufs.h" ++ ++#ifdef CONFIG_AUFS_BR_FUSE ++int vfsub_test_mntns(struct vfsmount *mnt, struct super_block *h_sb) ++{ ++ if (!au_test_fuse(h_sb) || !au_userns) ++ return 0; ++ ++ return is_current_mnt_ns(mnt) ? 0 : -EACCES; ++} ++#endif ++ ++int vfsub_sync_filesystem(struct super_block *h_sb, int wait) ++{ ++ int err; ++ ++ lockdep_off(); ++ down_read(&h_sb->s_umount); ++ err = __sync_filesystem(h_sb, wait); ++ up_read(&h_sb->s_umount); ++ lockdep_on(); ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++int vfsub_update_h_iattr(struct path *h_path, int *did) ++{ ++ int err; ++ struct kstat st; ++ struct super_block *h_sb; ++ ++ /* for remote fs, leave work for its getattr or d_revalidate */ ++ /* for bad i_attr fs, handle them in aufs_getattr() */ ++ /* still some fs may acquire i_mutex. we need to skip them */ ++ err = 0; ++ if (!did) ++ did = &err; ++ h_sb = h_path->dentry->d_sb; ++ *did = (!au_test_fs_remote(h_sb) && au_test_fs_refresh_iattr(h_sb)); ++ if (*did) ++ err = vfsub_getattr(h_path, &st); ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++struct file *vfsub_dentry_open(struct path *path, int flags) ++{ ++ struct file *file; ++ ++ file = dentry_open(path, flags /* | __FMODE_NONOTIFY */, ++ current_cred()); ++ if (!IS_ERR_OR_NULL(file) ++ && (file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) ++ i_readcount_inc(d_inode(path->dentry)); ++ ++ return file; ++} ++ ++struct file *vfsub_filp_open(const char *path, int oflags, int mode) ++{ ++ struct file *file; ++ ++ lockdep_off(); ++ file = filp_open(path, ++ oflags /* | __FMODE_NONOTIFY */, ++ mode); ++ lockdep_on(); ++ if (IS_ERR(file)) ++ goto out; ++ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/ ++ ++out: ++ return file; ++} ++ ++/* ++ * Ideally this function should call VFS:do_last() in order to keep all its ++ * checkings. But it is very hard for aufs to regenerate several VFS internal ++ * structure such as nameidata. This is a second (or third) best approach. ++ * cf. linux/fs/namei.c:do_last(), lookup_open() and atomic_open(). ++ */ ++int vfsub_atomic_open(struct inode *dir, struct dentry *dentry, ++ struct vfsub_aopen_args *args) ++{ ++ int err; ++ struct au_branch *br = args->br; ++ struct file *file = args->file; ++ /* copied from linux/fs/namei.c:atomic_open() */ ++ struct dentry *const DENTRY_NOT_SET = (void *)-1UL; ++ ++ IMustLock(dir); ++ AuDebugOn(!dir->i_op->atomic_open); ++ ++ err = au_br_test_oflag(args->open_flag, br); ++ if (unlikely(err)) ++ goto out; ++ ++ au_lcnt_inc(&br->br_nfiles); ++ file->f_path.dentry = DENTRY_NOT_SET; ++ file->f_path.mnt = au_br_mnt(br); ++ AuDbg("%ps\n", dir->i_op->atomic_open); ++ err = dir->i_op->atomic_open(dir, dentry, file, args->open_flag, ++ args->create_mode); ++ if (unlikely(err < 0)) { ++ au_lcnt_dec(&br->br_nfiles); ++ goto out; ++ } ++ ++ /* temporary workaround for nfsv4 branch */ ++ if (au_test_nfs(dir->i_sb)) ++ nfs_mark_for_revalidate(dir); ++ ++ if (file->f_mode & FMODE_CREATED) ++ fsnotify_create(dir, dentry); ++ if (!(file->f_mode & FMODE_OPENED)) { ++ au_lcnt_dec(&br->br_nfiles); ++ goto out; ++ } ++ ++ /* todo: call VFS:may_open() here */ ++ /* todo: ima_file_check() too? */ ++ if (!err && (args->open_flag & __FMODE_EXEC)) ++ err = deny_write_access(file); ++ if (!err) ++ fsnotify_open(file); ++ else ++ au_lcnt_dec(&br->br_nfiles); ++ /* note that the file is created and still opened */ ++ ++out: ++ return err; ++} ++ ++int vfsub_kern_path(const char *name, unsigned int flags, struct path *path) ++{ ++ int err; ++ ++ err = kern_path(name, flags, path); ++ if (!err && d_is_positive(path->dentry)) ++ vfsub_update_h_iattr(path, /*did*/NULL); /*ignore*/ ++ return err; ++} ++ ++struct dentry *vfsub_lookup_one_len_unlocked(const char *name, ++ struct dentry *parent, int len) ++{ ++ struct path path = { ++ .mnt = NULL ++ }; ++ ++ path.dentry = lookup_one_len_unlocked(name, parent, len); ++ if (IS_ERR(path.dentry)) ++ goto out; ++ if (d_is_positive(path.dentry)) ++ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/ ++ ++out: ++ AuTraceErrPtr(path.dentry); ++ return path.dentry; ++} ++ ++struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent, ++ int len) ++{ ++ struct path path = { ++ .mnt = NULL ++ }; ++ ++ /* VFS checks it too, but by WARN_ON_ONCE() */ ++ IMustLock(d_inode(parent)); ++ ++ path.dentry = lookup_one_len(name, parent, len); ++ if (IS_ERR(path.dentry)) ++ goto out; ++ if (d_is_positive(path.dentry)) ++ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/ ++ ++out: ++ AuTraceErrPtr(path.dentry); ++ return path.dentry; ++} ++ ++void vfsub_call_lkup_one(void *args) ++{ ++ struct vfsub_lkup_one_args *a = args; ++ *a->errp = vfsub_lkup_one(a->name, a->parent); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1, ++ struct dentry *d2, struct au_hinode *hdir2) ++{ ++ struct dentry *d; ++ ++ lockdep_off(); ++ d = lock_rename(d1, d2); ++ lockdep_on(); ++ au_hn_suspend(hdir1); ++ if (hdir1 != hdir2) ++ au_hn_suspend(hdir2); ++ ++ return d; ++} ++ ++void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1, ++ struct dentry *d2, struct au_hinode *hdir2) ++{ ++ au_hn_resume(hdir1); ++ if (hdir1 != hdir2) ++ au_hn_resume(hdir2); ++ lockdep_off(); ++ unlock_rename(d1, d2); ++ lockdep_on(); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++int vfsub_create(struct inode *dir, struct path *path, int mode, bool want_excl) ++{ ++ int err; ++ struct dentry *d; ++ ++ IMustLock(dir); ++ ++ d = path->dentry; ++ path->dentry = d->d_parent; ++ err = security_path_mknod(path, d, mode, 0); ++ path->dentry = d; ++ if (unlikely(err)) ++ goto out; ++ ++ lockdep_off(); ++ err = vfs_create(dir, path->dentry, mode, want_excl); ++ lockdep_on(); ++ if (!err) { ++ struct path tmp = *path; ++ int did; ++ ++ vfsub_update_h_iattr(&tmp, &did); ++ if (did) { ++ tmp.dentry = path->dentry->d_parent; ++ vfsub_update_h_iattr(&tmp, /*did*/NULL); ++ } ++ /*ignore*/ ++ } ++ ++out: ++ return err; ++} ++ ++int vfsub_symlink(struct inode *dir, struct path *path, const char *symname) ++{ ++ int err; ++ struct dentry *d; ++ ++ IMustLock(dir); ++ ++ d = path->dentry; ++ path->dentry = d->d_parent; ++ err = security_path_symlink(path, d, symname); ++ path->dentry = d; ++ if (unlikely(err)) ++ goto out; ++ ++ lockdep_off(); ++ err = vfs_symlink(dir, path->dentry, symname); ++ lockdep_on(); ++ if (!err) { ++ struct path tmp = *path; ++ int did; ++ ++ vfsub_update_h_iattr(&tmp, &did); ++ if (did) { ++ tmp.dentry = path->dentry->d_parent; ++ vfsub_update_h_iattr(&tmp, /*did*/NULL); ++ } ++ /*ignore*/ ++ } ++ ++out: ++ return err; ++} ++ ++int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev) ++{ ++ int err; ++ struct dentry *d; ++ ++ IMustLock(dir); ++ ++ d = path->dentry; ++ path->dentry = d->d_parent; ++ err = security_path_mknod(path, d, mode, new_encode_dev(dev)); ++ path->dentry = d; ++ if (unlikely(err)) ++ goto out; ++ ++ lockdep_off(); ++ err = vfs_mknod(dir, path->dentry, mode, dev); ++ lockdep_on(); ++ if (!err) { ++ struct path tmp = *path; ++ int did; ++ ++ vfsub_update_h_iattr(&tmp, &did); ++ if (did) { ++ tmp.dentry = path->dentry->d_parent; ++ vfsub_update_h_iattr(&tmp, /*did*/NULL); ++ } ++ /*ignore*/ ++ } ++ ++out: ++ return err; ++} ++ ++static int au_test_nlink(struct inode *inode) ++{ ++ const unsigned int link_max = UINT_MAX >> 1; /* rough margin */ ++ ++ if (!au_test_fs_no_limit_nlink(inode->i_sb) ++ || inode->i_nlink < link_max) ++ return 0; ++ return -EMLINK; ++} ++ ++int vfsub_link(struct dentry *src_dentry, struct inode *dir, struct path *path, ++ struct inode **delegated_inode) ++{ ++ int err; ++ struct dentry *d; ++ ++ IMustLock(dir); ++ ++ err = au_test_nlink(d_inode(src_dentry)); ++ if (unlikely(err)) ++ return err; ++ ++ /* we don't call may_linkat() */ ++ d = path->dentry; ++ path->dentry = d->d_parent; ++ err = security_path_link(src_dentry, path, d); ++ path->dentry = d; ++ if (unlikely(err)) ++ goto out; ++ ++ lockdep_off(); ++ err = vfs_link(src_dentry, dir, path->dentry, delegated_inode); ++ lockdep_on(); ++ if (!err) { ++ struct path tmp = *path; ++ int did; ++ ++ /* fuse has different memory inode for the same inumber */ ++ vfsub_update_h_iattr(&tmp, &did); ++ if (did) { ++ tmp.dentry = path->dentry->d_parent; ++ vfsub_update_h_iattr(&tmp, /*did*/NULL); ++ tmp.dentry = src_dentry; ++ vfsub_update_h_iattr(&tmp, /*did*/NULL); ++ } ++ /*ignore*/ ++ } ++ ++out: ++ return err; ++} ++ ++int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry, ++ struct inode *dir, struct path *path, ++ struct inode **delegated_inode, unsigned int flags) ++{ ++ int err; ++ struct path tmp = { ++ .mnt = path->mnt ++ }; ++ struct dentry *d; ++ ++ IMustLock(dir); ++ IMustLock(src_dir); ++ ++ d = path->dentry; ++ path->dentry = d->d_parent; ++ tmp.dentry = src_dentry->d_parent; ++ err = security_path_rename(&tmp, src_dentry, path, d, /*flags*/0); ++ path->dentry = d; ++ if (unlikely(err)) ++ goto out; ++ ++ lockdep_off(); ++ err = vfs_rename(src_dir, src_dentry, dir, path->dentry, ++ delegated_inode, flags); ++ lockdep_on(); ++ if (!err) { ++ int did; ++ ++ tmp.dentry = d->d_parent; ++ vfsub_update_h_iattr(&tmp, &did); ++ if (did) { ++ tmp.dentry = src_dentry; ++ vfsub_update_h_iattr(&tmp, /*did*/NULL); ++ tmp.dentry = src_dentry->d_parent; ++ vfsub_update_h_iattr(&tmp, /*did*/NULL); ++ } ++ /*ignore*/ ++ } ++ ++out: ++ return err; ++} ++ ++int vfsub_mkdir(struct inode *dir, struct path *path, int mode) ++{ ++ int err; ++ struct dentry *d; ++ ++ IMustLock(dir); ++ ++ d = path->dentry; ++ path->dentry = d->d_parent; ++ err = security_path_mkdir(path, d, mode); ++ path->dentry = d; ++ if (unlikely(err)) ++ goto out; ++ ++ lockdep_off(); ++ err = vfs_mkdir(dir, path->dentry, mode); ++ lockdep_on(); ++ if (!err) { ++ struct path tmp = *path; ++ int did; ++ ++ vfsub_update_h_iattr(&tmp, &did); ++ if (did) { ++ tmp.dentry = path->dentry->d_parent; ++ vfsub_update_h_iattr(&tmp, /*did*/NULL); ++ } ++ /*ignore*/ ++ } ++ ++out: ++ return err; ++} ++ ++int vfsub_rmdir(struct inode *dir, struct path *path) ++{ ++ int err; ++ struct dentry *d; ++ ++ IMustLock(dir); ++ ++ d = path->dentry; ++ path->dentry = d->d_parent; ++ err = security_path_rmdir(path, d); ++ path->dentry = d; ++ if (unlikely(err)) ++ goto out; ++ ++ lockdep_off(); ++ err = vfs_rmdir(dir, path->dentry); ++ lockdep_on(); ++ if (!err) { ++ struct path tmp = { ++ .dentry = path->dentry->d_parent, ++ .mnt = path->mnt ++ }; ++ ++ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/ ++ } ++ ++out: ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* todo: support mmap_sem? */ ++ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count, ++ loff_t *ppos) ++{ ++ ssize_t err; ++ ++ lockdep_off(); ++ err = vfs_read(file, ubuf, count, ppos); ++ lockdep_on(); ++ if (err >= 0) ++ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/ ++ return err; ++} ++ ++/* todo: kernel_read()? */ ++ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count, ++ loff_t *ppos) ++{ ++ ssize_t err; ++ mm_segment_t oldfs; ++ union { ++ void *k; ++ char __user *u; ++ } buf; ++ ++ buf.k = kbuf; ++ oldfs = get_fs(); ++ set_fs(KERNEL_DS); ++ err = vfsub_read_u(file, buf.u, count, ppos); ++ set_fs(oldfs); ++ return err; ++} ++ ++ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count, ++ loff_t *ppos) ++{ ++ ssize_t err; ++ ++ lockdep_off(); ++ err = vfs_write(file, ubuf, count, ppos); ++ lockdep_on(); ++ if (err >= 0) ++ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/ ++ return err; ++} ++ ++ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos) ++{ ++ ssize_t err; ++ mm_segment_t oldfs; ++ union { ++ void *k; ++ const char __user *u; ++ } buf; ++ ++ buf.k = kbuf; ++ oldfs = get_fs(); ++ set_fs(KERNEL_DS); ++ err = vfsub_write_u(file, buf.u, count, ppos); ++ set_fs(oldfs); ++ return err; ++} ++ ++int vfsub_flush(struct file *file, fl_owner_t id) ++{ ++ int err; ++ ++ err = 0; ++ if (file->f_op->flush) { ++ if (!au_test_nfs(file->f_path.dentry->d_sb)) ++ err = file->f_op->flush(file, id); ++ else { ++ lockdep_off(); ++ err = file->f_op->flush(file, id); ++ lockdep_on(); ++ } ++ if (!err) ++ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); ++ /*ignore*/ ++ } ++ return err; ++} ++ ++int vfsub_iterate_dir(struct file *file, struct dir_context *ctx) ++{ ++ int err; ++ ++ AuDbg("%pD, ctx{%ps, %llu}\n", file, ctx->actor, ctx->pos); ++ ++ lockdep_off(); ++ err = iterate_dir(file, ctx); ++ lockdep_on(); ++ if (err >= 0) ++ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/ ++ ++ return err; ++} ++ ++long vfsub_splice_to(struct file *in, loff_t *ppos, ++ struct pipe_inode_info *pipe, size_t len, ++ unsigned int flags) ++{ ++ long err; ++ ++ lockdep_off(); ++ err = do_splice_to(in, ppos, pipe, len, flags); ++ lockdep_on(); ++ file_accessed(in); ++ if (err >= 0) ++ vfsub_update_h_iattr(&in->f_path, /*did*/NULL); /*ignore*/ ++ return err; ++} ++ ++long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out, ++ loff_t *ppos, size_t len, unsigned int flags) ++{ ++ long err; ++ ++ lockdep_off(); ++ err = do_splice_from(pipe, out, ppos, len, flags); ++ lockdep_on(); ++ if (err >= 0) ++ vfsub_update_h_iattr(&out->f_path, /*did*/NULL); /*ignore*/ ++ return err; ++} ++ ++int vfsub_fsync(struct file *file, struct path *path, int datasync) ++{ ++ int err; ++ ++ /* file can be NULL */ ++ lockdep_off(); ++ err = vfs_fsync(file, datasync); ++ lockdep_on(); ++ if (!err) { ++ if (!path) { ++ AuDebugOn(!file); ++ path = &file->f_path; ++ } ++ vfsub_update_h_iattr(path, /*did*/NULL); /*ignore*/ ++ } ++ return err; ++} ++ ++/* cf. open.c:do_sys_truncate() and do_sys_ftruncate() */ ++int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr, ++ struct file *h_file) ++{ ++ int err; ++ struct inode *h_inode; ++ struct super_block *h_sb; ++ ++ if (!h_file) { ++ err = vfsub_truncate(h_path, length); ++ goto out; ++ } ++ ++ h_inode = d_inode(h_path->dentry); ++ h_sb = h_inode->i_sb; ++ lockdep_off(); ++ sb_start_write(h_sb); ++ lockdep_on(); ++ err = locks_verify_truncate(h_inode, h_file, length); ++ if (!err) ++ err = security_path_truncate(h_path); ++ if (!err) { ++ lockdep_off(); ++ err = do_truncate(h_path->dentry, length, attr, h_file); ++ lockdep_on(); ++ } ++ lockdep_off(); ++ sb_end_write(h_sb); ++ lockdep_on(); ++ ++out: ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++struct au_vfsub_mkdir_args { ++ int *errp; ++ struct inode *dir; ++ struct path *path; ++ int mode; ++}; ++ ++static void au_call_vfsub_mkdir(void *args) ++{ ++ struct au_vfsub_mkdir_args *a = args; ++ *a->errp = vfsub_mkdir(a->dir, a->path, a->mode); ++} ++ ++int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode) ++{ ++ int err, do_sio, wkq_err; ++ ++ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE); ++ if (!do_sio) { ++ lockdep_off(); ++ err = vfsub_mkdir(dir, path, mode); ++ lockdep_on(); ++ } else { ++ struct au_vfsub_mkdir_args args = { ++ .errp = &err, ++ .dir = dir, ++ .path = path, ++ .mode = mode ++ }; ++ wkq_err = au_wkq_wait(au_call_vfsub_mkdir, &args); ++ if (unlikely(wkq_err)) ++ err = wkq_err; ++ } ++ ++ return err; ++} ++ ++struct au_vfsub_rmdir_args { ++ int *errp; ++ struct inode *dir; ++ struct path *path; ++}; ++ ++static void au_call_vfsub_rmdir(void *args) ++{ ++ struct au_vfsub_rmdir_args *a = args; ++ *a->errp = vfsub_rmdir(a->dir, a->path); ++} ++ ++int vfsub_sio_rmdir(struct inode *dir, struct path *path) ++{ ++ int err, do_sio, wkq_err; ++ ++ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE); ++ if (!do_sio) { ++ lockdep_off(); ++ err = vfsub_rmdir(dir, path); ++ lockdep_on(); ++ } else { ++ struct au_vfsub_rmdir_args args = { ++ .errp = &err, ++ .dir = dir, ++ .path = path ++ }; ++ wkq_err = au_wkq_wait(au_call_vfsub_rmdir, &args); ++ if (unlikely(wkq_err)) ++ err = wkq_err; ++ } ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++struct notify_change_args { ++ int *errp; ++ struct path *path; ++ struct iattr *ia; ++ struct inode **delegated_inode; ++}; ++ ++static void call_notify_change(void *args) ++{ ++ struct notify_change_args *a = args; ++ struct inode *h_inode; ++ ++ h_inode = d_inode(a->path->dentry); ++ IMustLock(h_inode); ++ ++ *a->errp = -EPERM; ++ if (!IS_IMMUTABLE(h_inode) && !IS_APPEND(h_inode)) { ++ lockdep_off(); ++ *a->errp = notify_change(a->path->dentry, a->ia, ++ a->delegated_inode); ++ lockdep_on(); ++ if (!*a->errp) ++ vfsub_update_h_iattr(a->path, /*did*/NULL); /*ignore*/ ++ } ++ AuTraceErr(*a->errp); ++} ++ ++int vfsub_notify_change(struct path *path, struct iattr *ia, ++ struct inode **delegated_inode) ++{ ++ int err; ++ struct notify_change_args args = { ++ .errp = &err, ++ .path = path, ++ .ia = ia, ++ .delegated_inode = delegated_inode ++ }; ++ ++ call_notify_change(&args); ++ ++ return err; ++} ++ ++int vfsub_sio_notify_change(struct path *path, struct iattr *ia, ++ struct inode **delegated_inode) ++{ ++ int err, wkq_err; ++ struct notify_change_args args = { ++ .errp = &err, ++ .path = path, ++ .ia = ia, ++ .delegated_inode = delegated_inode ++ }; ++ ++ wkq_err = au_wkq_wait(call_notify_change, &args); ++ if (unlikely(wkq_err)) ++ err = wkq_err; ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++struct unlink_args { ++ int *errp; ++ struct inode *dir; ++ struct path *path; ++ struct inode **delegated_inode; ++}; ++ ++static void call_unlink(void *args) ++{ ++ struct unlink_args *a = args; ++ struct dentry *d = a->path->dentry; ++ struct inode *h_inode; ++ const int stop_sillyrename = (au_test_nfs(d->d_sb) ++ && au_dcount(d) == 1); ++ ++ IMustLock(a->dir); ++ ++ a->path->dentry = d->d_parent; ++ *a->errp = security_path_unlink(a->path, d); ++ a->path->dentry = d; ++ if (unlikely(*a->errp)) ++ return; ++ ++ if (!stop_sillyrename) ++ dget(d); ++ h_inode = NULL; ++ if (d_is_positive(d)) { ++ h_inode = d_inode(d); ++ ihold(h_inode); ++ } ++ ++ lockdep_off(); ++ *a->errp = vfs_unlink(a->dir, d, a->delegated_inode); ++ lockdep_on(); ++ if (!*a->errp) { ++ struct path tmp = { ++ .dentry = d->d_parent, ++ .mnt = a->path->mnt ++ }; ++ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/ ++ } ++ ++ if (!stop_sillyrename) ++ dput(d); ++ if (h_inode) ++ iput(h_inode); ++ ++ AuTraceErr(*a->errp); ++} ++ ++/* ++ * @dir: must be locked. ++ * @dentry: target dentry. ++ */ ++int vfsub_unlink(struct inode *dir, struct path *path, ++ struct inode **delegated_inode, int force) ++{ ++ int err; ++ struct unlink_args args = { ++ .errp = &err, ++ .dir = dir, ++ .path = path, ++ .delegated_inode = delegated_inode ++ }; ++ ++ if (!force) ++ call_unlink(&args); ++ else { ++ int wkq_err; ++ ++ wkq_err = au_wkq_wait(call_unlink, &args); ++ if (unlikely(wkq_err)) ++ err = wkq_err; ++ } ++ ++ return err; ++} +diff -Nurp linux-5.4/fs/aufs/vfsub.h linux-5.4-aufs/fs/aufs/vfsub.h +--- linux-5.4/fs/aufs/vfsub.h 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/vfsub.h 2019-11-28 01:25:59.068925618 +0200 +@@ -0,0 +1,341 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * sub-routines for VFS ++ */ ++ ++#ifndef __AUFS_VFSUB_H__ ++#define __AUFS_VFSUB_H__ ++ ++#ifdef __KERNEL__ ++ ++#include ++#include ++#include ++#include ++#include "debug.h" ++ ++/* copied from linux/fs/internal.h */ ++/* todo: BAD approach!! */ ++extern void __mnt_drop_write(struct vfsmount *); ++extern struct file *alloc_empty_file(int, const struct cred *); ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* lock subclass for lower inode */ ++/* default MAX_LOCKDEP_SUBCLASSES(8) is not enough */ ++/* reduce? gave up. */ ++enum { ++ AuLsc_I_Begin = I_MUTEX_PARENT2, /* 5 */ ++ AuLsc_I_PARENT, /* lower inode, parent first */ ++ AuLsc_I_PARENT2, /* copyup dirs */ ++ AuLsc_I_PARENT3, /* copyup wh */ ++ AuLsc_I_CHILD, ++ AuLsc_I_CHILD2, ++ AuLsc_I_End ++}; ++ ++/* to debug easier, do not make them inlined functions */ ++#define MtxMustLock(mtx) AuDebugOn(!mutex_is_locked(mtx)) ++#define IMustLock(i) AuDebugOn(!inode_is_locked(i)) ++ ++/* ---------------------------------------------------------------------- */ ++ ++static inline void vfsub_drop_nlink(struct inode *inode) ++{ ++ AuDebugOn(!inode->i_nlink); ++ drop_nlink(inode); ++} ++ ++static inline void vfsub_dead_dir(struct inode *inode) ++{ ++ AuDebugOn(!S_ISDIR(inode->i_mode)); ++ inode->i_flags |= S_DEAD; ++ clear_nlink(inode); ++} ++ ++static inline int vfsub_native_ro(struct inode *inode) ++{ ++ return sb_rdonly(inode->i_sb) ++ || IS_RDONLY(inode) ++ /* || IS_APPEND(inode) */ ++ || IS_IMMUTABLE(inode); ++} ++ ++#ifdef CONFIG_AUFS_BR_FUSE ++int vfsub_test_mntns(struct vfsmount *mnt, struct super_block *h_sb); ++#else ++AuStubInt0(vfsub_test_mntns, struct vfsmount *mnt, struct super_block *h_sb); ++#endif ++ ++int vfsub_sync_filesystem(struct super_block *h_sb, int wait); ++ ++/* ---------------------------------------------------------------------- */ ++ ++int vfsub_update_h_iattr(struct path *h_path, int *did); ++struct file *vfsub_dentry_open(struct path *path, int flags); ++struct file *vfsub_filp_open(const char *path, int oflags, int mode); ++struct au_branch; ++struct vfsub_aopen_args { ++ struct file *file; ++ unsigned int open_flag; ++ umode_t create_mode; ++ struct au_branch *br; ++}; ++int vfsub_atomic_open(struct inode *dir, struct dentry *dentry, ++ struct vfsub_aopen_args *args); ++int vfsub_kern_path(const char *name, unsigned int flags, struct path *path); ++ ++struct dentry *vfsub_lookup_one_len_unlocked(const char *name, ++ struct dentry *parent, int len); ++struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent, ++ int len); ++ ++struct vfsub_lkup_one_args { ++ struct dentry **errp; ++ struct qstr *name; ++ struct dentry *parent; ++}; ++ ++static inline struct dentry *vfsub_lkup_one(struct qstr *name, ++ struct dentry *parent) ++{ ++ return vfsub_lookup_one_len(name->name, parent, name->len); ++} ++ ++void vfsub_call_lkup_one(void *args); ++ ++/* ---------------------------------------------------------------------- */ ++ ++static inline int vfsub_mnt_want_write(struct vfsmount *mnt) ++{ ++ int err; ++ ++ lockdep_off(); ++ err = mnt_want_write(mnt); ++ lockdep_on(); ++ return err; ++} ++ ++static inline void vfsub_mnt_drop_write(struct vfsmount *mnt) ++{ ++ lockdep_off(); ++ mnt_drop_write(mnt); ++ lockdep_on(); ++} ++ ++#if 0 /* reserved */ ++static inline void vfsub_mnt_drop_write_file(struct file *file) ++{ ++ lockdep_off(); ++ mnt_drop_write_file(file); ++ lockdep_on(); ++} ++#endif ++ ++/* ---------------------------------------------------------------------- */ ++ ++struct au_hinode; ++struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1, ++ struct dentry *d2, struct au_hinode *hdir2); ++void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1, ++ struct dentry *d2, struct au_hinode *hdir2); ++ ++int vfsub_create(struct inode *dir, struct path *path, int mode, ++ bool want_excl); ++int vfsub_symlink(struct inode *dir, struct path *path, ++ const char *symname); ++int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev); ++int vfsub_link(struct dentry *src_dentry, struct inode *dir, ++ struct path *path, struct inode **delegated_inode); ++int vfsub_rename(struct inode *src_hdir, struct dentry *src_dentry, ++ struct inode *hdir, struct path *path, ++ struct inode **delegated_inode, unsigned int flags); ++int vfsub_mkdir(struct inode *dir, struct path *path, int mode); ++int vfsub_rmdir(struct inode *dir, struct path *path); ++ ++/* ---------------------------------------------------------------------- */ ++ ++ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count, ++ loff_t *ppos); ++ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count, ++ loff_t *ppos); ++ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count, ++ loff_t *ppos); ++ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, ++ loff_t *ppos); ++int vfsub_flush(struct file *file, fl_owner_t id); ++int vfsub_iterate_dir(struct file *file, struct dir_context *ctx); ++ ++static inline loff_t vfsub_f_size_read(struct file *file) ++{ ++ return i_size_read(file_inode(file)); ++} ++ ++static inline unsigned int vfsub_file_flags(struct file *file) ++{ ++ unsigned int flags; ++ ++ spin_lock(&file->f_lock); ++ flags = file->f_flags; ++ spin_unlock(&file->f_lock); ++ ++ return flags; ++} ++ ++static inline int vfsub_file_execed(struct file *file) ++{ ++ /* todo: direct access f_flags */ ++ return !!(vfsub_file_flags(file) & __FMODE_EXEC); ++} ++ ++#if 0 /* reserved */ ++static inline void vfsub_file_accessed(struct file *h_file) ++{ ++ file_accessed(h_file); ++ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL); /*ignore*/ ++} ++#endif ++ ++#if 0 /* reserved */ ++static inline void vfsub_touch_atime(struct vfsmount *h_mnt, ++ struct dentry *h_dentry) ++{ ++ struct path h_path = { ++ .dentry = h_dentry, ++ .mnt = h_mnt ++ }; ++ touch_atime(&h_path); ++ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/ ++} ++#endif ++ ++static inline int vfsub_update_time(struct inode *h_inode, ++ struct timespec64 *ts, int flags) ++{ ++ return update_time(h_inode, ts, flags); ++ /* no vfsub_update_h_iattr() since we don't have struct path */ ++} ++ ++#ifdef CONFIG_FS_POSIX_ACL ++static inline int vfsub_acl_chmod(struct inode *h_inode, umode_t h_mode) ++{ ++ int err; ++ ++ err = posix_acl_chmod(h_inode, h_mode); ++ if (err == -EOPNOTSUPP) ++ err = 0; ++ return err; ++} ++#else ++AuStubInt0(vfsub_acl_chmod, struct inode *h_inode, umode_t h_mode); ++#endif ++ ++long vfsub_splice_to(struct file *in, loff_t *ppos, ++ struct pipe_inode_info *pipe, size_t len, ++ unsigned int flags); ++long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out, ++ loff_t *ppos, size_t len, unsigned int flags); ++ ++static inline long vfsub_truncate(struct path *path, loff_t length) ++{ ++ long err; ++ ++ lockdep_off(); ++ err = vfs_truncate(path, length); ++ lockdep_on(); ++ return err; ++} ++ ++int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr, ++ struct file *h_file); ++int vfsub_fsync(struct file *file, struct path *path, int datasync); ++ ++/* ++ * re-use branch fs's ioctl(FICLONE) while aufs itself doesn't support such ++ * ioctl. ++ */ ++static inline loff_t vfsub_clone_file_range(struct file *src, struct file *dst, ++ loff_t len) ++{ ++ loff_t err; ++ ++ lockdep_off(); ++ err = vfs_clone_file_range(src, 0, dst, 0, len, /*remap_flags*/0); ++ lockdep_on(); ++ ++ return err; ++} ++ ++/* copy_file_range(2) is a systemcall */ ++static inline ssize_t vfsub_copy_file_range(struct file *src, loff_t src_pos, ++ struct file *dst, loff_t dst_pos, ++ size_t len, unsigned int flags) ++{ ++ ssize_t ssz; ++ ++ lockdep_off(); ++ ssz = vfs_copy_file_range(src, src_pos, dst, dst_pos, len, flags); ++ lockdep_on(); ++ ++ return ssz; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static inline loff_t vfsub_llseek(struct file *file, loff_t offset, int origin) ++{ ++ loff_t err; ++ ++ lockdep_off(); ++ err = vfs_llseek(file, offset, origin); ++ lockdep_on(); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode); ++int vfsub_sio_rmdir(struct inode *dir, struct path *path); ++int vfsub_sio_notify_change(struct path *path, struct iattr *ia, ++ struct inode **delegated_inode); ++int vfsub_notify_change(struct path *path, struct iattr *ia, ++ struct inode **delegated_inode); ++int vfsub_unlink(struct inode *dir, struct path *path, ++ struct inode **delegated_inode, int force); ++ ++static inline int vfsub_getattr(const struct path *path, struct kstat *st) ++{ ++ return vfs_getattr(path, st, STATX_BASIC_STATS, AT_STATX_SYNC_AS_STAT); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static inline int vfsub_setxattr(struct dentry *dentry, const char *name, ++ const void *value, size_t size, int flags) ++{ ++ int err; ++ ++ lockdep_off(); ++ err = vfs_setxattr(dentry, name, value, size, flags); ++ lockdep_on(); ++ ++ return err; ++} ++ ++static inline int vfsub_removexattr(struct dentry *dentry, const char *name) ++{ ++ int err; ++ ++ lockdep_off(); ++ err = vfs_removexattr(dentry, name); ++ lockdep_on(); ++ ++ return err; ++} ++ ++#endif /* __KERNEL__ */ ++#endif /* __AUFS_VFSUB_H__ */ +diff -Nurp linux-5.4/fs/aufs/whout.c linux-5.4-aufs/fs/aufs/whout.c +--- linux-5.4/fs/aufs/whout.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/whout.c 2019-11-28 01:25:59.069925618 +0200 +@@ -0,0 +1,1049 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * whiteout for logical deletion and opaque directory ++ */ ++ ++#include "aufs.h" ++ ++#define WH_MASK 0444 ++ ++/* ++ * If a directory contains this file, then it is opaque. We start with the ++ * .wh. flag so that it is blocked by lookup. ++ */ ++static struct qstr diropq_name = QSTR_INIT(AUFS_WH_DIROPQ, ++ sizeof(AUFS_WH_DIROPQ) - 1); ++ ++/* ++ * generate whiteout name, which is NOT terminated by NULL. ++ * @name: original d_name.name ++ * @len: original d_name.len ++ * @wh: whiteout qstr ++ * returns zero when succeeds, otherwise error. ++ * succeeded value as wh->name should be freed by kfree(). ++ */ ++int au_wh_name_alloc(struct qstr *wh, const struct qstr *name) ++{ ++ char *p; ++ ++ if (unlikely(name->len > PATH_MAX - AUFS_WH_PFX_LEN)) ++ return -ENAMETOOLONG; ++ ++ wh->len = name->len + AUFS_WH_PFX_LEN; ++ p = kmalloc(wh->len, GFP_NOFS); ++ wh->name = p; ++ if (p) { ++ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN); ++ memcpy(p + AUFS_WH_PFX_LEN, name->name, name->len); ++ /* smp_mb(); */ ++ return 0; ++ } ++ return -ENOMEM; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * test if the @wh_name exists under @h_parent. ++ * @try_sio specifies the necessary of super-io. ++ */ ++int au_wh_test(struct dentry *h_parent, struct qstr *wh_name, int try_sio) ++{ ++ int err; ++ struct dentry *wh_dentry; ++ ++ if (!try_sio) ++ wh_dentry = vfsub_lkup_one(wh_name, h_parent); ++ else ++ wh_dentry = au_sio_lkup_one(wh_name, h_parent); ++ err = PTR_ERR(wh_dentry); ++ if (IS_ERR(wh_dentry)) { ++ if (err == -ENAMETOOLONG) ++ err = 0; ++ goto out; ++ } ++ ++ err = 0; ++ if (d_is_negative(wh_dentry)) ++ goto out_wh; /* success */ ++ ++ err = 1; ++ if (d_is_reg(wh_dentry)) ++ goto out_wh; /* success */ ++ ++ err = -EIO; ++ AuIOErr("%pd Invalid whiteout entry type 0%o.\n", ++ wh_dentry, d_inode(wh_dentry)->i_mode); ++ ++out_wh: ++ dput(wh_dentry); ++out: ++ return err; ++} ++ ++/* ++ * test if the @h_dentry sets opaque or not. ++ */ ++int au_diropq_test(struct dentry *h_dentry) ++{ ++ int err; ++ struct inode *h_dir; ++ ++ h_dir = d_inode(h_dentry); ++ err = au_wh_test(h_dentry, &diropq_name, ++ au_test_h_perm_sio(h_dir, MAY_EXEC)); ++ return err; ++} ++ ++/* ++ * returns a negative dentry whose name is unique and temporary. ++ */ ++struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br, ++ struct qstr *prefix) ++{ ++ struct dentry *dentry; ++ int i; ++ char defname[NAME_MAX - AUFS_MAX_NAMELEN + DNAME_INLINE_LEN + 1], ++ *name, *p; ++ /* strict atomic_t is unnecessary here */ ++ static unsigned short cnt; ++ struct qstr qs; ++ ++ BUILD_BUG_ON(sizeof(cnt) * 2 > AUFS_WH_TMP_LEN); ++ ++ name = defname; ++ qs.len = sizeof(defname) - DNAME_INLINE_LEN + prefix->len - 1; ++ if (unlikely(prefix->len > DNAME_INLINE_LEN)) { ++ dentry = ERR_PTR(-ENAMETOOLONG); ++ if (unlikely(qs.len > NAME_MAX)) ++ goto out; ++ dentry = ERR_PTR(-ENOMEM); ++ name = kmalloc(qs.len + 1, GFP_NOFS); ++ if (unlikely(!name)) ++ goto out; ++ } ++ ++ /* doubly whiteout-ed */ ++ memcpy(name, AUFS_WH_PFX AUFS_WH_PFX, AUFS_WH_PFX_LEN * 2); ++ p = name + AUFS_WH_PFX_LEN * 2; ++ memcpy(p, prefix->name, prefix->len); ++ p += prefix->len; ++ *p++ = '.'; ++ AuDebugOn(name + qs.len + 1 - p <= AUFS_WH_TMP_LEN); ++ ++ qs.name = name; ++ for (i = 0; i < 3; i++) { ++ sprintf(p, "%.*x", AUFS_WH_TMP_LEN, cnt++); ++ dentry = au_sio_lkup_one(&qs, h_parent); ++ if (IS_ERR(dentry) || d_is_negative(dentry)) ++ goto out_name; ++ dput(dentry); ++ } ++ /* pr_warn("could not get random name\n"); */ ++ dentry = ERR_PTR(-EEXIST); ++ AuDbg("%.*s\n", AuLNPair(&qs)); ++ BUG(); ++ ++out_name: ++ if (name != defname) ++ au_kfree_try_rcu(name); ++out: ++ AuTraceErrPtr(dentry); ++ return dentry; ++} ++ ++/* ++ * rename the @h_dentry on @br to the whiteouted temporary name. ++ */ ++int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br) ++{ ++ int err; ++ struct path h_path = { ++ .mnt = au_br_mnt(br) ++ }; ++ struct inode *h_dir, *delegated; ++ struct dentry *h_parent; ++ ++ h_parent = h_dentry->d_parent; /* dir inode is locked */ ++ h_dir = d_inode(h_parent); ++ IMustLock(h_dir); ++ ++ h_path.dentry = au_whtmp_lkup(h_parent, br, &h_dentry->d_name); ++ err = PTR_ERR(h_path.dentry); ++ if (IS_ERR(h_path.dentry)) ++ goto out; ++ ++ /* under the same dir, no need to lock_rename() */ ++ delegated = NULL; ++ err = vfsub_rename(h_dir, h_dentry, h_dir, &h_path, &delegated, ++ /*flags*/0); ++ AuTraceErr(err); ++ if (unlikely(err == -EWOULDBLOCK)) { ++ pr_warn("cannot retry for NFSv4 delegation" ++ " for an internal rename\n"); ++ iput(delegated); ++ } ++ dput(h_path.dentry); ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++/* ++ * functions for removing a whiteout ++ */ ++ ++static int do_unlink_wh(struct inode *h_dir, struct path *h_path) ++{ ++ int err, force; ++ struct inode *delegated; ++ ++ /* ++ * forces superio when the dir has a sticky bit. ++ * this may be a violation of unix fs semantics. ++ */ ++ force = (h_dir->i_mode & S_ISVTX) ++ && !uid_eq(current_fsuid(), d_inode(h_path->dentry)->i_uid); ++ delegated = NULL; ++ err = vfsub_unlink(h_dir, h_path, &delegated, force); ++ if (unlikely(err == -EWOULDBLOCK)) { ++ pr_warn("cannot retry for NFSv4 delegation" ++ " for an internal unlink\n"); ++ iput(delegated); ++ } ++ return err; ++} ++ ++int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path, ++ struct dentry *dentry) ++{ ++ int err; ++ ++ err = do_unlink_wh(h_dir, h_path); ++ if (!err && dentry) ++ au_set_dbwh(dentry, -1); ++ ++ return err; ++} ++ ++static int unlink_wh_name(struct dentry *h_parent, struct qstr *wh, ++ struct au_branch *br) ++{ ++ int err; ++ struct path h_path = { ++ .mnt = au_br_mnt(br) ++ }; ++ ++ err = 0; ++ h_path.dentry = vfsub_lkup_one(wh, h_parent); ++ if (IS_ERR(h_path.dentry)) ++ err = PTR_ERR(h_path.dentry); ++ else { ++ if (d_is_reg(h_path.dentry)) ++ err = do_unlink_wh(d_inode(h_parent), &h_path); ++ dput(h_path.dentry); ++ } ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++/* ++ * initialize/clean whiteout for a branch ++ */ ++ ++static void au_wh_clean(struct inode *h_dir, struct path *whpath, ++ const int isdir) ++{ ++ int err; ++ struct inode *delegated; ++ ++ if (d_is_negative(whpath->dentry)) ++ return; ++ ++ if (isdir) ++ err = vfsub_rmdir(h_dir, whpath); ++ else { ++ delegated = NULL; ++ err = vfsub_unlink(h_dir, whpath, &delegated, /*force*/0); ++ if (unlikely(err == -EWOULDBLOCK)) { ++ pr_warn("cannot retry for NFSv4 delegation" ++ " for an internal unlink\n"); ++ iput(delegated); ++ } ++ } ++ if (unlikely(err)) ++ pr_warn("failed removing %pd (%d), ignored.\n", ++ whpath->dentry, err); ++} ++ ++static int test_linkable(struct dentry *h_root) ++{ ++ struct inode *h_dir = d_inode(h_root); ++ ++ if (h_dir->i_op->link) ++ return 0; ++ ++ pr_err("%pd (%s) doesn't support link(2), use noplink and rw+nolwh\n", ++ h_root, au_sbtype(h_root->d_sb)); ++ return -ENOSYS; ++} ++ ++/* todo: should this mkdir be done in /sbin/mount.aufs helper? */ ++static int au_whdir(struct inode *h_dir, struct path *path) ++{ ++ int err; ++ ++ err = -EEXIST; ++ if (d_is_negative(path->dentry)) { ++ int mode = 0700; ++ ++ if (au_test_nfs(path->dentry->d_sb)) ++ mode |= 0111; ++ err = vfsub_mkdir(h_dir, path, mode); ++ } else if (d_is_dir(path->dentry)) ++ err = 0; ++ else ++ pr_err("unknown %pd exists\n", path->dentry); ++ ++ return err; ++} ++ ++struct au_wh_base { ++ const struct qstr *name; ++ struct dentry *dentry; ++}; ++ ++static void au_wh_init_ro(struct inode *h_dir, struct au_wh_base base[], ++ struct path *h_path) ++{ ++ h_path->dentry = base[AuBrWh_BASE].dentry; ++ au_wh_clean(h_dir, h_path, /*isdir*/0); ++ h_path->dentry = base[AuBrWh_PLINK].dentry; ++ au_wh_clean(h_dir, h_path, /*isdir*/1); ++ h_path->dentry = base[AuBrWh_ORPH].dentry; ++ au_wh_clean(h_dir, h_path, /*isdir*/1); ++} ++ ++/* ++ * returns tri-state, ++ * minus: error, caller should print the message ++ * zero: success ++ * plus: error, caller should NOT print the message ++ */ ++static int au_wh_init_rw_nolink(struct dentry *h_root, struct au_wbr *wbr, ++ int do_plink, struct au_wh_base base[], ++ struct path *h_path) ++{ ++ int err; ++ struct inode *h_dir; ++ ++ h_dir = d_inode(h_root); ++ h_path->dentry = base[AuBrWh_BASE].dentry; ++ au_wh_clean(h_dir, h_path, /*isdir*/0); ++ h_path->dentry = base[AuBrWh_PLINK].dentry; ++ if (do_plink) { ++ err = test_linkable(h_root); ++ if (unlikely(err)) { ++ err = 1; ++ goto out; ++ } ++ ++ err = au_whdir(h_dir, h_path); ++ if (unlikely(err)) ++ goto out; ++ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry); ++ } else ++ au_wh_clean(h_dir, h_path, /*isdir*/1); ++ h_path->dentry = base[AuBrWh_ORPH].dentry; ++ err = au_whdir(h_dir, h_path); ++ if (unlikely(err)) ++ goto out; ++ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry); ++ ++out: ++ return err; ++} ++ ++/* ++ * for the moment, aufs supports the branch filesystem which does not support ++ * link(2). testing on FAT which does not support i_op->setattr() fully either, ++ * copyup failed. finally, such filesystem will not be used as the writable ++ * branch. ++ * ++ * returns tri-state, see above. ++ */ ++static int au_wh_init_rw(struct dentry *h_root, struct au_wbr *wbr, ++ int do_plink, struct au_wh_base base[], ++ struct path *h_path) ++{ ++ int err; ++ struct inode *h_dir; ++ ++ WbrWhMustWriteLock(wbr); ++ ++ err = test_linkable(h_root); ++ if (unlikely(err)) { ++ err = 1; ++ goto out; ++ } ++ ++ /* ++ * todo: should this create be done in /sbin/mount.aufs helper? ++ */ ++ err = -EEXIST; ++ h_dir = d_inode(h_root); ++ if (d_is_negative(base[AuBrWh_BASE].dentry)) { ++ h_path->dentry = base[AuBrWh_BASE].dentry; ++ err = vfsub_create(h_dir, h_path, WH_MASK, /*want_excl*/true); ++ } else if (d_is_reg(base[AuBrWh_BASE].dentry)) ++ err = 0; ++ else ++ pr_err("unknown %pd2 exists\n", base[AuBrWh_BASE].dentry); ++ if (unlikely(err)) ++ goto out; ++ ++ h_path->dentry = base[AuBrWh_PLINK].dentry; ++ if (do_plink) { ++ err = au_whdir(h_dir, h_path); ++ if (unlikely(err)) ++ goto out; ++ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry); ++ } else ++ au_wh_clean(h_dir, h_path, /*isdir*/1); ++ wbr->wbr_whbase = dget(base[AuBrWh_BASE].dentry); ++ ++ h_path->dentry = base[AuBrWh_ORPH].dentry; ++ err = au_whdir(h_dir, h_path); ++ if (unlikely(err)) ++ goto out; ++ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry); ++ ++out: ++ return err; ++} ++ ++/* ++ * initialize the whiteout base file/dir for @br. ++ */ ++int au_wh_init(struct au_branch *br, struct super_block *sb) ++{ ++ int err, i; ++ const unsigned char do_plink ++ = !!au_opt_test(au_mntflags(sb), PLINK); ++ struct inode *h_dir; ++ struct path path = br->br_path; ++ struct dentry *h_root = path.dentry; ++ struct au_wbr *wbr = br->br_wbr; ++ static const struct qstr base_name[] = { ++ [AuBrWh_BASE] = QSTR_INIT(AUFS_BASE_NAME, ++ sizeof(AUFS_BASE_NAME) - 1), ++ [AuBrWh_PLINK] = QSTR_INIT(AUFS_PLINKDIR_NAME, ++ sizeof(AUFS_PLINKDIR_NAME) - 1), ++ [AuBrWh_ORPH] = QSTR_INIT(AUFS_ORPHDIR_NAME, ++ sizeof(AUFS_ORPHDIR_NAME) - 1) ++ }; ++ struct au_wh_base base[] = { ++ [AuBrWh_BASE] = { ++ .name = base_name + AuBrWh_BASE, ++ .dentry = NULL ++ }, ++ [AuBrWh_PLINK] = { ++ .name = base_name + AuBrWh_PLINK, ++ .dentry = NULL ++ }, ++ [AuBrWh_ORPH] = { ++ .name = base_name + AuBrWh_ORPH, ++ .dentry = NULL ++ } ++ }; ++ ++ if (wbr) ++ WbrWhMustWriteLock(wbr); ++ ++ for (i = 0; i < AuBrWh_Last; i++) { ++ /* doubly whiteouted */ ++ struct dentry *d; ++ ++ d = au_wh_lkup(h_root, (void *)base[i].name, br); ++ err = PTR_ERR(d); ++ if (IS_ERR(d)) ++ goto out; ++ ++ base[i].dentry = d; ++ AuDebugOn(wbr ++ && wbr->wbr_wh[i] ++ && wbr->wbr_wh[i] != base[i].dentry); ++ } ++ ++ if (wbr) ++ for (i = 0; i < AuBrWh_Last; i++) { ++ dput(wbr->wbr_wh[i]); ++ wbr->wbr_wh[i] = NULL; ++ } ++ ++ err = 0; ++ if (!au_br_writable(br->br_perm)) { ++ h_dir = d_inode(h_root); ++ au_wh_init_ro(h_dir, base, &path); ++ } else if (!au_br_wh_linkable(br->br_perm)) { ++ err = au_wh_init_rw_nolink(h_root, wbr, do_plink, base, &path); ++ if (err > 0) ++ goto out; ++ else if (err) ++ goto out_err; ++ } else { ++ err = au_wh_init_rw(h_root, wbr, do_plink, base, &path); ++ if (err > 0) ++ goto out; ++ else if (err) ++ goto out_err; ++ } ++ goto out; /* success */ ++ ++out_err: ++ pr_err("an error(%d) on the writable branch %pd(%s)\n", ++ err, h_root, au_sbtype(h_root->d_sb)); ++out: ++ for (i = 0; i < AuBrWh_Last; i++) ++ dput(base[i].dentry); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++/* ++ * whiteouts are all hard-linked usually. ++ * when its link count reaches a ceiling, we create a new whiteout base ++ * asynchronously. ++ */ ++ ++struct reinit_br_wh { ++ struct super_block *sb; ++ struct au_branch *br; ++}; ++ ++static void reinit_br_wh(void *arg) ++{ ++ int err; ++ aufs_bindex_t bindex; ++ struct path h_path; ++ struct reinit_br_wh *a = arg; ++ struct au_wbr *wbr; ++ struct inode *dir, *delegated; ++ struct dentry *h_root; ++ struct au_hinode *hdir; ++ ++ err = 0; ++ wbr = a->br->br_wbr; ++ /* big aufs lock */ ++ si_noflush_write_lock(a->sb); ++ if (!au_br_writable(a->br->br_perm)) ++ goto out; ++ bindex = au_br_index(a->sb, a->br->br_id); ++ if (unlikely(bindex < 0)) ++ goto out; ++ ++ di_read_lock_parent(a->sb->s_root, AuLock_IR); ++ dir = d_inode(a->sb->s_root); ++ hdir = au_hi(dir, bindex); ++ h_root = au_h_dptr(a->sb->s_root, bindex); ++ AuDebugOn(h_root != au_br_dentry(a->br)); ++ ++ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT); ++ wbr_wh_write_lock(wbr); ++ err = au_h_verify(wbr->wbr_whbase, au_opt_udba(a->sb), hdir->hi_inode, ++ h_root, a->br); ++ if (!err) { ++ h_path.dentry = wbr->wbr_whbase; ++ h_path.mnt = au_br_mnt(a->br); ++ delegated = NULL; ++ err = vfsub_unlink(hdir->hi_inode, &h_path, &delegated, ++ /*force*/0); ++ if (unlikely(err == -EWOULDBLOCK)) { ++ pr_warn("cannot retry for NFSv4 delegation" ++ " for an internal unlink\n"); ++ iput(delegated); ++ } ++ } else { ++ pr_warn("%pd is moved, ignored\n", wbr->wbr_whbase); ++ err = 0; ++ } ++ dput(wbr->wbr_whbase); ++ wbr->wbr_whbase = NULL; ++ if (!err) ++ err = au_wh_init(a->br, a->sb); ++ wbr_wh_write_unlock(wbr); ++ au_hn_inode_unlock(hdir); ++ di_read_unlock(a->sb->s_root, AuLock_IR); ++ if (!err) ++ au_fhsm_wrote(a->sb, bindex, /*force*/0); ++ ++out: ++ if (wbr) ++ atomic_dec(&wbr->wbr_wh_running); ++ au_lcnt_dec(&a->br->br_count); ++ si_write_unlock(a->sb); ++ au_nwt_done(&au_sbi(a->sb)->si_nowait); ++ au_kfree_rcu(a); ++ if (unlikely(err)) ++ AuIOErr("err %d\n", err); ++} ++ ++static void kick_reinit_br_wh(struct super_block *sb, struct au_branch *br) ++{ ++ int do_dec, wkq_err; ++ struct reinit_br_wh *arg; ++ ++ do_dec = 1; ++ if (atomic_inc_return(&br->br_wbr->wbr_wh_running) != 1) ++ goto out; ++ ++ /* ignore ENOMEM */ ++ arg = kmalloc(sizeof(*arg), GFP_NOFS); ++ if (arg) { ++ /* ++ * dec(wh_running), kfree(arg) and dec(br_count) ++ * in reinit function ++ */ ++ arg->sb = sb; ++ arg->br = br; ++ au_lcnt_inc(&br->br_count); ++ wkq_err = au_wkq_nowait(reinit_br_wh, arg, sb, /*flags*/0); ++ if (unlikely(wkq_err)) { ++ atomic_dec(&br->br_wbr->wbr_wh_running); ++ au_lcnt_dec(&br->br_count); ++ au_kfree_rcu(arg); ++ } ++ do_dec = 0; ++ } ++ ++out: ++ if (do_dec) ++ atomic_dec(&br->br_wbr->wbr_wh_running); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * create the whiteout @wh. ++ */ ++static int link_or_create_wh(struct super_block *sb, aufs_bindex_t bindex, ++ struct dentry *wh) ++{ ++ int err; ++ struct path h_path = { ++ .dentry = wh ++ }; ++ struct au_branch *br; ++ struct au_wbr *wbr; ++ struct dentry *h_parent; ++ struct inode *h_dir, *delegated; ++ ++ h_parent = wh->d_parent; /* dir inode is locked */ ++ h_dir = d_inode(h_parent); ++ IMustLock(h_dir); ++ ++ br = au_sbr(sb, bindex); ++ h_path.mnt = au_br_mnt(br); ++ wbr = br->br_wbr; ++ wbr_wh_read_lock(wbr); ++ if (wbr->wbr_whbase) { ++ delegated = NULL; ++ err = vfsub_link(wbr->wbr_whbase, h_dir, &h_path, &delegated); ++ if (unlikely(err == -EWOULDBLOCK)) { ++ pr_warn("cannot retry for NFSv4 delegation" ++ " for an internal link\n"); ++ iput(delegated); ++ } ++ if (!err || err != -EMLINK) ++ goto out; ++ ++ /* link count full. re-initialize br_whbase. */ ++ kick_reinit_br_wh(sb, br); ++ } ++ ++ /* return this error in this context */ ++ err = vfsub_create(h_dir, &h_path, WH_MASK, /*want_excl*/true); ++ if (!err) ++ au_fhsm_wrote(sb, bindex, /*force*/0); ++ ++out: ++ wbr_wh_read_unlock(wbr); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * create or remove the diropq. ++ */ ++static struct dentry *do_diropq(struct dentry *dentry, aufs_bindex_t bindex, ++ unsigned int flags) ++{ ++ struct dentry *opq_dentry, *h_dentry; ++ struct super_block *sb; ++ struct au_branch *br; ++ int err; ++ ++ sb = dentry->d_sb; ++ br = au_sbr(sb, bindex); ++ h_dentry = au_h_dptr(dentry, bindex); ++ opq_dentry = vfsub_lkup_one(&diropq_name, h_dentry); ++ if (IS_ERR(opq_dentry)) ++ goto out; ++ ++ if (au_ftest_diropq(flags, CREATE)) { ++ err = link_or_create_wh(sb, bindex, opq_dentry); ++ if (!err) { ++ au_set_dbdiropq(dentry, bindex); ++ goto out; /* success */ ++ } ++ } else { ++ struct path tmp = { ++ .dentry = opq_dentry, ++ .mnt = au_br_mnt(br) ++ }; ++ err = do_unlink_wh(au_h_iptr(d_inode(dentry), bindex), &tmp); ++ if (!err) ++ au_set_dbdiropq(dentry, -1); ++ } ++ dput(opq_dentry); ++ opq_dentry = ERR_PTR(err); ++ ++out: ++ return opq_dentry; ++} ++ ++struct do_diropq_args { ++ struct dentry **errp; ++ struct dentry *dentry; ++ aufs_bindex_t bindex; ++ unsigned int flags; ++}; ++ ++static void call_do_diropq(void *args) ++{ ++ struct do_diropq_args *a = args; ++ *a->errp = do_diropq(a->dentry, a->bindex, a->flags); ++} ++ ++struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex, ++ unsigned int flags) ++{ ++ struct dentry *diropq, *h_dentry; ++ ++ h_dentry = au_h_dptr(dentry, bindex); ++ if (!au_test_h_perm_sio(d_inode(h_dentry), MAY_EXEC | MAY_WRITE)) ++ diropq = do_diropq(dentry, bindex, flags); ++ else { ++ int wkq_err; ++ struct do_diropq_args args = { ++ .errp = &diropq, ++ .dentry = dentry, ++ .bindex = bindex, ++ .flags = flags ++ }; ++ ++ wkq_err = au_wkq_wait(call_do_diropq, &args); ++ if (unlikely(wkq_err)) ++ diropq = ERR_PTR(wkq_err); ++ } ++ ++ return diropq; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * lookup whiteout dentry. ++ * @h_parent: lower parent dentry which must exist and be locked ++ * @base_name: name of dentry which will be whiteouted ++ * returns dentry for whiteout. ++ */ ++struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name, ++ struct au_branch *br) ++{ ++ int err; ++ struct qstr wh_name; ++ struct dentry *wh_dentry; ++ ++ err = au_wh_name_alloc(&wh_name, base_name); ++ wh_dentry = ERR_PTR(err); ++ if (!err) { ++ wh_dentry = vfsub_lkup_one(&wh_name, h_parent); ++ au_kfree_try_rcu(wh_name.name); ++ } ++ return wh_dentry; ++} ++ ++/* ++ * link/create a whiteout for @dentry on @bindex. ++ */ ++struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex, ++ struct dentry *h_parent) ++{ ++ struct dentry *wh_dentry; ++ struct super_block *sb; ++ int err; ++ ++ sb = dentry->d_sb; ++ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, au_sbr(sb, bindex)); ++ if (!IS_ERR(wh_dentry) && d_is_negative(wh_dentry)) { ++ err = link_or_create_wh(sb, bindex, wh_dentry); ++ if (!err) { ++ au_set_dbwh(dentry, bindex); ++ au_fhsm_wrote(sb, bindex, /*force*/0); ++ } else { ++ dput(wh_dentry); ++ wh_dentry = ERR_PTR(err); ++ } ++ } ++ ++ return wh_dentry; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* Delete all whiteouts in this directory on branch bindex. */ ++static int del_wh_children(struct dentry *h_dentry, struct au_nhash *whlist, ++ aufs_bindex_t bindex, struct au_branch *br) ++{ ++ int err; ++ unsigned long ul, n; ++ struct qstr wh_name; ++ char *p; ++ struct hlist_head *head; ++ struct au_vdir_wh *pos; ++ struct au_vdir_destr *str; ++ ++ err = -ENOMEM; ++ p = (void *)__get_free_page(GFP_NOFS); ++ wh_name.name = p; ++ if (unlikely(!wh_name.name)) ++ goto out; ++ ++ err = 0; ++ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN); ++ p += AUFS_WH_PFX_LEN; ++ n = whlist->nh_num; ++ head = whlist->nh_head; ++ for (ul = 0; !err && ul < n; ul++, head++) { ++ hlist_for_each_entry(pos, head, wh_hash) { ++ if (pos->wh_bindex != bindex) ++ continue; ++ ++ str = &pos->wh_str; ++ if (str->len + AUFS_WH_PFX_LEN <= PATH_MAX) { ++ memcpy(p, str->name, str->len); ++ wh_name.len = AUFS_WH_PFX_LEN + str->len; ++ err = unlink_wh_name(h_dentry, &wh_name, br); ++ if (!err) ++ continue; ++ break; ++ } ++ AuIOErr("whiteout name too long %.*s\n", ++ str->len, str->name); ++ err = -EIO; ++ break; ++ } ++ } ++ free_page((unsigned long)wh_name.name); ++ ++out: ++ return err; ++} ++ ++struct del_wh_children_args { ++ int *errp; ++ struct dentry *h_dentry; ++ struct au_nhash *whlist; ++ aufs_bindex_t bindex; ++ struct au_branch *br; ++}; ++ ++static void call_del_wh_children(void *args) ++{ ++ struct del_wh_children_args *a = args; ++ *a->errp = del_wh_children(a->h_dentry, a->whlist, a->bindex, a->br); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp) ++{ ++ struct au_whtmp_rmdir *whtmp; ++ int err; ++ unsigned int rdhash; ++ ++ SiMustAnyLock(sb); ++ ++ whtmp = kzalloc(sizeof(*whtmp), gfp); ++ if (unlikely(!whtmp)) { ++ whtmp = ERR_PTR(-ENOMEM); ++ goto out; ++ } ++ ++ /* no estimation for dir size */ ++ rdhash = au_sbi(sb)->si_rdhash; ++ if (!rdhash) ++ rdhash = AUFS_RDHASH_DEF; ++ err = au_nhash_alloc(&whtmp->whlist, rdhash, gfp); ++ if (unlikely(err)) { ++ au_kfree_rcu(whtmp); ++ whtmp = ERR_PTR(err); ++ } ++ ++out: ++ return whtmp; ++} ++ ++void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp) ++{ ++ if (whtmp->br) ++ au_lcnt_dec(&whtmp->br->br_count); ++ dput(whtmp->wh_dentry); ++ iput(whtmp->dir); ++ au_nhash_wh_free(&whtmp->whlist); ++ au_kfree_rcu(whtmp); ++} ++ ++/* ++ * rmdir the whiteouted temporary named dir @h_dentry. ++ * @whlist: whiteouted children. ++ */ ++int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex, ++ struct dentry *wh_dentry, struct au_nhash *whlist) ++{ ++ int err; ++ unsigned int h_nlink; ++ struct path h_tmp; ++ struct inode *wh_inode, *h_dir; ++ struct au_branch *br; ++ ++ h_dir = d_inode(wh_dentry->d_parent); /* dir inode is locked */ ++ IMustLock(h_dir); ++ ++ br = au_sbr(dir->i_sb, bindex); ++ wh_inode = d_inode(wh_dentry); ++ inode_lock_nested(wh_inode, AuLsc_I_CHILD); ++ ++ /* ++ * someone else might change some whiteouts while we were sleeping. ++ * it means this whlist may have an obsoleted entry. ++ */ ++ if (!au_test_h_perm_sio(wh_inode, MAY_EXEC | MAY_WRITE)) ++ err = del_wh_children(wh_dentry, whlist, bindex, br); ++ else { ++ int wkq_err; ++ struct del_wh_children_args args = { ++ .errp = &err, ++ .h_dentry = wh_dentry, ++ .whlist = whlist, ++ .bindex = bindex, ++ .br = br ++ }; ++ ++ wkq_err = au_wkq_wait(call_del_wh_children, &args); ++ if (unlikely(wkq_err)) ++ err = wkq_err; ++ } ++ inode_unlock(wh_inode); ++ ++ if (!err) { ++ h_tmp.dentry = wh_dentry; ++ h_tmp.mnt = au_br_mnt(br); ++ h_nlink = h_dir->i_nlink; ++ err = vfsub_rmdir(h_dir, &h_tmp); ++ /* some fs doesn't change the parent nlink in some cases */ ++ h_nlink -= h_dir->i_nlink; ++ } ++ ++ if (!err) { ++ if (au_ibtop(dir) == bindex) { ++ /* todo: dir->i_mutex is necessary */ ++ au_cpup_attr_timesizes(dir); ++ if (h_nlink) ++ vfsub_drop_nlink(dir); ++ } ++ return 0; /* success */ ++ } ++ ++ pr_warn("failed removing %pd(%d), ignored\n", wh_dentry, err); ++ return err; ++} ++ ++static void call_rmdir_whtmp(void *args) ++{ ++ int err; ++ aufs_bindex_t bindex; ++ struct au_whtmp_rmdir *a = args; ++ struct super_block *sb; ++ struct dentry *h_parent; ++ struct inode *h_dir; ++ struct au_hinode *hdir; ++ ++ /* rmdir by nfsd may cause deadlock with this i_mutex */ ++ /* inode_lock(a->dir); */ ++ err = -EROFS; ++ sb = a->dir->i_sb; ++ si_read_lock(sb, !AuLock_FLUSH); ++ if (!au_br_writable(a->br->br_perm)) ++ goto out; ++ bindex = au_br_index(sb, a->br->br_id); ++ if (unlikely(bindex < 0)) ++ goto out; ++ ++ err = -EIO; ++ ii_write_lock_parent(a->dir); ++ h_parent = dget_parent(a->wh_dentry); ++ h_dir = d_inode(h_parent); ++ hdir = au_hi(a->dir, bindex); ++ err = vfsub_mnt_want_write(au_br_mnt(a->br)); ++ if (unlikely(err)) ++ goto out_mnt; ++ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT); ++ err = au_h_verify(a->wh_dentry, au_opt_udba(sb), h_dir, h_parent, ++ a->br); ++ if (!err) ++ err = au_whtmp_rmdir(a->dir, bindex, a->wh_dentry, &a->whlist); ++ au_hn_inode_unlock(hdir); ++ vfsub_mnt_drop_write(au_br_mnt(a->br)); ++ ++out_mnt: ++ dput(h_parent); ++ ii_write_unlock(a->dir); ++out: ++ /* inode_unlock(a->dir); */ ++ au_whtmp_rmdir_free(a); ++ si_read_unlock(sb); ++ au_nwt_done(&au_sbi(sb)->si_nowait); ++ if (unlikely(err)) ++ AuIOErr("err %d\n", err); ++} ++ ++void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex, ++ struct dentry *wh_dentry, struct au_whtmp_rmdir *args) ++{ ++ int wkq_err; ++ struct super_block *sb; ++ ++ IMustLock(dir); ++ ++ /* all post-process will be done in do_rmdir_whtmp(). */ ++ sb = dir->i_sb; ++ args->dir = au_igrab(dir); ++ args->br = au_sbr(sb, bindex); ++ au_lcnt_inc(&args->br->br_count); ++ args->wh_dentry = dget(wh_dentry); ++ wkq_err = au_wkq_nowait(call_rmdir_whtmp, args, sb, /*flags*/0); ++ if (unlikely(wkq_err)) { ++ pr_warn("rmdir error %pd (%d), ignored\n", wh_dentry, wkq_err); ++ au_whtmp_rmdir_free(args); ++ } ++} +diff -Nurp linux-5.4/fs/aufs/whout.h linux-5.4-aufs/fs/aufs/whout.h +--- linux-5.4/fs/aufs/whout.h 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/whout.h 2019-11-28 01:25:59.069925618 +0200 +@@ -0,0 +1,73 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * whiteout for logical deletion and opaque directory ++ */ ++ ++#ifndef __AUFS_WHOUT_H__ ++#define __AUFS_WHOUT_H__ ++ ++#ifdef __KERNEL__ ++ ++#include "dir.h" ++ ++/* whout.c */ ++int au_wh_name_alloc(struct qstr *wh, const struct qstr *name); ++int au_wh_test(struct dentry *h_parent, struct qstr *wh_name, int try_sio); ++int au_diropq_test(struct dentry *h_dentry); ++struct au_branch; ++struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br, ++ struct qstr *prefix); ++int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br); ++int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path, ++ struct dentry *dentry); ++int au_wh_init(struct au_branch *br, struct super_block *sb); ++ ++/* diropq flags */ ++#define AuDiropq_CREATE 1 ++#define au_ftest_diropq(flags, name) ((flags) & AuDiropq_##name) ++#define au_fset_diropq(flags, name) \ ++ do { (flags) |= AuDiropq_##name; } while (0) ++#define au_fclr_diropq(flags, name) \ ++ do { (flags) &= ~AuDiropq_##name; } while (0) ++ ++struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex, ++ unsigned int flags); ++struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name, ++ struct au_branch *br); ++struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex, ++ struct dentry *h_parent); ++ ++/* real rmdir for the whiteout-ed dir */ ++struct au_whtmp_rmdir { ++ struct inode *dir; ++ struct au_branch *br; ++ struct dentry *wh_dentry; ++ struct au_nhash whlist; ++}; ++ ++struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp); ++void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp); ++int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex, ++ struct dentry *wh_dentry, struct au_nhash *whlist); ++void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex, ++ struct dentry *wh_dentry, struct au_whtmp_rmdir *args); ++ ++/* ---------------------------------------------------------------------- */ ++ ++static inline struct dentry *au_diropq_create(struct dentry *dentry, ++ aufs_bindex_t bindex) ++{ ++ return au_diropq_sio(dentry, bindex, AuDiropq_CREATE); ++} ++ ++static inline int au_diropq_remove(struct dentry *dentry, aufs_bindex_t bindex) ++{ ++ return PTR_ERR(au_diropq_sio(dentry, bindex, !AuDiropq_CREATE)); ++} ++ ++#endif /* __KERNEL__ */ ++#endif /* __AUFS_WHOUT_H__ */ +diff -Nurp linux-5.4/fs/aufs/wkq.c linux-5.4-aufs/fs/aufs/wkq.c +--- linux-5.4/fs/aufs/wkq.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/wkq.c 2019-11-28 01:25:59.069925618 +0200 +@@ -0,0 +1,379 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * workqueue for asynchronous/super-io operations ++ * todo: try new credential scheme ++ */ ++ ++#include ++#include "aufs.h" ++ ++/* internal workqueue named AUFS_WKQ_NAME */ ++ ++static struct workqueue_struct *au_wkq; ++ ++struct au_wkinfo { ++ struct work_struct wk; ++ struct kobject *kobj; ++ ++ unsigned int flags; /* see wkq.h */ ++ ++ au_wkq_func_t func; ++ void *args; ++ ++#ifdef CONFIG_LOCKDEP ++ int dont_check; ++ struct held_lock **hlock; ++#endif ++ ++ struct completion *comp; ++}; ++ ++/* ---------------------------------------------------------------------- */ ++/* ++ * Aufs passes some operations to the workqueue such as the internal copyup. ++ * This scheme looks rather unnatural for LOCKDEP debugging feature, since the ++ * job run by workqueue depends upon the locks acquired in the other task. ++ * Delegating a small operation to the workqueue, aufs passes its lockdep ++ * information too. And the job in the workqueue restores the info in order to ++ * pretend as if it acquired those locks. This is just to make LOCKDEP work ++ * correctly and expectedly. ++ */ ++ ++#ifndef CONFIG_LOCKDEP ++AuStubInt0(au_wkq_lockdep_alloc, struct au_wkinfo *wkinfo); ++AuStubVoid(au_wkq_lockdep_free, struct au_wkinfo *wkinfo); ++AuStubVoid(au_wkq_lockdep_pre, struct au_wkinfo *wkinfo); ++AuStubVoid(au_wkq_lockdep_post, struct au_wkinfo *wkinfo); ++AuStubVoid(au_wkq_lockdep_init, struct au_wkinfo *wkinfo); ++#else ++static void au_wkq_lockdep_init(struct au_wkinfo *wkinfo) ++{ ++ wkinfo->hlock = NULL; ++ wkinfo->dont_check = 0; ++} ++ ++/* ++ * 1: matched ++ * 0: unmatched ++ */ ++static int au_wkq_lockdep_test(struct lock_class_key *key, const char *name) ++{ ++ static DEFINE_SPINLOCK(spin); ++ static struct { ++ char *name; ++ struct lock_class_key *key; ++ } a[] = { ++ { .name = "&sbinfo->si_rwsem" }, ++ { .name = "&finfo->fi_rwsem" }, ++ { .name = "&dinfo->di_rwsem" }, ++ { .name = "&iinfo->ii_rwsem" } ++ }; ++ static int set; ++ int i; ++ ++ /* lockless read from 'set.' see below */ ++ if (set == ARRAY_SIZE(a)) { ++ for (i = 0; i < ARRAY_SIZE(a); i++) ++ if (a[i].key == key) ++ goto match; ++ goto unmatch; ++ } ++ ++ spin_lock(&spin); ++ if (set) ++ for (i = 0; i < ARRAY_SIZE(a); i++) ++ if (a[i].key == key) { ++ spin_unlock(&spin); ++ goto match; ++ } ++ for (i = 0; i < ARRAY_SIZE(a); i++) { ++ if (a[i].key) { ++ if (unlikely(a[i].key == key)) { /* rare but possible */ ++ spin_unlock(&spin); ++ goto match; ++ } else ++ continue; ++ } ++ if (strstr(a[i].name, name)) { ++ /* ++ * the order of these three lines is important for the ++ * lockless read above. ++ */ ++ a[i].key = key; ++ spin_unlock(&spin); ++ set++; ++ /* AuDbg("%d, %s\n", set, name); */ ++ goto match; ++ } ++ } ++ spin_unlock(&spin); ++ goto unmatch; ++ ++match: ++ return 1; ++unmatch: ++ return 0; ++} ++ ++static int au_wkq_lockdep_alloc(struct au_wkinfo *wkinfo) ++{ ++ int err, n; ++ struct task_struct *curr; ++ struct held_lock **hl, *held_locks, *p; ++ ++ err = 0; ++ curr = current; ++ wkinfo->dont_check = lockdep_recursing(curr); ++ if (wkinfo->dont_check) ++ goto out; ++ n = curr->lockdep_depth; ++ if (!n) ++ goto out; ++ ++ err = -ENOMEM; ++ wkinfo->hlock = kmalloc_array(n + 1, sizeof(*wkinfo->hlock), GFP_NOFS); ++ if (unlikely(!wkinfo->hlock)) ++ goto out; ++ ++ err = 0; ++#if 0 ++ if (0 && au_debug_test()) /* left for debugging */ ++ lockdep_print_held_locks(curr); ++#endif ++ held_locks = curr->held_locks; ++ hl = wkinfo->hlock; ++ while (n--) { ++ p = held_locks++; ++ if (au_wkq_lockdep_test(p->instance->key, p->instance->name)) ++ *hl++ = p; ++ } ++ *hl = NULL; ++ ++out: ++ return err; ++} ++ ++static void au_wkq_lockdep_free(struct au_wkinfo *wkinfo) ++{ ++ au_kfree_try_rcu(wkinfo->hlock); ++} ++ ++static void au_wkq_lockdep_pre(struct au_wkinfo *wkinfo) ++{ ++ struct held_lock *p, **hl = wkinfo->hlock; ++ int subclass; ++ ++ if (wkinfo->dont_check) ++ lockdep_off(); ++ if (!hl) ++ return; ++ while ((p = *hl++)) { /* assignment */ ++ subclass = lockdep_hlock_class(p)->subclass; ++ /* AuDbg("%s, %d\n", p->instance->name, subclass); */ ++ if (p->read) ++ rwsem_acquire_read(p->instance, subclass, 0, ++ /*p->acquire_ip*/_RET_IP_); ++ else ++ rwsem_acquire(p->instance, subclass, 0, ++ /*p->acquire_ip*/_RET_IP_); ++ } ++} ++ ++static void au_wkq_lockdep_post(struct au_wkinfo *wkinfo) ++{ ++ struct held_lock *p, **hl = wkinfo->hlock; ++ ++ if (wkinfo->dont_check) ++ lockdep_on(); ++ if (!hl) ++ return; ++ while ((p = *hl++)) /* assignment */ ++ rwsem_release(p->instance, 0, /*p->acquire_ip*/_RET_IP_); ++} ++#endif ++ ++static void wkq_func(struct work_struct *wk) ++{ ++ struct au_wkinfo *wkinfo = container_of(wk, struct au_wkinfo, wk); ++ ++ AuDebugOn(!uid_eq(current_fsuid(), GLOBAL_ROOT_UID)); ++ AuDebugOn(rlimit(RLIMIT_FSIZE) != RLIM_INFINITY); ++ ++ au_wkq_lockdep_pre(wkinfo); ++ wkinfo->func(wkinfo->args); ++ au_wkq_lockdep_post(wkinfo); ++ if (au_ftest_wkq(wkinfo->flags, WAIT)) ++ complete(wkinfo->comp); ++ else { ++ kobject_put(wkinfo->kobj); ++ module_put(THIS_MODULE); /* todo: ?? */ ++ au_kfree_rcu(wkinfo); ++ } ++} ++ ++/* ++ * Since struct completion is large, try allocating it dynamically. ++ */ ++#if 1 /* defined(CONFIG_4KSTACKS) || defined(AuTest4KSTACKS) */ ++#define AuWkqCompDeclare(name) struct completion *comp = NULL ++ ++static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp) ++{ ++ *comp = kmalloc(sizeof(**comp), GFP_NOFS); ++ if (*comp) { ++ init_completion(*comp); ++ wkinfo->comp = *comp; ++ return 0; ++ } ++ return -ENOMEM; ++} ++ ++static void au_wkq_comp_free(struct completion *comp) ++{ ++ au_kfree_rcu(comp); ++} ++ ++#else ++ ++/* no braces */ ++#define AuWkqCompDeclare(name) \ ++ DECLARE_COMPLETION_ONSTACK(_ ## name); \ ++ struct completion *comp = &_ ## name ++ ++static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp) ++{ ++ wkinfo->comp = *comp; ++ return 0; ++} ++ ++static void au_wkq_comp_free(struct completion *comp __maybe_unused) ++{ ++ /* empty */ ++} ++#endif /* 4KSTACKS */ ++ ++static void au_wkq_run(struct au_wkinfo *wkinfo) ++{ ++ if (au_ftest_wkq(wkinfo->flags, NEST)) { ++ if (au_wkq_test()) { ++ AuWarn1("wkq from wkq, unless silly-rename on NFS," ++ " due to a dead dir by UDBA," ++ " or async xino write?\n"); ++ AuDebugOn(au_ftest_wkq(wkinfo->flags, WAIT)); ++ } ++ } else ++ au_dbg_verify_kthread(); ++ ++ if (au_ftest_wkq(wkinfo->flags, WAIT)) { ++ INIT_WORK_ONSTACK(&wkinfo->wk, wkq_func); ++ queue_work(au_wkq, &wkinfo->wk); ++ } else { ++ INIT_WORK(&wkinfo->wk, wkq_func); ++ schedule_work(&wkinfo->wk); ++ } ++} ++ ++/* ++ * Be careful. It is easy to make deadlock happen. ++ * processA: lock, wkq and wait ++ * processB: wkq and wait, lock in wkq ++ * --> deadlock ++ */ ++int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args) ++{ ++ int err; ++ AuWkqCompDeclare(comp); ++ struct au_wkinfo wkinfo = { ++ .flags = flags, ++ .func = func, ++ .args = args ++ }; ++ ++ err = au_wkq_comp_alloc(&wkinfo, &comp); ++ if (unlikely(err)) ++ goto out; ++ err = au_wkq_lockdep_alloc(&wkinfo); ++ if (unlikely(err)) ++ goto out_comp; ++ if (!err) { ++ au_wkq_run(&wkinfo); ++ /* no timeout, no interrupt */ ++ wait_for_completion(wkinfo.comp); ++ } ++ au_wkq_lockdep_free(&wkinfo); ++ ++out_comp: ++ au_wkq_comp_free(comp); ++out: ++ destroy_work_on_stack(&wkinfo.wk); ++ return err; ++} ++ ++/* ++ * Note: dget/dput() in func for aufs dentries are not supported. It will be a ++ * problem in a concurrent umounting. ++ */ ++int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb, ++ unsigned int flags) ++{ ++ int err; ++ struct au_wkinfo *wkinfo; ++ ++ atomic_inc(&au_sbi(sb)->si_nowait.nw_len); ++ ++ /* ++ * wkq_func() must free this wkinfo. ++ * it highly depends upon the implementation of workqueue. ++ */ ++ err = 0; ++ wkinfo = kmalloc(sizeof(*wkinfo), GFP_NOFS); ++ if (wkinfo) { ++ wkinfo->kobj = &au_sbi(sb)->si_kobj; ++ wkinfo->flags = flags & ~AuWkq_WAIT; ++ wkinfo->func = func; ++ wkinfo->args = args; ++ wkinfo->comp = NULL; ++ au_wkq_lockdep_init(wkinfo); ++ kobject_get(wkinfo->kobj); ++ __module_get(THIS_MODULE); /* todo: ?? */ ++ ++ au_wkq_run(wkinfo); ++ } else { ++ err = -ENOMEM; ++ au_nwt_done(&au_sbi(sb)->si_nowait); ++ } ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++void au_nwt_init(struct au_nowait_tasks *nwt) ++{ ++ atomic_set(&nwt->nw_len, 0); ++ /* smp_mb(); */ /* atomic_set */ ++ init_waitqueue_head(&nwt->nw_wq); ++} ++ ++void au_wkq_fin(void) ++{ ++ destroy_workqueue(au_wkq); ++} ++ ++int __init au_wkq_init(void) ++{ ++ int err; ++ ++ err = 0; ++ au_wkq = alloc_workqueue(AUFS_WKQ_NAME, 0, WQ_DFL_ACTIVE); ++ if (IS_ERR(au_wkq)) ++ err = PTR_ERR(au_wkq); ++ else if (!au_wkq) ++ err = -ENOMEM; ++ ++ return err; ++} +diff -Nurp linux-5.4/fs/aufs/wkq.h linux-5.4-aufs/fs/aufs/wkq.h +--- linux-5.4/fs/aufs/wkq.h 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/wkq.h 2019-11-28 01:25:59.069925618 +0200 +@@ -0,0 +1,76 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * workqueue for asynchronous/super-io operations ++ * todo: try new credentials management scheme ++ */ ++ ++#ifndef __AUFS_WKQ_H__ ++#define __AUFS_WKQ_H__ ++ ++#ifdef __KERNEL__ ++ ++#include ++ ++struct super_block; ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * in the next operation, wait for the 'nowait' tasks in system-wide workqueue ++ */ ++struct au_nowait_tasks { ++ atomic_t nw_len; ++ wait_queue_head_t nw_wq; ++}; ++ ++/* ---------------------------------------------------------------------- */ ++ ++typedef void (*au_wkq_func_t)(void *args); ++ ++/* wkq flags */ ++#define AuWkq_WAIT 1 ++#define AuWkq_NEST (1 << 1) ++#define au_ftest_wkq(flags, name) ((flags) & AuWkq_##name) ++#define au_fset_wkq(flags, name) \ ++ do { (flags) |= AuWkq_##name; } while (0) ++#define au_fclr_wkq(flags, name) \ ++ do { (flags) &= ~AuWkq_##name; } while (0) ++ ++/* wkq.c */ ++int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args); ++int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb, ++ unsigned int flags); ++void au_nwt_init(struct au_nowait_tasks *nwt); ++int __init au_wkq_init(void); ++void au_wkq_fin(void); ++ ++/* ---------------------------------------------------------------------- */ ++ ++static inline int au_wkq_test(void) ++{ ++ return current->flags & PF_WQ_WORKER; ++} ++ ++static inline int au_wkq_wait(au_wkq_func_t func, void *args) ++{ ++ return au_wkq_do_wait(AuWkq_WAIT, func, args); ++} ++ ++static inline void au_nwt_done(struct au_nowait_tasks *nwt) ++{ ++ if (atomic_dec_and_test(&nwt->nw_len)) ++ wake_up_all(&nwt->nw_wq); ++} ++ ++static inline int au_nwt_flush(struct au_nowait_tasks *nwt) ++{ ++ wait_event(nwt->nw_wq, !atomic_read(&nwt->nw_len)); ++ return 0; ++} ++ ++#endif /* __KERNEL__ */ ++#endif /* __AUFS_WKQ_H__ */ +diff -Nurp linux-5.4/fs/aufs/xattr.c linux-5.4-aufs/fs/aufs/xattr.c +--- linux-5.4/fs/aufs/xattr.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/xattr.c 2019-11-28 01:25:59.069925618 +0200 +@@ -0,0 +1,343 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2014-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * handling xattr functions ++ */ ++ ++#include ++#include ++#include ++#include "aufs.h" ++ ++static int au_xattr_ignore(int err, char *name, unsigned int ignore_flags) ++{ ++ if (!ignore_flags) ++ goto out; ++ switch (err) { ++ case -ENOMEM: ++ case -EDQUOT: ++ goto out; ++ } ++ ++ if ((ignore_flags & AuBrAttr_ICEX) == AuBrAttr_ICEX) { ++ err = 0; ++ goto out; ++ } ++ ++#define cmp(brattr, prefix) do { \ ++ if (!strncmp(name, XATTR_##prefix##_PREFIX, \ ++ XATTR_##prefix##_PREFIX_LEN)) { \ ++ if (ignore_flags & AuBrAttr_ICEX_##brattr) \ ++ err = 0; \ ++ goto out; \ ++ } \ ++ } while (0) ++ ++ cmp(SEC, SECURITY); ++ cmp(SYS, SYSTEM); ++ cmp(TR, TRUSTED); ++ cmp(USR, USER); ++#undef cmp ++ ++ if (ignore_flags & AuBrAttr_ICEX_OTH) ++ err = 0; ++ ++out: ++ return err; ++} ++ ++static const int au_xattr_out_of_list = AuBrAttr_ICEX_OTH << 1; ++ ++static int au_do_cpup_xattr(struct dentry *h_dst, struct dentry *h_src, ++ char *name, char **buf, unsigned int ignore_flags, ++ unsigned int verbose) ++{ ++ int err; ++ ssize_t ssz; ++ struct inode *h_idst; ++ ++ ssz = vfs_getxattr_alloc(h_src, name, buf, 0, GFP_NOFS); ++ err = ssz; ++ if (unlikely(err <= 0)) { ++ if (err == -ENODATA ++ || (err == -EOPNOTSUPP ++ && ((ignore_flags & au_xattr_out_of_list) ++ || (au_test_nfs_noacl(d_inode(h_src)) ++ && (!strcmp(name, XATTR_NAME_POSIX_ACL_ACCESS) ++ || !strcmp(name, ++ XATTR_NAME_POSIX_ACL_DEFAULT)))) ++ )) ++ err = 0; ++ if (err && (verbose || au_debug_test())) ++ pr_err("%s, err %d\n", name, err); ++ goto out; ++ } ++ ++ /* unlock it temporary */ ++ h_idst = d_inode(h_dst); ++ inode_unlock(h_idst); ++ err = vfsub_setxattr(h_dst, name, *buf, ssz, /*flags*/0); ++ inode_lock_nested(h_idst, AuLsc_I_CHILD2); ++ if (unlikely(err)) { ++ if (verbose || au_debug_test()) ++ pr_err("%s, err %d\n", name, err); ++ err = au_xattr_ignore(err, name, ignore_flags); ++ } ++ ++out: ++ return err; ++} ++ ++int au_cpup_xattr(struct dentry *h_dst, struct dentry *h_src, int ignore_flags, ++ unsigned int verbose) ++{ ++ int err, unlocked, acl_access, acl_default; ++ ssize_t ssz; ++ struct inode *h_isrc, *h_idst; ++ char *value, *p, *o, *e; ++ ++ /* try stopping to update the source inode while we are referencing */ ++ /* there should not be the parent-child relationship between them */ ++ h_isrc = d_inode(h_src); ++ h_idst = d_inode(h_dst); ++ inode_unlock(h_idst); ++ inode_lock_shared_nested(h_isrc, AuLsc_I_CHILD); ++ inode_lock_nested(h_idst, AuLsc_I_CHILD2); ++ unlocked = 0; ++ ++ /* some filesystems don't list POSIX ACL, for example tmpfs */ ++ ssz = vfs_listxattr(h_src, NULL, 0); ++ err = ssz; ++ if (unlikely(err < 0)) { ++ AuTraceErr(err); ++ if (err == -ENODATA ++ || err == -EOPNOTSUPP) ++ err = 0; /* ignore */ ++ goto out; ++ } ++ ++ err = 0; ++ p = NULL; ++ o = NULL; ++ if (ssz) { ++ err = -ENOMEM; ++ p = kmalloc(ssz, GFP_NOFS); ++ o = p; ++ if (unlikely(!p)) ++ goto out; ++ err = vfs_listxattr(h_src, p, ssz); ++ } ++ inode_unlock_shared(h_isrc); ++ unlocked = 1; ++ AuDbg("err %d, ssz %zd\n", err, ssz); ++ if (unlikely(err < 0)) ++ goto out_free; ++ ++ err = 0; ++ e = p + ssz; ++ value = NULL; ++ acl_access = 0; ++ acl_default = 0; ++ while (!err && p < e) { ++ acl_access |= !strncmp(p, XATTR_NAME_POSIX_ACL_ACCESS, ++ sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1); ++ acl_default |= !strncmp(p, XATTR_NAME_POSIX_ACL_DEFAULT, ++ sizeof(XATTR_NAME_POSIX_ACL_DEFAULT) ++ - 1); ++ err = au_do_cpup_xattr(h_dst, h_src, p, &value, ignore_flags, ++ verbose); ++ p += strlen(p) + 1; ++ } ++ AuTraceErr(err); ++ ignore_flags |= au_xattr_out_of_list; ++ if (!err && !acl_access) { ++ err = au_do_cpup_xattr(h_dst, h_src, ++ XATTR_NAME_POSIX_ACL_ACCESS, &value, ++ ignore_flags, verbose); ++ AuTraceErr(err); ++ } ++ if (!err && !acl_default) { ++ err = au_do_cpup_xattr(h_dst, h_src, ++ XATTR_NAME_POSIX_ACL_DEFAULT, &value, ++ ignore_flags, verbose); ++ AuTraceErr(err); ++ } ++ ++ au_kfree_try_rcu(value); ++ ++out_free: ++ au_kfree_try_rcu(o); ++out: ++ if (!unlocked) ++ inode_unlock_shared(h_isrc); ++ AuTraceErr(err); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int au_smack_reentering(struct super_block *sb) ++{ ++#if IS_ENABLED(CONFIG_SECURITY_SMACK) ++ /* ++ * as a part of lookup, smack_d_instantiate() is called, and it calls ++ * i_op->getxattr(). ouch. ++ */ ++ return si_pid_test(sb); ++#else ++ return 0; ++#endif ++} ++ ++enum { ++ AU_XATTR_LIST, ++ AU_XATTR_GET ++}; ++ ++struct au_lgxattr { ++ int type; ++ union { ++ struct { ++ char *list; ++ size_t size; ++ } list; ++ struct { ++ const char *name; ++ void *value; ++ size_t size; ++ } get; ++ } u; ++}; ++ ++static ssize_t au_lgxattr(struct dentry *dentry, struct au_lgxattr *arg) ++{ ++ ssize_t err; ++ int reenter; ++ struct path h_path; ++ struct super_block *sb; ++ ++ sb = dentry->d_sb; ++ reenter = au_smack_reentering(sb); ++ if (!reenter) { ++ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM); ++ if (unlikely(err)) ++ goto out; ++ } ++ err = au_h_path_getattr(dentry, /*force*/1, &h_path, reenter); ++ if (unlikely(err)) ++ goto out_si; ++ if (unlikely(!h_path.dentry)) ++ /* illegally overlapped or something */ ++ goto out_di; /* pretending success */ ++ ++ /* always topmost entry only */ ++ switch (arg->type) { ++ case AU_XATTR_LIST: ++ err = vfs_listxattr(h_path.dentry, ++ arg->u.list.list, arg->u.list.size); ++ break; ++ case AU_XATTR_GET: ++ AuDebugOn(d_is_negative(h_path.dentry)); ++ err = vfs_getxattr(h_path.dentry, ++ arg->u.get.name, arg->u.get.value, ++ arg->u.get.size); ++ break; ++ } ++ ++out_di: ++ if (!reenter) ++ di_read_unlock(dentry, AuLock_IR); ++out_si: ++ if (!reenter) ++ si_read_unlock(sb); ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++ssize_t aufs_listxattr(struct dentry *dentry, char *list, size_t size) ++{ ++ struct au_lgxattr arg = { ++ .type = AU_XATTR_LIST, ++ .u.list = { ++ .list = list, ++ .size = size ++ }, ++ }; ++ ++ return au_lgxattr(dentry, &arg); ++} ++ ++static ssize_t au_getxattr(struct dentry *dentry, ++ struct inode *inode __maybe_unused, ++ const char *name, void *value, size_t size) ++{ ++ struct au_lgxattr arg = { ++ .type = AU_XATTR_GET, ++ .u.get = { ++ .name = name, ++ .value = value, ++ .size = size ++ }, ++ }; ++ ++ return au_lgxattr(dentry, &arg); ++} ++ ++static int au_setxattr(struct dentry *dentry, struct inode *inode, ++ const char *name, const void *value, size_t size, ++ int flags) ++{ ++ struct au_sxattr arg = { ++ .type = AU_XATTR_SET, ++ .u.set = { ++ .name = name, ++ .value = value, ++ .size = size, ++ .flags = flags ++ }, ++ }; ++ ++ return au_sxattr(dentry, inode, &arg); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int au_xattr_get(const struct xattr_handler *handler, ++ struct dentry *dentry, struct inode *inode, ++ const char *name, void *buffer, size_t size) ++{ ++ return au_getxattr(dentry, inode, name, buffer, size); ++} ++ ++static int au_xattr_set(const struct xattr_handler *handler, ++ struct dentry *dentry, struct inode *inode, ++ const char *name, const void *value, size_t size, ++ int flags) ++{ ++ return au_setxattr(dentry, inode, name, value, size, flags); ++} ++ ++static const struct xattr_handler au_xattr_handler = { ++ .name = "", ++ .prefix = "", ++ .get = au_xattr_get, ++ .set = au_xattr_set ++}; ++ ++static const struct xattr_handler *au_xattr_handlers[] = { ++#ifdef CONFIG_FS_POSIX_ACL ++ &posix_acl_access_xattr_handler, ++ &posix_acl_default_xattr_handler, ++#endif ++ &au_xattr_handler, /* must be last */ ++ NULL ++}; ++ ++void au_xattr_init(struct super_block *sb) ++{ ++ sb->s_xattr = au_xattr_handlers; ++} +diff -Nurp linux-5.4/fs/aufs/xino.c linux-5.4-aufs/fs/aufs/xino.c +--- linux-5.4/fs/aufs/xino.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/fs/aufs/xino.c 2019-11-28 01:25:59.069925618 +0200 +@@ -0,0 +1,1952 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++/* ++ * external inode number translation table and bitmap ++ * ++ * things to consider ++ * - the lifetime ++ * + au_xino object ++ * + XINO files (xino, xib, xigen) ++ * + dynamic debugfs entries (xiN) ++ * + static debugfs entries (xib, xigen) ++ * + static sysfs entry (xi_path) ++ * - several entry points to handle them. ++ * + mount(2) without xino option (default) ++ * + mount(2) with xino option ++ * + mount(2) with noxino option ++ * + umount(2) ++ * + remount with add/del branches ++ * + remount with xino/noxino options ++ */ ++ ++#include ++#include ++#include "aufs.h" ++ ++static aufs_bindex_t sbr_find_shared(struct super_block *sb, aufs_bindex_t btop, ++ aufs_bindex_t bbot, ++ struct super_block *h_sb) ++{ ++ /* todo: try binary-search if the branches are many */ ++ for (; btop <= bbot; btop++) ++ if (h_sb == au_sbr_sb(sb, btop)) ++ return btop; ++ return -1; ++} ++ ++/* ++ * find another branch who is on the same filesystem of the specified ++ * branch{@btgt}. search until @bbot. ++ */ ++static aufs_bindex_t is_sb_shared(struct super_block *sb, aufs_bindex_t btgt, ++ aufs_bindex_t bbot) ++{ ++ aufs_bindex_t bindex; ++ struct super_block *tgt_sb; ++ ++ tgt_sb = au_sbr_sb(sb, btgt); ++ bindex = sbr_find_shared(sb, /*btop*/0, btgt - 1, tgt_sb); ++ if (bindex < 0) ++ bindex = sbr_find_shared(sb, btgt + 1, bbot, tgt_sb); ++ ++ return bindex; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * stop unnecessary notify events at creating xino files ++ */ ++ ++aufs_bindex_t au_xi_root(struct super_block *sb, struct dentry *dentry) ++{ ++ aufs_bindex_t bfound, bindex, bbot; ++ struct dentry *parent; ++ struct au_branch *br; ++ ++ bfound = -1; ++ parent = dentry->d_parent; /* safe d_parent access */ ++ bbot = au_sbbot(sb); ++ for (bindex = 0; bindex <= bbot; bindex++) { ++ br = au_sbr(sb, bindex); ++ if (au_br_dentry(br) == parent) { ++ bfound = bindex; ++ break; ++ } ++ } ++ ++ AuDbg("bfound b%d\n", bfound); ++ return bfound; ++} ++ ++struct au_xino_lock_dir { ++ struct au_hinode *hdir; ++ struct dentry *parent; ++ struct inode *dir; ++}; ++ ++static struct dentry *au_dget_parent_lock(struct dentry *dentry, ++ unsigned int lsc) ++{ ++ struct dentry *parent; ++ struct inode *dir; ++ ++ parent = dget_parent(dentry); ++ dir = d_inode(parent); ++ inode_lock_nested(dir, lsc); ++#if 0 /* it should not happen */ ++ spin_lock(&dentry->d_lock); ++ if (unlikely(dentry->d_parent != parent)) { ++ spin_unlock(&dentry->d_lock); ++ inode_unlock(dir); ++ dput(parent); ++ parent = NULL; ++ goto out; ++ } ++ spin_unlock(&dentry->d_lock); ++ ++out: ++#endif ++ return parent; ++} ++ ++static void au_xino_lock_dir(struct super_block *sb, struct path *xipath, ++ struct au_xino_lock_dir *ldir) ++{ ++ aufs_bindex_t bindex; ++ ++ ldir->hdir = NULL; ++ bindex = au_xi_root(sb, xipath->dentry); ++ if (bindex >= 0) { ++ /* rw branch root */ ++ ldir->hdir = au_hi(d_inode(sb->s_root), bindex); ++ au_hn_inode_lock_nested(ldir->hdir, AuLsc_I_PARENT); ++ } else { ++ /* other */ ++ ldir->parent = au_dget_parent_lock(xipath->dentry, ++ AuLsc_I_PARENT); ++ ldir->dir = d_inode(ldir->parent); ++ } ++} ++ ++static void au_xino_unlock_dir(struct au_xino_lock_dir *ldir) ++{ ++ if (ldir->hdir) ++ au_hn_inode_unlock(ldir->hdir); ++ else { ++ inode_unlock(ldir->dir); ++ dput(ldir->parent); ++ } ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * create and set a new xino file ++ */ ++struct file *au_xino_create(struct super_block *sb, char *fpath, int silent, ++ int wbrtop) ++{ ++ struct file *file; ++ struct dentry *h_parent, *d; ++ struct inode *h_dir, *inode; ++ int err; ++ static DEFINE_MUTEX(mtx); ++ ++ /* ++ * at mount-time, and the xino file is the default path, ++ * hnotify is disabled so we have no notify events to ignore. ++ * when a user specified the xino, we cannot get au_hdir to be ignored. ++ */ ++ if (!wbrtop) ++ mutex_lock(&mtx); ++ file = vfsub_filp_open(fpath, O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE ++ /* | __FMODE_NONOTIFY */, ++ 0666); ++ if (IS_ERR(file)) { ++ if (!wbrtop) ++ mutex_unlock(&mtx); ++ if (!silent) ++ pr_err("open %s(%ld)\n", fpath, PTR_ERR(file)); ++ return file; ++ } ++ ++ /* keep file count */ ++ err = 0; ++ d = file->f_path.dentry; ++ h_parent = au_dget_parent_lock(d, AuLsc_I_PARENT); ++ if (!wbrtop) ++ mutex_unlock(&mtx); ++ /* mnt_want_write() is unnecessary here */ ++ h_dir = d_inode(h_parent); ++ inode = file_inode(file); ++ /* no delegation since it is just created */ ++ if (inode->i_nlink) ++ err = vfsub_unlink(h_dir, &file->f_path, /*delegated*/NULL, ++ /*force*/0); ++ inode_unlock(h_dir); ++ dput(h_parent); ++ if (unlikely(err)) { ++ if (!silent) ++ pr_err("unlink %s(%d)\n", fpath, err); ++ goto out; ++ } ++ ++ err = -EINVAL; ++ if (unlikely(sb == d->d_sb)) { ++ if (!silent) ++ pr_err("%s must be outside\n", fpath); ++ goto out; ++ } ++ if (unlikely(au_test_fs_bad_xino(d->d_sb))) { ++ if (!silent) ++ pr_err("xino doesn't support %s(%s)\n", ++ fpath, au_sbtype(d->d_sb)); ++ goto out; ++ } ++ return file; /* success */ ++ ++out: ++ fput(file); ++ file = ERR_PTR(err); ++ return file; ++} ++ ++/* ++ * create a new xinofile at the same place/path as @base. ++ */ ++struct file *au_xino_create2(struct super_block *sb, struct path *base, ++ struct file *copy_src) ++{ ++ struct file *file; ++ struct dentry *dentry, *parent; ++ struct inode *dir, *delegated; ++ struct qstr *name; ++ struct path path; ++ int err, do_unlock; ++ struct au_xino_lock_dir ldir; ++ ++ do_unlock = 1; ++ au_xino_lock_dir(sb, base, &ldir); ++ dentry = base->dentry; ++ parent = dentry->d_parent; /* dir inode is locked */ ++ dir = d_inode(parent); ++ IMustLock(dir); ++ ++ name = &dentry->d_name; ++ path.dentry = vfsub_lookup_one_len(name->name, parent, name->len); ++ if (IS_ERR(path.dentry)) { ++ file = (void *)path.dentry; ++ pr_err("%pd lookup err %ld\n", dentry, PTR_ERR(path.dentry)); ++ goto out; ++ } ++ ++ /* no need to mnt_want_write() since we call dentry_open() later */ ++ err = vfs_create(dir, path.dentry, 0666, NULL); ++ if (unlikely(err)) { ++ file = ERR_PTR(err); ++ pr_err("%pd create err %d\n", dentry, err); ++ goto out_dput; ++ } ++ ++ path.mnt = base->mnt; ++ file = vfsub_dentry_open(&path, ++ O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE ++ /* | __FMODE_NONOTIFY */); ++ if (IS_ERR(file)) { ++ pr_err("%pd open err %ld\n", dentry, PTR_ERR(file)); ++ goto out_dput; ++ } ++ ++ delegated = NULL; ++ err = vfsub_unlink(dir, &file->f_path, &delegated, /*force*/0); ++ au_xino_unlock_dir(&ldir); ++ do_unlock = 0; ++ if (unlikely(err == -EWOULDBLOCK)) { ++ pr_warn("cannot retry for NFSv4 delegation" ++ " for an internal unlink\n"); ++ iput(delegated); ++ } ++ if (unlikely(err)) { ++ pr_err("%pd unlink err %d\n", dentry, err); ++ goto out_fput; ++ } ++ ++ if (copy_src) { ++ /* no one can touch copy_src xino */ ++ err = au_copy_file(file, copy_src, vfsub_f_size_read(copy_src)); ++ if (unlikely(err)) { ++ pr_err("%pd copy err %d\n", dentry, err); ++ goto out_fput; ++ } ++ } ++ goto out_dput; /* success */ ++ ++out_fput: ++ fput(file); ++ file = ERR_PTR(err); ++out_dput: ++ dput(path.dentry); ++out: ++ if (do_unlock) ++ au_xino_unlock_dir(&ldir); ++ return file; ++} ++ ++struct file *au_xino_file1(struct au_xino *xi) ++{ ++ struct file *file; ++ unsigned int u, nfile; ++ ++ file = NULL; ++ nfile = xi->xi_nfile; ++ for (u = 0; u < nfile; u++) { ++ file = xi->xi_file[u]; ++ if (file) ++ break; ++ } ++ ++ return file; ++} ++ ++static int au_xino_file_set(struct au_xino *xi, int idx, struct file *file) ++{ ++ int err; ++ struct file *f; ++ void *p; ++ ++ if (file) ++ get_file(file); ++ ++ err = 0; ++ f = NULL; ++ if (idx < xi->xi_nfile) { ++ f = xi->xi_file[idx]; ++ if (f) ++ fput(f); ++ } else { ++ p = au_kzrealloc(xi->xi_file, ++ sizeof(*xi->xi_file) * xi->xi_nfile, ++ sizeof(*xi->xi_file) * (idx + 1), ++ GFP_NOFS, /*may_shrink*/0); ++ if (p) { ++ MtxMustLock(&xi->xi_mtx); ++ xi->xi_file = p; ++ xi->xi_nfile = idx + 1; ++ } else { ++ err = -ENOMEM; ++ if (file) ++ fput(file); ++ goto out; ++ } ++ } ++ xi->xi_file[idx] = file; ++ ++out: ++ return err; ++} ++ ++/* ++ * if @xinew->xi is not set, then create new xigen file. ++ */ ++struct file *au_xi_new(struct super_block *sb, struct au_xi_new *xinew) ++{ ++ struct file *file; ++ int err; ++ ++ SiMustAnyLock(sb); ++ ++ file = au_xino_create2(sb, xinew->base, xinew->copy_src); ++ if (IS_ERR(file)) { ++ err = PTR_ERR(file); ++ pr_err("%s[%d], err %d\n", ++ xinew->xi ? "xino" : "xigen", ++ xinew->idx, err); ++ goto out; ++ } ++ ++ if (xinew->xi) ++ err = au_xino_file_set(xinew->xi, xinew->idx, file); ++ else { ++ BUG(); ++ /* todo: make xigen file an array */ ++ /* err = au_xigen_file_set(sb, xinew->idx, file); */ ++ } ++ fput(file); ++ if (unlikely(err)) ++ file = ERR_PTR(err); ++ ++out: ++ return file; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * truncate xino files ++ */ ++static int au_xino_do_trunc(struct super_block *sb, aufs_bindex_t bindex, ++ int idx, struct kstatfs *st) ++{ ++ int err; ++ blkcnt_t blocks; ++ struct file *file, *new_xino; ++ struct au_xi_new xinew = { ++ .idx = idx ++ }; ++ ++ err = 0; ++ xinew.xi = au_sbr(sb, bindex)->br_xino; ++ file = au_xino_file(xinew.xi, idx); ++ if (!file) ++ goto out; ++ ++ xinew.base = &file->f_path; ++ err = vfs_statfs(xinew.base, st); ++ if (unlikely(err)) { ++ AuErr1("statfs err %d, ignored\n", err); ++ err = 0; ++ goto out; ++ } ++ ++ blocks = file_inode(file)->i_blocks; ++ pr_info("begin truncating xino(b%d-%d), ib%llu, %llu/%llu free blks\n", ++ bindex, idx, (u64)blocks, st->f_bfree, st->f_blocks); ++ ++ xinew.copy_src = file; ++ new_xino = au_xi_new(sb, &xinew); ++ if (IS_ERR(new_xino)) { ++ err = PTR_ERR(new_xino); ++ pr_err("xino(b%d-%d), err %d, ignored\n", bindex, idx, err); ++ goto out; ++ } ++ ++ err = vfs_statfs(&new_xino->f_path, st); ++ if (!err) ++ pr_info("end truncating xino(b%d-%d), ib%llu, %llu/%llu free blks\n", ++ bindex, idx, (u64)file_inode(new_xino)->i_blocks, ++ st->f_bfree, st->f_blocks); ++ else { ++ AuErr1("statfs err %d, ignored\n", err); ++ err = 0; ++ } ++ ++out: ++ return err; ++} ++ ++int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex, int idx_begin) ++{ ++ int err, i; ++ unsigned long jiffy; ++ aufs_bindex_t bbot; ++ struct kstatfs *st; ++ struct au_branch *br; ++ struct au_xino *xi; ++ ++ err = -ENOMEM; ++ st = kmalloc(sizeof(*st), GFP_NOFS); ++ if (unlikely(!st)) ++ goto out; ++ ++ err = -EINVAL; ++ bbot = au_sbbot(sb); ++ if (unlikely(bindex < 0 || bbot < bindex)) ++ goto out_st; ++ ++ err = 0; ++ jiffy = jiffies; ++ br = au_sbr(sb, bindex); ++ xi = br->br_xino; ++ for (i = idx_begin; !err && i < xi->xi_nfile; i++) ++ err = au_xino_do_trunc(sb, bindex, i, st); ++ if (!err) ++ au_sbi(sb)->si_xino_jiffy = jiffy; ++ ++out_st: ++ au_kfree_rcu(st); ++out: ++ return err; ++} ++ ++struct xino_do_trunc_args { ++ struct super_block *sb; ++ struct au_branch *br; ++ int idx; ++}; ++ ++static void xino_do_trunc(void *_args) ++{ ++ struct xino_do_trunc_args *args = _args; ++ struct super_block *sb; ++ struct au_branch *br; ++ struct inode *dir; ++ int err, idx; ++ aufs_bindex_t bindex; ++ ++ err = 0; ++ sb = args->sb; ++ dir = d_inode(sb->s_root); ++ br = args->br; ++ idx = args->idx; ++ ++ si_noflush_write_lock(sb); ++ ii_read_lock_parent(dir); ++ bindex = au_br_index(sb, br->br_id); ++ err = au_xino_trunc(sb, bindex, idx); ++ ii_read_unlock(dir); ++ if (unlikely(err)) ++ pr_warn("err b%d, (%d)\n", bindex, err); ++ atomic_dec(&br->br_xino->xi_truncating); ++ au_lcnt_dec(&br->br_count); ++ si_write_unlock(sb); ++ au_nwt_done(&au_sbi(sb)->si_nowait); ++ au_kfree_rcu(args); ++} ++ ++/* ++ * returns the index in the xi_file array whose corresponding file is necessary ++ * to truncate, or -1 which means no need to truncate. ++ */ ++static int xino_trunc_test(struct super_block *sb, struct au_branch *br) ++{ ++ int err; ++ unsigned int u; ++ struct kstatfs st; ++ struct au_sbinfo *sbinfo; ++ struct au_xino *xi; ++ struct file *file; ++ ++ /* todo: si_xino_expire and the ratio should be customizable */ ++ sbinfo = au_sbi(sb); ++ if (time_before(jiffies, ++ sbinfo->si_xino_jiffy + sbinfo->si_xino_expire)) ++ return -1; ++ ++ /* truncation border */ ++ xi = br->br_xino; ++ for (u = 0; u < xi->xi_nfile; u++) { ++ file = au_xino_file(xi, u); ++ if (!file) ++ continue; ++ ++ err = vfs_statfs(&file->f_path, &st); ++ if (unlikely(err)) { ++ AuErr1("statfs err %d, ignored\n", err); ++ return -1; ++ } ++ if (div64_u64(st.f_bfree * 100, st.f_blocks) ++ >= AUFS_XINO_DEF_TRUNC) ++ return u; ++ } ++ ++ return -1; ++} ++ ++static void xino_try_trunc(struct super_block *sb, struct au_branch *br) ++{ ++ int idx; ++ struct xino_do_trunc_args *args; ++ int wkq_err; ++ ++ idx = xino_trunc_test(sb, br); ++ if (idx < 0) ++ return; ++ ++ if (atomic_inc_return(&br->br_xino->xi_truncating) > 1) ++ goto out; ++ ++ /* lock and kfree() will be called in trunc_xino() */ ++ args = kmalloc(sizeof(*args), GFP_NOFS); ++ if (unlikely(!args)) { ++ AuErr1("no memory\n"); ++ goto out; ++ } ++ ++ au_lcnt_inc(&br->br_count); ++ args->sb = sb; ++ args->br = br; ++ args->idx = idx; ++ wkq_err = au_wkq_nowait(xino_do_trunc, args, sb, /*flags*/0); ++ if (!wkq_err) ++ return; /* success */ ++ ++ pr_err("wkq %d\n", wkq_err); ++ au_lcnt_dec(&br->br_count); ++ au_kfree_rcu(args); ++ ++out: ++ atomic_dec(&br->br_xino->xi_truncating); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++struct au_xi_calc { ++ int idx; ++ loff_t pos; ++}; ++ ++static void au_xi_calc(struct super_block *sb, ino_t h_ino, ++ struct au_xi_calc *calc) ++{ ++ loff_t maxent; ++ ++ maxent = au_xi_maxent(sb); ++ calc->idx = div64_u64_rem(h_ino, maxent, &calc->pos); ++ calc->pos *= sizeof(ino_t); ++} ++ ++static int au_xino_do_new_async(struct super_block *sb, struct au_branch *br, ++ struct au_xi_calc *calc) ++{ ++ int err; ++ struct file *file; ++ struct au_xino *xi = br->br_xino; ++ struct au_xi_new xinew = { ++ .xi = xi ++ }; ++ ++ SiMustAnyLock(sb); ++ ++ err = 0; ++ if (!xi) ++ goto out; ++ ++ mutex_lock(&xi->xi_mtx); ++ file = au_xino_file(xi, calc->idx); ++ if (file) ++ goto out_mtx; ++ ++ file = au_xino_file(xi, /*idx*/-1); ++ AuDebugOn(!file); ++ xinew.idx = calc->idx; ++ xinew.base = &file->f_path; ++ /* xinew.copy_src = NULL; */ ++ file = au_xi_new(sb, &xinew); ++ if (IS_ERR(file)) ++ err = PTR_ERR(file); ++ ++out_mtx: ++ mutex_unlock(&xi->xi_mtx); ++out: ++ return err; ++} ++ ++struct au_xino_do_new_async_args { ++ struct super_block *sb; ++ struct au_branch *br; ++ struct au_xi_calc calc; ++ ino_t ino; ++}; ++ ++struct au_xi_writing { ++ struct hlist_bl_node node; ++ ino_t h_ino, ino; ++}; ++ ++static int au_xino_do_write(vfs_writef_t write, struct file *file, ++ struct au_xi_calc *calc, ino_t ino); ++ ++static void au_xino_call_do_new_async(void *args) ++{ ++ struct au_xino_do_new_async_args *a = args; ++ struct au_branch *br; ++ struct super_block *sb; ++ struct au_sbinfo *sbi; ++ struct inode *root; ++ struct file *file; ++ struct au_xi_writing *del, *p; ++ struct hlist_bl_head *hbl; ++ struct hlist_bl_node *pos; ++ int err; ++ ++ br = a->br; ++ sb = a->sb; ++ sbi = au_sbi(sb); ++ si_noflush_read_lock(sb); ++ root = d_inode(sb->s_root); ++ ii_read_lock_child(root); ++ err = au_xino_do_new_async(sb, br, &a->calc); ++ if (unlikely(err)) { ++ AuIOErr("err %d\n", err); ++ goto out; ++ } ++ ++ file = au_xino_file(br->br_xino, a->calc.idx); ++ AuDebugOn(!file); ++ err = au_xino_do_write(sbi->si_xwrite, file, &a->calc, a->ino); ++ if (unlikely(err)) { ++ AuIOErr("err %d\n", err); ++ goto out; ++ } ++ ++ del = NULL; ++ hbl = &br->br_xino->xi_writing; ++ hlist_bl_lock(hbl); ++ au_hbl_for_each(pos, hbl) { ++ p = container_of(pos, struct au_xi_writing, node); ++ if (p->ino == a->ino) { ++ del = p; ++ hlist_bl_del(&p->node); ++ break; ++ } ++ } ++ hlist_bl_unlock(hbl); ++ au_kfree_rcu(del); ++ ++out: ++ au_lcnt_dec(&br->br_count); ++ ii_read_unlock(root); ++ si_read_unlock(sb); ++ au_nwt_done(&sbi->si_nowait); ++ au_kfree_rcu(a); ++} ++ ++/* ++ * create a new xino file asynchronously ++ */ ++static int au_xino_new_async(struct super_block *sb, struct au_branch *br, ++ struct au_xi_calc *calc, ino_t ino) ++{ ++ int err; ++ struct au_xino_do_new_async_args *arg; ++ ++ err = -ENOMEM; ++ arg = kmalloc(sizeof(*arg), GFP_NOFS); ++ if (unlikely(!arg)) ++ goto out; ++ ++ arg->sb = sb; ++ arg->br = br; ++ arg->calc = *calc; ++ arg->ino = ino; ++ au_lcnt_inc(&br->br_count); ++ err = au_wkq_nowait(au_xino_call_do_new_async, arg, sb, AuWkq_NEST); ++ if (unlikely(err)) { ++ pr_err("wkq %d\n", err); ++ au_lcnt_dec(&br->br_count); ++ au_kfree_rcu(arg); ++ } ++ ++out: ++ return err; ++} ++ ++/* ++ * read @ino from xinofile for the specified branch{@sb, @bindex} ++ * at the position of @h_ino. ++ */ ++int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, ++ ino_t *ino) ++{ ++ int err; ++ ssize_t sz; ++ struct au_xi_calc calc; ++ struct au_sbinfo *sbinfo; ++ struct file *file; ++ struct au_xino *xi; ++ struct hlist_bl_head *hbl; ++ struct hlist_bl_node *pos; ++ struct au_xi_writing *p; ++ ++ *ino = 0; ++ if (!au_opt_test(au_mntflags(sb), XINO)) ++ return 0; /* no xino */ ++ ++ err = 0; ++ au_xi_calc(sb, h_ino, &calc); ++ xi = au_sbr(sb, bindex)->br_xino; ++ file = au_xino_file(xi, calc.idx); ++ if (!file) { ++ hbl = &xi->xi_writing; ++ hlist_bl_lock(hbl); ++ au_hbl_for_each(pos, hbl) { ++ p = container_of(pos, struct au_xi_writing, node); ++ if (p->h_ino == h_ino) { ++ AuDbg("hi%llu, i%llu, found\n", ++ (u64)p->h_ino, (u64)p->ino); ++ *ino = p->ino; ++ break; ++ } ++ } ++ hlist_bl_unlock(hbl); ++ return 0; ++ } else if (vfsub_f_size_read(file) < calc.pos + sizeof(*ino)) ++ return 0; /* no xino */ ++ ++ sbinfo = au_sbi(sb); ++ sz = xino_fread(sbinfo->si_xread, file, ino, sizeof(*ino), &calc.pos); ++ if (sz == sizeof(*ino)) ++ return 0; /* success */ ++ ++ err = sz; ++ if (unlikely(sz >= 0)) { ++ err = -EIO; ++ AuIOErr("xino read error (%zd)\n", sz); ++ } ++ return err; ++} ++ ++static int au_xino_do_write(vfs_writef_t write, struct file *file, ++ struct au_xi_calc *calc, ino_t ino) ++{ ++ ssize_t sz; ++ ++ sz = xino_fwrite(write, file, &ino, sizeof(ino), &calc->pos); ++ if (sz == sizeof(ino)) ++ return 0; /* success */ ++ ++ AuIOErr("write failed (%zd)\n", sz); ++ return -EIO; ++} ++ ++/* ++ * write @ino to the xinofile for the specified branch{@sb, @bindex} ++ * at the position of @h_ino. ++ * even if @ino is zero, it is written to the xinofile and means no entry. ++ * if the size of the xino file on a specific filesystem exceeds the watermark, ++ * try truncating it. ++ */ ++int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, ++ ino_t ino) ++{ ++ int err; ++ unsigned int mnt_flags; ++ struct au_xi_calc calc; ++ struct file *file; ++ struct au_branch *br; ++ struct au_xino *xi; ++ struct au_xi_writing *p; ++ ++ SiMustAnyLock(sb); ++ ++ mnt_flags = au_mntflags(sb); ++ if (!au_opt_test(mnt_flags, XINO)) ++ return 0; ++ ++ au_xi_calc(sb, h_ino, &calc); ++ br = au_sbr(sb, bindex); ++ xi = br->br_xino; ++ file = au_xino_file(xi, calc.idx); ++ if (!file) { ++ /* store the inum pair into the list */ ++ p = kmalloc(sizeof(*p), GFP_NOFS | __GFP_NOFAIL); ++ p->h_ino = h_ino; ++ p->ino = ino; ++ au_hbl_add(&p->node, &xi->xi_writing); ++ ++ /* create and write a new xino file asynchronously */ ++ err = au_xino_new_async(sb, br, &calc, ino); ++ if (!err) ++ return 0; /* success */ ++ goto out; ++ } ++ ++ err = au_xino_do_write(au_sbi(sb)->si_xwrite, file, &calc, ino); ++ if (!err) { ++ br = au_sbr(sb, bindex); ++ if (au_opt_test(mnt_flags, TRUNC_XINO) ++ && au_test_fs_trunc_xino(au_br_sb(br))) ++ xino_try_trunc(sb, br); ++ return 0; /* success */ ++ } ++ ++out: ++ AuIOErr("write failed (%d)\n", err); ++ return -EIO; ++} ++ ++static ssize_t xino_fread_wkq(vfs_readf_t func, struct file *file, void *buf, ++ size_t size, loff_t *pos); ++ ++/* todo: unnecessary to support mmap_sem since kernel-space? */ ++ssize_t xino_fread(vfs_readf_t func, struct file *file, void *kbuf, size_t size, ++ loff_t *pos) ++{ ++ ssize_t err; ++ mm_segment_t oldfs; ++ union { ++ void *k; ++ char __user *u; ++ } buf; ++ int i; ++ const int prevent_endless = 10; ++ ++ i = 0; ++ buf.k = kbuf; ++ oldfs = get_fs(); ++ set_fs(KERNEL_DS); ++ do { ++ err = func(file, buf.u, size, pos); ++ if (err == -EINTR ++ && !au_wkq_test() ++ && fatal_signal_pending(current)) { ++ set_fs(oldfs); ++ err = xino_fread_wkq(func, file, kbuf, size, pos); ++ BUG_ON(err == -EINTR); ++ oldfs = get_fs(); ++ set_fs(KERNEL_DS); ++ } ++ } while (i++ < prevent_endless ++ && (err == -EAGAIN || err == -EINTR)); ++ set_fs(oldfs); ++ ++#if 0 /* reserved for future use */ ++ if (err > 0) ++ fsnotify_access(file->f_path.dentry); ++#endif ++ ++ return err; ++} ++ ++struct xino_fread_args { ++ ssize_t *errp; ++ vfs_readf_t func; ++ struct file *file; ++ void *buf; ++ size_t size; ++ loff_t *pos; ++}; ++ ++static void call_xino_fread(void *args) ++{ ++ struct xino_fread_args *a = args; ++ *a->errp = xino_fread(a->func, a->file, a->buf, a->size, a->pos); ++} ++ ++static ssize_t xino_fread_wkq(vfs_readf_t func, struct file *file, void *buf, ++ size_t size, loff_t *pos) ++{ ++ ssize_t err; ++ int wkq_err; ++ struct xino_fread_args args = { ++ .errp = &err, ++ .func = func, ++ .file = file, ++ .buf = buf, ++ .size = size, ++ .pos = pos ++ }; ++ ++ wkq_err = au_wkq_wait(call_xino_fread, &args); ++ if (unlikely(wkq_err)) ++ err = wkq_err; ++ ++ return err; ++} ++ ++static ssize_t xino_fwrite_wkq(vfs_writef_t func, struct file *file, void *buf, ++ size_t size, loff_t *pos); ++ ++static ssize_t do_xino_fwrite(vfs_writef_t func, struct file *file, void *kbuf, ++ size_t size, loff_t *pos) ++{ ++ ssize_t err; ++ mm_segment_t oldfs; ++ union { ++ void *k; ++ const char __user *u; ++ } buf; ++ int i; ++ const int prevent_endless = 10; ++ ++ i = 0; ++ buf.k = kbuf; ++ oldfs = get_fs(); ++ set_fs(KERNEL_DS); ++ do { ++ err = func(file, buf.u, size, pos); ++ if (err == -EINTR ++ && !au_wkq_test() ++ && fatal_signal_pending(current)) { ++ set_fs(oldfs); ++ err = xino_fwrite_wkq(func, file, kbuf, size, pos); ++ BUG_ON(err == -EINTR); ++ oldfs = get_fs(); ++ set_fs(KERNEL_DS); ++ } ++ } while (i++ < prevent_endless ++ && (err == -EAGAIN || err == -EINTR)); ++ set_fs(oldfs); ++ ++#if 0 /* reserved for future use */ ++ if (err > 0) ++ fsnotify_modify(file->f_path.dentry); ++#endif ++ ++ return err; ++} ++ ++struct do_xino_fwrite_args { ++ ssize_t *errp; ++ vfs_writef_t func; ++ struct file *file; ++ void *buf; ++ size_t size; ++ loff_t *pos; ++}; ++ ++static void call_do_xino_fwrite(void *args) ++{ ++ struct do_xino_fwrite_args *a = args; ++ *a->errp = do_xino_fwrite(a->func, a->file, a->buf, a->size, a->pos); ++} ++ ++static ssize_t xino_fwrite_wkq(vfs_writef_t func, struct file *file, void *buf, ++ size_t size, loff_t *pos) ++{ ++ ssize_t err; ++ int wkq_err; ++ struct do_xino_fwrite_args args = { ++ .errp = &err, ++ .func = func, ++ .file = file, ++ .buf = buf, ++ .size = size, ++ .pos = pos ++ }; ++ ++ /* ++ * it breaks RLIMIT_FSIZE and normal user's limit, ++ * users should care about quota and real 'filesystem full.' ++ */ ++ wkq_err = au_wkq_wait(call_do_xino_fwrite, &args); ++ if (unlikely(wkq_err)) ++ err = wkq_err; ++ ++ return err; ++} ++ ++ssize_t xino_fwrite(vfs_writef_t func, struct file *file, void *buf, ++ size_t size, loff_t *pos) ++{ ++ ssize_t err; ++ ++ if (rlimit(RLIMIT_FSIZE) == RLIM_INFINITY) { ++ lockdep_off(); ++ err = do_xino_fwrite(func, file, buf, size, pos); ++ lockdep_on(); ++ } else { ++ lockdep_off(); ++ err = xino_fwrite_wkq(func, file, buf, size, pos); ++ lockdep_on(); ++ } ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * inode number bitmap ++ */ ++static const int page_bits = (int)PAGE_SIZE * BITS_PER_BYTE; ++static ino_t xib_calc_ino(unsigned long pindex, int bit) ++{ ++ ino_t ino; ++ ++ AuDebugOn(bit < 0 || page_bits <= bit); ++ ino = AUFS_FIRST_INO + pindex * page_bits + bit; ++ return ino; ++} ++ ++static void xib_calc_bit(ino_t ino, unsigned long *pindex, int *bit) ++{ ++ AuDebugOn(ino < AUFS_FIRST_INO); ++ ino -= AUFS_FIRST_INO; ++ *pindex = ino / page_bits; ++ *bit = ino % page_bits; ++} ++ ++static int xib_pindex(struct super_block *sb, unsigned long pindex) ++{ ++ int err; ++ loff_t pos; ++ ssize_t sz; ++ struct au_sbinfo *sbinfo; ++ struct file *xib; ++ unsigned long *p; ++ ++ sbinfo = au_sbi(sb); ++ MtxMustLock(&sbinfo->si_xib_mtx); ++ AuDebugOn(pindex > ULONG_MAX / PAGE_SIZE ++ || !au_opt_test(sbinfo->si_mntflags, XINO)); ++ ++ if (pindex == sbinfo->si_xib_last_pindex) ++ return 0; ++ ++ xib = sbinfo->si_xib; ++ p = sbinfo->si_xib_buf; ++ pos = sbinfo->si_xib_last_pindex; ++ pos *= PAGE_SIZE; ++ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos); ++ if (unlikely(sz != PAGE_SIZE)) ++ goto out; ++ ++ pos = pindex; ++ pos *= PAGE_SIZE; ++ if (vfsub_f_size_read(xib) >= pos + PAGE_SIZE) ++ sz = xino_fread(sbinfo->si_xread, xib, p, PAGE_SIZE, &pos); ++ else { ++ memset(p, 0, PAGE_SIZE); ++ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos); ++ } ++ if (sz == PAGE_SIZE) { ++ sbinfo->si_xib_last_pindex = pindex; ++ return 0; /* success */ ++ } ++ ++out: ++ AuIOErr1("write failed (%zd)\n", sz); ++ err = sz; ++ if (sz >= 0) ++ err = -EIO; ++ return err; ++} ++ ++static void au_xib_clear_bit(struct inode *inode) ++{ ++ int err, bit; ++ unsigned long pindex; ++ struct super_block *sb; ++ struct au_sbinfo *sbinfo; ++ ++ AuDebugOn(inode->i_nlink); ++ ++ sb = inode->i_sb; ++ xib_calc_bit(inode->i_ino, &pindex, &bit); ++ AuDebugOn(page_bits <= bit); ++ sbinfo = au_sbi(sb); ++ mutex_lock(&sbinfo->si_xib_mtx); ++ err = xib_pindex(sb, pindex); ++ if (!err) { ++ clear_bit(bit, sbinfo->si_xib_buf); ++ sbinfo->si_xib_next_bit = bit; ++ } ++ mutex_unlock(&sbinfo->si_xib_mtx); ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * truncate a xino bitmap file ++ */ ++ ++/* todo: slow */ ++static int do_xib_restore(struct super_block *sb, struct file *file, void *page) ++{ ++ int err, bit; ++ ssize_t sz; ++ unsigned long pindex; ++ loff_t pos, pend; ++ struct au_sbinfo *sbinfo; ++ vfs_readf_t func; ++ ino_t *ino; ++ unsigned long *p; ++ ++ err = 0; ++ sbinfo = au_sbi(sb); ++ MtxMustLock(&sbinfo->si_xib_mtx); ++ p = sbinfo->si_xib_buf; ++ func = sbinfo->si_xread; ++ pend = vfsub_f_size_read(file); ++ pos = 0; ++ while (pos < pend) { ++ sz = xino_fread(func, file, page, PAGE_SIZE, &pos); ++ err = sz; ++ if (unlikely(sz <= 0)) ++ goto out; ++ ++ err = 0; ++ for (ino = page; sz > 0; ino++, sz -= sizeof(ino)) { ++ if (unlikely(*ino < AUFS_FIRST_INO)) ++ continue; ++ ++ xib_calc_bit(*ino, &pindex, &bit); ++ AuDebugOn(page_bits <= bit); ++ err = xib_pindex(sb, pindex); ++ if (!err) ++ set_bit(bit, p); ++ else ++ goto out; ++ } ++ } ++ ++out: ++ return err; ++} ++ ++static int xib_restore(struct super_block *sb) ++{ ++ int err, i; ++ unsigned int nfile; ++ aufs_bindex_t bindex, bbot; ++ void *page; ++ struct au_branch *br; ++ struct au_xino *xi; ++ struct file *file; ++ ++ err = -ENOMEM; ++ page = (void *)__get_free_page(GFP_NOFS); ++ if (unlikely(!page)) ++ goto out; ++ ++ err = 0; ++ bbot = au_sbbot(sb); ++ for (bindex = 0; !err && bindex <= bbot; bindex++) ++ if (!bindex || is_sb_shared(sb, bindex, bindex - 1) < 0) { ++ br = au_sbr(sb, bindex); ++ xi = br->br_xino; ++ nfile = xi->xi_nfile; ++ for (i = 0; i < nfile; i++) { ++ file = au_xino_file(xi, i); ++ if (file) ++ err = do_xib_restore(sb, file, page); ++ } ++ } else ++ AuDbg("skip shared b%d\n", bindex); ++ free_page((unsigned long)page); ++ ++out: ++ return err; ++} ++ ++int au_xib_trunc(struct super_block *sb) ++{ ++ int err; ++ ssize_t sz; ++ loff_t pos; ++ struct au_sbinfo *sbinfo; ++ unsigned long *p; ++ struct file *file; ++ ++ SiMustWriteLock(sb); ++ ++ err = 0; ++ sbinfo = au_sbi(sb); ++ if (!au_opt_test(sbinfo->si_mntflags, XINO)) ++ goto out; ++ ++ file = sbinfo->si_xib; ++ if (vfsub_f_size_read(file) <= PAGE_SIZE) ++ goto out; ++ ++ file = au_xino_create2(sb, &sbinfo->si_xib->f_path, NULL); ++ err = PTR_ERR(file); ++ if (IS_ERR(file)) ++ goto out; ++ fput(sbinfo->si_xib); ++ sbinfo->si_xib = file; ++ ++ p = sbinfo->si_xib_buf; ++ memset(p, 0, PAGE_SIZE); ++ pos = 0; ++ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xib, p, PAGE_SIZE, &pos); ++ if (unlikely(sz != PAGE_SIZE)) { ++ err = sz; ++ AuIOErr("err %d\n", err); ++ if (sz >= 0) ++ err = -EIO; ++ goto out; ++ } ++ ++ mutex_lock(&sbinfo->si_xib_mtx); ++ /* mnt_want_write() is unnecessary here */ ++ err = xib_restore(sb); ++ mutex_unlock(&sbinfo->si_xib_mtx); ++ ++out: ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++struct au_xino *au_xino_alloc(unsigned int nfile) ++{ ++ struct au_xino *xi; ++ ++ xi = kzalloc(sizeof(*xi), GFP_NOFS); ++ if (unlikely(!xi)) ++ goto out; ++ xi->xi_nfile = nfile; ++ xi->xi_file = kcalloc(nfile, sizeof(*xi->xi_file), GFP_NOFS); ++ if (unlikely(!xi->xi_file)) ++ goto out_free; ++ ++ xi->xi_nondir.total = 8; /* initial size */ ++ xi->xi_nondir.array = kcalloc(xi->xi_nondir.total, sizeof(ino_t), ++ GFP_NOFS); ++ if (unlikely(!xi->xi_nondir.array)) ++ goto out_file; ++ ++ spin_lock_init(&xi->xi_nondir.spin); ++ init_waitqueue_head(&xi->xi_nondir.wqh); ++ mutex_init(&xi->xi_mtx); ++ INIT_HLIST_BL_HEAD(&xi->xi_writing); ++ atomic_set(&xi->xi_truncating, 0); ++ kref_init(&xi->xi_kref); ++ goto out; /* success */ ++ ++out_file: ++ au_kfree_try_rcu(xi->xi_file); ++out_free: ++ au_kfree_rcu(xi); ++ xi = NULL; ++out: ++ return xi; ++} ++ ++static int au_xino_init(struct au_branch *br, int idx, struct file *file) ++{ ++ int err; ++ struct au_xino *xi; ++ ++ err = 0; ++ xi = au_xino_alloc(idx + 1); ++ if (unlikely(!xi)) { ++ err = -ENOMEM; ++ goto out; ++ } ++ ++ if (file) ++ get_file(file); ++ xi->xi_file[idx] = file; ++ AuDebugOn(br->br_xino); ++ br->br_xino = xi; ++ ++out: ++ return err; ++} ++ ++static void au_xino_release(struct kref *kref) ++{ ++ struct au_xino *xi; ++ int i; ++ unsigned long ul; ++ struct hlist_bl_head *hbl; ++ struct hlist_bl_node *pos, *n; ++ struct au_xi_writing *p; ++ ++ xi = container_of(kref, struct au_xino, xi_kref); ++ for (i = 0; i < xi->xi_nfile; i++) ++ if (xi->xi_file[i]) ++ fput(xi->xi_file[i]); ++ for (i = xi->xi_nondir.total - 1; i >= 0; i--) ++ AuDebugOn(xi->xi_nondir.array[i]); ++ mutex_destroy(&xi->xi_mtx); ++ hbl = &xi->xi_writing; ++ ul = au_hbl_count(hbl); ++ if (unlikely(ul)) { ++ pr_warn("xi_writing %lu\n", ul); ++ hlist_bl_lock(hbl); ++ hlist_bl_for_each_entry_safe (p, pos, n, hbl, node) { ++ hlist_bl_del(&p->node); ++ au_kfree_rcu(p); ++ } ++ hlist_bl_unlock(hbl); ++ } ++ au_kfree_try_rcu(xi->xi_file); ++ au_kfree_try_rcu(xi->xi_nondir.array); ++ au_kfree_rcu(xi); ++} ++ ++int au_xino_put(struct au_branch *br) ++{ ++ int ret; ++ struct au_xino *xi; ++ ++ ret = 0; ++ xi = br->br_xino; ++ if (xi) { ++ br->br_xino = NULL; ++ ret = kref_put(&xi->xi_kref, au_xino_release); ++ } ++ ++ return ret; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * xino mount option handlers ++ */ ++ ++/* xino bitmap */ ++static void xino_clear_xib(struct super_block *sb) ++{ ++ struct au_sbinfo *sbinfo; ++ ++ SiMustWriteLock(sb); ++ ++ sbinfo = au_sbi(sb); ++ /* unnecessary to clear sbinfo->si_xread and ->si_xwrite */ ++ if (sbinfo->si_xib) ++ fput(sbinfo->si_xib); ++ sbinfo->si_xib = NULL; ++ if (sbinfo->si_xib_buf) ++ free_page((unsigned long)sbinfo->si_xib_buf); ++ sbinfo->si_xib_buf = NULL; ++} ++ ++static int au_xino_set_xib(struct super_block *sb, struct path *path) ++{ ++ int err; ++ loff_t pos; ++ struct au_sbinfo *sbinfo; ++ struct file *file; ++ struct super_block *xi_sb; ++ ++ SiMustWriteLock(sb); ++ ++ sbinfo = au_sbi(sb); ++ file = au_xino_create2(sb, path, sbinfo->si_xib); ++ err = PTR_ERR(file); ++ if (IS_ERR(file)) ++ goto out; ++ if (sbinfo->si_xib) ++ fput(sbinfo->si_xib); ++ sbinfo->si_xib = file; ++ sbinfo->si_xread = vfs_readf(file); ++ sbinfo->si_xwrite = vfs_writef(file); ++ xi_sb = file_inode(file)->i_sb; ++ sbinfo->si_ximaxent = xi_sb->s_maxbytes; ++ if (unlikely(sbinfo->si_ximaxent < PAGE_SIZE)) { ++ err = -EIO; ++ pr_err("s_maxbytes(%llu) on %s is too small\n", ++ (u64)sbinfo->si_ximaxent, au_sbtype(xi_sb)); ++ goto out_unset; ++ } ++ sbinfo->si_ximaxent /= sizeof(ino_t); ++ ++ err = -ENOMEM; ++ if (!sbinfo->si_xib_buf) ++ sbinfo->si_xib_buf = (void *)get_zeroed_page(GFP_NOFS); ++ if (unlikely(!sbinfo->si_xib_buf)) ++ goto out_unset; ++ ++ sbinfo->si_xib_last_pindex = 0; ++ sbinfo->si_xib_next_bit = 0; ++ if (vfsub_f_size_read(file) < PAGE_SIZE) { ++ pos = 0; ++ err = xino_fwrite(sbinfo->si_xwrite, file, sbinfo->si_xib_buf, ++ PAGE_SIZE, &pos); ++ if (unlikely(err != PAGE_SIZE)) ++ goto out_free; ++ } ++ err = 0; ++ goto out; /* success */ ++ ++out_free: ++ if (sbinfo->si_xib_buf) ++ free_page((unsigned long)sbinfo->si_xib_buf); ++ sbinfo->si_xib_buf = NULL; ++ if (err >= 0) ++ err = -EIO; ++out_unset: ++ fput(sbinfo->si_xib); ++ sbinfo->si_xib = NULL; ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++/* xino for each branch */ ++static void xino_clear_br(struct super_block *sb) ++{ ++ aufs_bindex_t bindex, bbot; ++ struct au_branch *br; ++ ++ bbot = au_sbbot(sb); ++ for (bindex = 0; bindex <= bbot; bindex++) { ++ br = au_sbr(sb, bindex); ++ AuDebugOn(!br); ++ au_xino_put(br); ++ } ++} ++ ++static void au_xino_set_br_shared(struct super_block *sb, struct au_branch *br, ++ aufs_bindex_t bshared) ++{ ++ struct au_branch *brshared; ++ ++ brshared = au_sbr(sb, bshared); ++ AuDebugOn(!brshared->br_xino); ++ AuDebugOn(!brshared->br_xino->xi_file); ++ if (br->br_xino != brshared->br_xino) { ++ au_xino_get(brshared); ++ au_xino_put(br); ++ br->br_xino = brshared->br_xino; ++ } ++} ++ ++struct au_xino_do_set_br { ++ vfs_writef_t writef; ++ struct au_branch *br; ++ ino_t h_ino; ++ aufs_bindex_t bshared; ++}; ++ ++static int au_xino_do_set_br(struct super_block *sb, struct path *path, ++ struct au_xino_do_set_br *args) ++{ ++ int err; ++ struct au_xi_calc calc; ++ struct file *file; ++ struct au_branch *br; ++ struct au_xi_new xinew = { ++ .base = path ++ }; ++ ++ br = args->br; ++ xinew.xi = br->br_xino; ++ au_xi_calc(sb, args->h_ino, &calc); ++ xinew.copy_src = au_xino_file(xinew.xi, calc.idx); ++ if (args->bshared >= 0) ++ /* shared xino */ ++ au_xino_set_br_shared(sb, br, args->bshared); ++ else if (!xinew.xi) { ++ /* new xino */ ++ err = au_xino_init(br, calc.idx, xinew.copy_src); ++ if (unlikely(err)) ++ goto out; ++ } ++ ++ /* force re-creating */ ++ xinew.xi = br->br_xino; ++ xinew.idx = calc.idx; ++ mutex_lock(&xinew.xi->xi_mtx); ++ file = au_xi_new(sb, &xinew); ++ mutex_unlock(&xinew.xi->xi_mtx); ++ err = PTR_ERR(file); ++ if (IS_ERR(file)) ++ goto out; ++ AuDebugOn(!file); ++ ++ err = au_xino_do_write(args->writef, file, &calc, AUFS_ROOT_INO); ++ if (unlikely(err)) ++ au_xino_put(br); ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++static int au_xino_set_br(struct super_block *sb, struct path *path) ++{ ++ int err; ++ aufs_bindex_t bindex, bbot; ++ struct au_xino_do_set_br args; ++ struct inode *inode; ++ ++ SiMustWriteLock(sb); ++ ++ bbot = au_sbbot(sb); ++ inode = d_inode(sb->s_root); ++ args.writef = au_sbi(sb)->si_xwrite; ++ for (bindex = 0; bindex <= bbot; bindex++) { ++ args.h_ino = au_h_iptr(inode, bindex)->i_ino; ++ args.br = au_sbr(sb, bindex); ++ args.bshared = is_sb_shared(sb, bindex, bindex - 1); ++ err = au_xino_do_set_br(sb, path, &args); ++ if (unlikely(err)) ++ break; ++ } ++ ++ AuTraceErr(err); ++ return err; ++} ++ ++void au_xino_clr(struct super_block *sb) ++{ ++ struct au_sbinfo *sbinfo; ++ ++ au_xigen_clr(sb); ++ xino_clear_xib(sb); ++ xino_clear_br(sb); ++ dbgaufs_brs_del(sb, 0); ++ sbinfo = au_sbi(sb); ++ /* lvalue, do not call au_mntflags() */ ++ au_opt_clr(sbinfo->si_mntflags, XINO); ++} ++ ++int au_xino_set(struct super_block *sb, struct au_opt_xino *xiopt, int remount) ++{ ++ int err, skip; ++ struct dentry *dentry, *parent, *cur_dentry, *cur_parent; ++ struct qstr *dname, *cur_name; ++ struct file *cur_xino; ++ struct au_sbinfo *sbinfo; ++ struct path *path, *cur_path; ++ ++ SiMustWriteLock(sb); ++ ++ err = 0; ++ sbinfo = au_sbi(sb); ++ path = &xiopt->file->f_path; ++ dentry = path->dentry; ++ parent = dget_parent(dentry); ++ if (remount) { ++ skip = 0; ++ cur_xino = sbinfo->si_xib; ++ if (cur_xino) { ++ cur_path = &cur_xino->f_path; ++ cur_dentry = cur_path->dentry; ++ cur_parent = dget_parent(cur_dentry); ++ cur_name = &cur_dentry->d_name; ++ dname = &dentry->d_name; ++ skip = (cur_parent == parent ++ && au_qstreq(dname, cur_name)); ++ dput(cur_parent); ++ } ++ if (skip) ++ goto out; ++ } ++ ++ au_opt_set(sbinfo->si_mntflags, XINO); ++ err = au_xino_set_xib(sb, path); ++ /* si_x{read,write} are set */ ++ if (!err) ++ err = au_xigen_set(sb, path); ++ if (!err) ++ err = au_xino_set_br(sb, path); ++ if (!err) { ++ dbgaufs_brs_add(sb, 0, /*topdown*/1); ++ goto out; /* success */ ++ } ++ ++ /* reset all */ ++ AuIOErr("failed setting xino(%d).\n", err); ++ au_xino_clr(sb); ++ ++out: ++ dput(parent); ++ return err; ++} ++ ++/* ++ * create a xinofile at the default place/path. ++ */ ++struct file *au_xino_def(struct super_block *sb) ++{ ++ struct file *file; ++ char *page, *p; ++ struct au_branch *br; ++ struct super_block *h_sb; ++ struct path path; ++ aufs_bindex_t bbot, bindex, bwr; ++ ++ br = NULL; ++ bbot = au_sbbot(sb); ++ bwr = -1; ++ for (bindex = 0; bindex <= bbot; bindex++) { ++ br = au_sbr(sb, bindex); ++ if (au_br_writable(br->br_perm) ++ && !au_test_fs_bad_xino(au_br_sb(br))) { ++ bwr = bindex; ++ break; ++ } ++ } ++ ++ if (bwr >= 0) { ++ file = ERR_PTR(-ENOMEM); ++ page = (void *)__get_free_page(GFP_NOFS); ++ if (unlikely(!page)) ++ goto out; ++ path.mnt = au_br_mnt(br); ++ path.dentry = au_h_dptr(sb->s_root, bwr); ++ p = d_path(&path, page, PATH_MAX - sizeof(AUFS_XINO_FNAME)); ++ file = (void *)p; ++ if (!IS_ERR(p)) { ++ strcat(p, "/" AUFS_XINO_FNAME); ++ AuDbg("%s\n", p); ++ file = au_xino_create(sb, p, /*silent*/0, /*wbrtop*/1); ++ } ++ free_page((unsigned long)page); ++ } else { ++ file = au_xino_create(sb, AUFS_XINO_DEFPATH, /*silent*/0, ++ /*wbrtop*/0); ++ if (IS_ERR(file)) ++ goto out; ++ h_sb = file->f_path.dentry->d_sb; ++ if (unlikely(au_test_fs_bad_xino(h_sb))) { ++ pr_err("xino doesn't support %s(%s)\n", ++ AUFS_XINO_DEFPATH, au_sbtype(h_sb)); ++ fput(file); ++ file = ERR_PTR(-EINVAL); ++ } ++ } ++ ++out: ++ return file; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * initialize the xinofile for the specified branch @br ++ * at the place/path where @base_file indicates. ++ * test whether another branch is on the same filesystem or not, ++ * if found then share the xinofile with another branch. ++ */ ++int au_xino_init_br(struct super_block *sb, struct au_branch *br, ino_t h_ino, ++ struct path *base) ++{ ++ int err; ++ struct au_xino_do_set_br args = { ++ .h_ino = h_ino, ++ .br = br ++ }; ++ ++ args.writef = au_sbi(sb)->si_xwrite; ++ args.bshared = sbr_find_shared(sb, /*btop*/0, au_sbbot(sb), ++ au_br_sb(br)); ++ err = au_xino_do_set_br(sb, base, &args); ++ if (unlikely(err)) ++ au_xino_put(br); ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * get an unused inode number from bitmap ++ */ ++ino_t au_xino_new_ino(struct super_block *sb) ++{ ++ ino_t ino; ++ unsigned long *p, pindex, ul, pend; ++ struct au_sbinfo *sbinfo; ++ struct file *file; ++ int free_bit, err; ++ ++ if (!au_opt_test(au_mntflags(sb), XINO)) ++ return iunique(sb, AUFS_FIRST_INO); ++ ++ sbinfo = au_sbi(sb); ++ mutex_lock(&sbinfo->si_xib_mtx); ++ p = sbinfo->si_xib_buf; ++ free_bit = sbinfo->si_xib_next_bit; ++ if (free_bit < page_bits && !test_bit(free_bit, p)) ++ goto out; /* success */ ++ free_bit = find_first_zero_bit(p, page_bits); ++ if (free_bit < page_bits) ++ goto out; /* success */ ++ ++ pindex = sbinfo->si_xib_last_pindex; ++ for (ul = pindex - 1; ul < ULONG_MAX; ul--) { ++ err = xib_pindex(sb, ul); ++ if (unlikely(err)) ++ goto out_err; ++ free_bit = find_first_zero_bit(p, page_bits); ++ if (free_bit < page_bits) ++ goto out; /* success */ ++ } ++ ++ file = sbinfo->si_xib; ++ pend = vfsub_f_size_read(file) / PAGE_SIZE; ++ for (ul = pindex + 1; ul <= pend; ul++) { ++ err = xib_pindex(sb, ul); ++ if (unlikely(err)) ++ goto out_err; ++ free_bit = find_first_zero_bit(p, page_bits); ++ if (free_bit < page_bits) ++ goto out; /* success */ ++ } ++ BUG(); ++ ++out: ++ set_bit(free_bit, p); ++ sbinfo->si_xib_next_bit = free_bit + 1; ++ pindex = sbinfo->si_xib_last_pindex; ++ mutex_unlock(&sbinfo->si_xib_mtx); ++ ino = xib_calc_ino(pindex, free_bit); ++ AuDbg("i%lu\n", (unsigned long)ino); ++ return ino; ++out_err: ++ mutex_unlock(&sbinfo->si_xib_mtx); ++ AuDbg("i0\n"); ++ return 0; ++} ++ ++/* for s_op->delete_inode() */ ++void au_xino_delete_inode(struct inode *inode, const int unlinked) ++{ ++ int err; ++ unsigned int mnt_flags; ++ aufs_bindex_t bindex, bbot, bi; ++ unsigned char try_trunc; ++ struct au_iinfo *iinfo; ++ struct super_block *sb; ++ struct au_hinode *hi; ++ struct inode *h_inode; ++ struct au_branch *br; ++ vfs_writef_t xwrite; ++ struct au_xi_calc calc; ++ struct file *file; ++ ++ AuDebugOn(au_is_bad_inode(inode)); ++ ++ sb = inode->i_sb; ++ mnt_flags = au_mntflags(sb); ++ if (!au_opt_test(mnt_flags, XINO) ++ || inode->i_ino == AUFS_ROOT_INO) ++ return; ++ ++ if (unlinked) { ++ au_xigen_inc(inode); ++ au_xib_clear_bit(inode); ++ } ++ ++ iinfo = au_ii(inode); ++ bindex = iinfo->ii_btop; ++ if (bindex < 0) ++ return; ++ ++ xwrite = au_sbi(sb)->si_xwrite; ++ try_trunc = !!au_opt_test(mnt_flags, TRUNC_XINO); ++ hi = au_hinode(iinfo, bindex); ++ bbot = iinfo->ii_bbot; ++ for (; bindex <= bbot; bindex++, hi++) { ++ h_inode = hi->hi_inode; ++ if (!h_inode ++ || (!unlinked && h_inode->i_nlink)) ++ continue; ++ ++ /* inode may not be revalidated */ ++ bi = au_br_index(sb, hi->hi_id); ++ if (bi < 0) ++ continue; ++ ++ br = au_sbr(sb, bi); ++ au_xi_calc(sb, h_inode->i_ino, &calc); ++ file = au_xino_file(br->br_xino, calc.idx); ++ if (IS_ERR_OR_NULL(file)) ++ continue; ++ ++ err = au_xino_do_write(xwrite, file, &calc, /*ino*/0); ++ if (!err && try_trunc ++ && au_test_fs_trunc_xino(au_br_sb(br))) ++ xino_try_trunc(sb, br); ++ } ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int au_xinondir_find(struct au_xino *xi, ino_t h_ino) ++{ ++ int found, total, i; ++ ++ found = -1; ++ total = xi->xi_nondir.total; ++ for (i = 0; i < total; i++) { ++ if (xi->xi_nondir.array[i] != h_ino) ++ continue; ++ found = i; ++ break; ++ } ++ ++ return found; ++} ++ ++static int au_xinondir_expand(struct au_xino *xi) ++{ ++ int err, sz; ++ ino_t *p; ++ ++ BUILD_BUG_ON(KMALLOC_MAX_SIZE > INT_MAX); ++ ++ err = -ENOMEM; ++ sz = xi->xi_nondir.total * sizeof(ino_t); ++ if (unlikely(sz > KMALLOC_MAX_SIZE / 2)) ++ goto out; ++ p = au_kzrealloc(xi->xi_nondir.array, sz, sz << 1, GFP_ATOMIC, ++ /*may_shrink*/0); ++ if (p) { ++ xi->xi_nondir.array = p; ++ xi->xi_nondir.total <<= 1; ++ AuDbg("xi_nondir.total %d\n", xi->xi_nondir.total); ++ err = 0; ++ } ++ ++out: ++ return err; ++} ++ ++void au_xinondir_leave(struct super_block *sb, aufs_bindex_t bindex, ++ ino_t h_ino, int idx) ++{ ++ struct au_xino *xi; ++ ++ AuDebugOn(!au_opt_test(au_mntflags(sb), XINO)); ++ xi = au_sbr(sb, bindex)->br_xino; ++ AuDebugOn(idx < 0 || xi->xi_nondir.total <= idx); ++ ++ spin_lock(&xi->xi_nondir.spin); ++ AuDebugOn(xi->xi_nondir.array[idx] != h_ino); ++ xi->xi_nondir.array[idx] = 0; ++ spin_unlock(&xi->xi_nondir.spin); ++ wake_up_all(&xi->xi_nondir.wqh); ++} ++ ++int au_xinondir_enter(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, ++ int *idx) ++{ ++ int err, found, empty; ++ struct au_xino *xi; ++ ++ err = 0; ++ *idx = -1; ++ if (!au_opt_test(au_mntflags(sb), XINO)) ++ goto out; /* no xino */ ++ ++ xi = au_sbr(sb, bindex)->br_xino; ++ ++again: ++ spin_lock(&xi->xi_nondir.spin); ++ found = au_xinondir_find(xi, h_ino); ++ if (found == -1) { ++ empty = au_xinondir_find(xi, /*h_ino*/0); ++ if (empty == -1) { ++ empty = xi->xi_nondir.total; ++ err = au_xinondir_expand(xi); ++ if (unlikely(err)) ++ goto out_unlock; ++ } ++ xi->xi_nondir.array[empty] = h_ino; ++ *idx = empty; ++ } else { ++ spin_unlock(&xi->xi_nondir.spin); ++ wait_event(xi->xi_nondir.wqh, ++ xi->xi_nondir.array[found] != h_ino); ++ goto again; ++ } ++ ++out_unlock: ++ spin_unlock(&xi->xi_nondir.spin); ++out: ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++int au_xino_path(struct seq_file *seq, struct file *file) ++{ ++ int err; ++ ++ err = au_seq_path(seq, &file->f_path); ++ if (unlikely(err)) ++ goto out; ++ ++#define Deleted "\\040(deleted)" ++ seq->count -= sizeof(Deleted) - 1; ++ AuDebugOn(memcmp(seq->buf + seq->count, Deleted, ++ sizeof(Deleted) - 1)); ++#undef Deleted ++ ++out: ++ return err; ++} +diff -Nurp linux-5.4/fs/dcache.c linux-5.4-aufs/fs/dcache.c +--- linux-5.4/fs/dcache.c 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/fs/dcache.c 2019-11-28 01:25:59.069925618 +0200 +@@ -1264,7 +1264,7 @@ enum d_walk_ret { + * + * The @enter() callbacks are called with d_lock held. + */ +-static void d_walk(struct dentry *parent, void *data, ++void d_walk(struct dentry *parent, void *data, + enum d_walk_ret (*enter)(void *, struct dentry *)) + { + struct dentry *this_parent; +diff -Nurp linux-5.4/fs/fcntl.c linux-5.4-aufs/fs/fcntl.c +--- linux-5.4/fs/fcntl.c 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/fs/fcntl.c 2019-11-28 01:25:59.069925618 +0200 +@@ -32,7 +32,7 @@ + + #define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | O_DIRECT | O_NOATIME) + +-static int setfl(int fd, struct file * filp, unsigned long arg) ++int setfl(int fd, struct file * filp, unsigned long arg) + { + struct inode * inode = file_inode(filp); + int error = 0; +@@ -63,6 +63,8 @@ static int setfl(int fd, struct file * f + + if (filp->f_op->check_flags) + error = filp->f_op->check_flags(arg); ++ if (!error && filp->f_op->setfl) ++ error = filp->f_op->setfl(filp, arg); + if (error) + return error; + +diff -Nurp linux-5.4/fs/inode.c linux-5.4-aufs/fs/inode.c +--- linux-5.4/fs/inode.c 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/fs/inode.c 2019-11-28 01:25:59.070925617 +0200 +@@ -1673,7 +1673,7 @@ EXPORT_SYMBOL(generic_update_time); + * This does the actual work of updating an inodes time or version. Must have + * had called mnt_want_write() before calling this. + */ +-static int update_time(struct inode *inode, struct timespec64 *time, int flags) ++int update_time(struct inode *inode, struct timespec64 *time, int flags) + { + int (*update_time)(struct inode *, struct timespec64 *, int); + +diff -Nurp linux-5.4/fs/Kconfig linux-5.4-aufs/fs/Kconfig +--- linux-5.4/fs/Kconfig 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/fs/Kconfig 2019-11-28 01:33:04.893908639 +0200 +@@ -121,6 +121,7 @@ source "fs/quota/Kconfig" + source "fs/autofs/Kconfig" + source "fs/fuse/Kconfig" + source "fs/overlayfs/Kconfig" ++source "fs/aufs/Kconfig" + + menu "Caches" + +diff -Nurp linux-5.4/fs/Makefile linux-5.4-aufs/fs/Makefile +--- linux-5.4/fs/Makefile 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/fs/Makefile 2019-11-28 01:34:16.881905768 +0200 +@@ -110,6 +110,7 @@ obj-$(CONFIG_AUTOFS_FS) += autofs/ + obj-$(CONFIG_ADFS_FS) += adfs/ + obj-$(CONFIG_FUSE_FS) += fuse/ + obj-$(CONFIG_OVERLAY_FS) += overlayfs/ ++obj-$(CONFIG_AUFS_FS) += aufs/ + obj-$(CONFIG_ORANGEFS_FS) += orangefs/ + obj-$(CONFIG_UDF_FS) += udf/ + obj-$(CONFIG_SUN_OPENPROMFS) += openpromfs/ +diff -Nurp linux-5.4/fs/namespace.c linux-5.4-aufs/fs/namespace.c +--- linux-5.4/fs/namespace.c 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/fs/namespace.c 2019-11-28 01:25:59.070925617 +0200 +@@ -776,6 +776,12 @@ static inline int check_mnt(struct mount + return mnt->mnt_ns == current->nsproxy->mnt_ns; + } + ++/* for aufs, CONFIG_AUFS_BR_FUSE */ ++int is_current_mnt_ns(struct vfsmount *mnt) ++{ ++ return check_mnt(real_mount(mnt)); ++} ++ + /* + * vfsmount lock must be held for write + */ +diff -Nurp linux-5.4/fs/proc/base.c linux-5.4-aufs/fs/proc/base.c +--- linux-5.4/fs/proc/base.c 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/fs/proc/base.c 2019-11-28 01:25:59.070925617 +0200 +@@ -2037,7 +2037,7 @@ static int map_files_get_link(struct den + rc = -ENOENT; + vma = find_exact_vma(mm, vm_start, vm_end); + if (vma && vma->vm_file) { +- *path = vma->vm_file->f_path; ++ *path = vma_pr_or_file(vma)->f_path; + path_get(path); + rc = 0; + } +diff -Nurp linux-5.4/fs/proc/nommu.c linux-5.4-aufs/fs/proc/nommu.c +--- linux-5.4/fs/proc/nommu.c 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/fs/proc/nommu.c 2019-11-28 01:25:59.070925617 +0200 +@@ -41,7 +41,10 @@ static int nommu_region_show(struct seq_ + file = region->vm_file; + + if (file) { +- struct inode *inode = file_inode(region->vm_file); ++ struct inode *inode; ++ ++ file = vmr_pr_or_file(region); ++ inode = file_inode(file); + dev = inode->i_sb->s_dev; + ino = inode->i_ino; + } +diff -Nurp linux-5.4/fs/proc/task_mmu.c linux-5.4-aufs/fs/proc/task_mmu.c +--- linux-5.4/fs/proc/task_mmu.c 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/fs/proc/task_mmu.c 2019-11-28 01:25:59.070925617 +0200 +@@ -309,7 +309,10 @@ show_map_vma(struct seq_file *m, struct + const char *name = NULL; + + if (file) { +- struct inode *inode = file_inode(vma->vm_file); ++ struct inode *inode; ++ ++ file = vma_pr_or_file(vma); ++ inode = file_inode(file); + dev = inode->i_sb->s_dev; + ino = inode->i_ino; + pgoff = ((loff_t)vma->vm_pgoff) << PAGE_SHIFT; +@@ -1819,7 +1822,7 @@ static int show_numa_map(struct seq_file + struct proc_maps_private *proc_priv = &numa_priv->proc_maps; + struct vm_area_struct *vma = v; + struct numa_maps *md = &numa_priv->md; +- struct file *file = vma->vm_file; ++ struct file *file = vma_pr_or_file(vma); + struct mm_struct *mm = vma->vm_mm; + struct mempolicy *pol; + char buffer[64]; +diff -Nurp linux-5.4/fs/proc/task_nommu.c linux-5.4-aufs/fs/proc/task_nommu.c +--- linux-5.4/fs/proc/task_nommu.c 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/fs/proc/task_nommu.c 2019-11-28 01:25:59.070925617 +0200 +@@ -155,7 +155,10 @@ static int nommu_vma_show(struct seq_fil + file = vma->vm_file; + + if (file) { +- struct inode *inode = file_inode(vma->vm_file); ++ struct inode *inode; ++ ++ file = vma_pr_or_file(vma); ++ inode = file_inode(file); + dev = inode->i_sb->s_dev; + ino = inode->i_ino; + pgoff = (loff_t)vma->vm_pgoff << PAGE_SHIFT; +diff -Nurp linux-5.4/fs/read_write.c linux-5.4-aufs/fs/read_write.c +--- linux-5.4/fs/read_write.c 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/fs/read_write.c 2019-11-28 01:25:59.070925617 +0200 +@@ -498,6 +498,28 @@ static ssize_t __vfs_write(struct file * + return -EINVAL; + } + ++vfs_readf_t vfs_readf(struct file *file) ++{ ++ const struct file_operations *fop = file->f_op; ++ ++ if (fop->read) ++ return fop->read; ++ if (fop->read_iter) ++ return new_sync_read; ++ return ERR_PTR(-ENOSYS); ++} ++ ++vfs_writef_t vfs_writef(struct file *file) ++{ ++ const struct file_operations *fop = file->f_op; ++ ++ if (fop->write) ++ return fop->write; ++ if (fop->write_iter) ++ return new_sync_write; ++ return ERR_PTR(-ENOSYS); ++} ++ + ssize_t __kernel_write(struct file *file, const void *buf, size_t count, loff_t *pos) + { + mm_segment_t old_fs; +diff -Nurp linux-5.4/fs/splice.c linux-5.4-aufs/fs/splice.c +--- linux-5.4/fs/splice.c 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/fs/splice.c 2019-11-28 01:25:59.071925617 +0200 +@@ -834,8 +834,8 @@ EXPORT_SYMBOL(generic_splice_sendpage); + /* + * Attempt to initiate a splice from pipe to file. + */ +-static long do_splice_from(struct pipe_inode_info *pipe, struct file *out, +- loff_t *ppos, size_t len, unsigned int flags) ++long do_splice_from(struct pipe_inode_info *pipe, struct file *out, ++ loff_t *ppos, size_t len, unsigned int flags) + { + ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, + loff_t *, size_t, unsigned int); +@@ -851,9 +851,9 @@ static long do_splice_from(struct pipe_i + /* + * Attempt to initiate a splice from a file to a pipe. + */ +-static long do_splice_to(struct file *in, loff_t *ppos, +- struct pipe_inode_info *pipe, size_t len, +- unsigned int flags) ++long do_splice_to(struct file *in, loff_t *ppos, ++ struct pipe_inode_info *pipe, size_t len, ++ unsigned int flags) + { + ssize_t (*splice_read)(struct file *, loff_t *, + struct pipe_inode_info *, size_t, unsigned int); +diff -Nurp linux-5.4/fs/sync.c linux-5.4-aufs/fs/sync.c +--- linux-5.4/fs/sync.c 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/fs/sync.c 2019-11-28 01:25:59.071925617 +0200 +@@ -28,7 +28,7 @@ + * wait == 1 case since in that case write_inode() functions do + * sync_dirty_buffer() and thus effectively write one block at a time. + */ +-static int __sync_filesystem(struct super_block *sb, int wait) ++int __sync_filesystem(struct super_block *sb, int wait) + { + if (wait) + sync_inodes_sb(sb); +diff -Nurp linux-5.4/include/linux/fs.h linux-5.4-aufs/include/linux/fs.h +--- linux-5.4/include/linux/fs.h 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/include/linux/fs.h 2019-11-28 01:25:59.071925617 +0200 +@@ -1349,6 +1349,7 @@ extern void fasync_free(struct fasync_st + /* can be called from interrupts */ + extern void kill_fasync(struct fasync_struct **, int, int); + ++extern int setfl(int fd, struct file * filp, unsigned long arg); + extern void __f_setown(struct file *filp, struct pid *, enum pid_type, int force); + extern int f_setown(struct file *filp, unsigned long arg, int force); + extern void f_delown(struct file *filp); +@@ -1835,6 +1836,7 @@ struct file_operations { + ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int); + unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); + int (*check_flags)(int); ++ int (*setfl)(struct file *, unsigned long); + int (*flock) (struct file *, int, struct file_lock *); + ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int); + ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int); +@@ -1905,6 +1907,12 @@ ssize_t rw_copy_check_uvector(int type, + struct iovec *fast_pointer, + struct iovec **ret_pointer); + ++typedef ssize_t (*vfs_readf_t)(struct file *, char __user *, size_t, loff_t *); ++typedef ssize_t (*vfs_writef_t)(struct file *, const char __user *, size_t, ++ loff_t *); ++vfs_readf_t vfs_readf(struct file *file); ++vfs_writef_t vfs_writef(struct file *file); ++ + extern ssize_t __vfs_read(struct file *, char __user *, size_t, loff_t *); + extern ssize_t vfs_read(struct file *, char __user *, size_t, loff_t *); + extern ssize_t vfs_write(struct file *, const char __user *, size_t, loff_t *); +@@ -2325,6 +2333,7 @@ extern int current_umask(void); + extern void ihold(struct inode * inode); + extern void iput(struct inode *); + extern int generic_update_time(struct inode *, struct timespec64 *, int); ++extern int update_time(struct inode *, struct timespec64 *, int); + + /* /sys/fs */ + extern struct kobject *fs_kobj; +@@ -2613,6 +2622,7 @@ static inline bool sb_is_blkdev_sb(struc + return false; + } + #endif ++extern int __sync_filesystem(struct super_block *, int); + extern int sync_filesystem(struct super_block *); + extern const struct file_operations def_blk_fops; + extern const struct file_operations def_chr_fops; +diff -Nurp linux-5.4/include/linux/lockdep.h linux-5.4-aufs/include/linux/lockdep.h +--- linux-5.4/include/linux/lockdep.h 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/include/linux/lockdep.h 2019-11-28 01:25:59.071925617 +0200 +@@ -331,6 +331,8 @@ static inline int lockdep_match_key(stru + return lock->key == key; + } + ++struct lock_class *lockdep_hlock_class(struct held_lock *hlock); ++ + /* + * Acquire a lock. + * +@@ -473,6 +475,7 @@ struct lockdep_map { }; + + #define lockdep_depth(tsk) (0) + ++#define lockdep_is_held(lock) (1) + #define lockdep_is_held_type(l, r) (1) + + #define lockdep_assert_held(l) do { (void)(l); } while (0) +diff -Nurp linux-5.4/include/linux/mm.h linux-5.4-aufs/include/linux/mm.h +--- linux-5.4/include/linux/mm.h 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/include/linux/mm.h 2019-11-28 01:25:59.071925617 +0200 +@@ -1510,6 +1510,28 @@ static inline void unmap_shared_mapping_ + unmap_mapping_range(mapping, holebegin, holelen, 0); + } + ++extern void vma_do_file_update_time(struct vm_area_struct *, const char[], int); ++extern struct file *vma_do_pr_or_file(struct vm_area_struct *, const char[], ++ int); ++extern void vma_do_get_file(struct vm_area_struct *, const char[], int); ++extern void vma_do_fput(struct vm_area_struct *, const char[], int); ++ ++#define vma_file_update_time(vma) vma_do_file_update_time(vma, __func__, \ ++ __LINE__) ++#define vma_pr_or_file(vma) vma_do_pr_or_file(vma, __func__, \ ++ __LINE__) ++#define vma_get_file(vma) vma_do_get_file(vma, __func__, __LINE__) ++#define vma_fput(vma) vma_do_fput(vma, __func__, __LINE__) ++ ++#ifndef CONFIG_MMU ++extern struct file *vmr_do_pr_or_file(struct vm_region *, const char[], int); ++extern void vmr_do_fput(struct vm_region *, const char[], int); ++ ++#define vmr_pr_or_file(region) vmr_do_pr_or_file(region, __func__, \ ++ __LINE__) ++#define vmr_fput(region) vmr_do_fput(region, __func__, __LINE__) ++#endif /* !CONFIG_MMU */ ++ + extern int access_process_vm(struct task_struct *tsk, unsigned long addr, + void *buf, int len, unsigned int gup_flags); + extern int access_remote_vm(struct mm_struct *mm, unsigned long addr, +diff -Nurp linux-5.4/include/linux/mm_types.h linux-5.4-aufs/include/linux/mm_types.h +--- linux-5.4/include/linux/mm_types.h 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/include/linux/mm_types.h 2019-11-28 01:25:59.071925617 +0200 +@@ -267,6 +267,7 @@ struct vm_region { + unsigned long vm_top; /* region allocated to here */ + unsigned long vm_pgoff; /* the offset in vm_file corresponding to vm_start */ + struct file *vm_file; /* the backing file or NULL */ ++ struct file *vm_prfile; /* the virtual backing file or NULL */ + + int vm_usage; /* region usage count (access under nommu_region_sem) */ + bool vm_icache_flushed : 1; /* true if the icache has been flushed for +@@ -341,6 +342,7 @@ struct vm_area_struct { + unsigned long vm_pgoff; /* Offset (within vm_file) in PAGE_SIZE + units */ + struct file * vm_file; /* File we map to (can be NULL). */ ++ struct file *vm_prfile; /* shadow of vm_file */ + void * vm_private_data; /* was vm_pte (shared mem) */ + + #ifdef CONFIG_SWAP +diff -Nurp linux-5.4/include/linux/mnt_namespace.h linux-5.4-aufs/include/linux/mnt_namespace.h +--- linux-5.4/include/linux/mnt_namespace.h 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/include/linux/mnt_namespace.h 2019-11-28 01:25:59.071925617 +0200 +@@ -6,11 +6,14 @@ + struct mnt_namespace; + struct fs_struct; + struct user_namespace; ++struct vfsmount; + + extern struct mnt_namespace *copy_mnt_ns(unsigned long, struct mnt_namespace *, + struct user_namespace *, struct fs_struct *); + extern void put_mnt_ns(struct mnt_namespace *ns); + ++extern int is_current_mnt_ns(struct vfsmount *mnt); ++ + extern const struct file_operations proc_mounts_operations; + extern const struct file_operations proc_mountinfo_operations; + extern const struct file_operations proc_mountstats_operations; +diff -Nurp linux-5.4/include/linux/splice.h linux-5.4-aufs/include/linux/splice.h +--- linux-5.4/include/linux/splice.h 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/include/linux/splice.h 2019-11-28 01:25:59.071925617 +0200 +@@ -87,4 +87,10 @@ extern void splice_shrink_spd(struct spl + + extern const struct pipe_buf_operations page_cache_pipe_buf_ops; + extern const struct pipe_buf_operations default_pipe_buf_ops; ++ ++extern long do_splice_from(struct pipe_inode_info *pipe, struct file *out, ++ loff_t *ppos, size_t len, unsigned int flags); ++extern long do_splice_to(struct file *in, loff_t *ppos, ++ struct pipe_inode_info *pipe, size_t len, ++ unsigned int flags); + #endif +diff -Nurp linux-5.4/include/uapi/linux/aufs_type.h linux-5.4-aufs/include/uapi/linux/aufs_type.h +--- linux-5.4/include/uapi/linux/aufs_type.h 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/include/uapi/linux/aufs_type.h 2019-11-28 01:25:59.071925617 +0200 +@@ -0,0 +1,439 @@ ++/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ ++/* ++ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ */ ++ ++#ifndef __AUFS_TYPE_H__ ++#define __AUFS_TYPE_H__ ++ ++#define AUFS_NAME "aufs" ++ ++#ifdef __KERNEL__ ++/* ++ * define it before including all other headers. ++ * sched.h may use pr_* macros before defining "current", so define the ++ * no-current version first, and re-define later. ++ */ ++#define pr_fmt(fmt) AUFS_NAME " %s:%d: " fmt, __func__, __LINE__ ++#include ++#undef pr_fmt ++#define pr_fmt(fmt) \ ++ AUFS_NAME " %s:%d:%.*s[%d]: " fmt, __func__, __LINE__, \ ++ (int)sizeof(current->comm), current->comm, current->pid ++#else ++#include ++#include ++#endif /* __KERNEL__ */ ++ ++#include ++ ++#define AUFS_VERSION "5.4" ++ ++/* todo? move this to linux-2.6.19/include/magic.h */ ++#define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's') ++ ++/* ---------------------------------------------------------------------- */ ++ ++#ifdef CONFIG_AUFS_BRANCH_MAX_127 ++typedef int8_t aufs_bindex_t; ++#define AUFS_BRANCH_MAX 127 ++#else ++typedef int16_t aufs_bindex_t; ++#ifdef CONFIG_AUFS_BRANCH_MAX_511 ++#define AUFS_BRANCH_MAX 511 ++#elif defined(CONFIG_AUFS_BRANCH_MAX_1023) ++#define AUFS_BRANCH_MAX 1023 ++#elif defined(CONFIG_AUFS_BRANCH_MAX_32767) ++#define AUFS_BRANCH_MAX 32767 ++#endif ++#endif ++ ++#ifdef __KERNEL__ ++#ifndef AUFS_BRANCH_MAX ++#error unknown CONFIG_AUFS_BRANCH_MAX value ++#endif ++#endif /* __KERNEL__ */ ++ ++/* ---------------------------------------------------------------------- */ ++ ++#define AUFS_FSTYPE AUFS_NAME ++ ++#define AUFS_ROOT_INO 2 ++#define AUFS_FIRST_INO 11 ++ ++#define AUFS_WH_PFX ".wh." ++#define AUFS_WH_PFX_LEN ((int)sizeof(AUFS_WH_PFX) - 1) ++#define AUFS_WH_TMP_LEN 4 ++/* a limit for rmdir/rename a dir and copyup */ ++#define AUFS_MAX_NAMELEN (NAME_MAX \ ++ - AUFS_WH_PFX_LEN * 2 /* doubly whiteouted */\ ++ - 1 /* dot */\ ++ - AUFS_WH_TMP_LEN) /* hex */ ++#define AUFS_XINO_FNAME "." AUFS_NAME ".xino" ++#define AUFS_XINO_DEFPATH "/tmp/" AUFS_XINO_FNAME ++#define AUFS_XINO_DEF_SEC 30 /* seconds */ ++#define AUFS_XINO_DEF_TRUNC 45 /* percentage */ ++#define AUFS_DIRWH_DEF 3 ++#define AUFS_RDCACHE_DEF 10 /* seconds */ ++#define AUFS_RDCACHE_MAX 3600 /* seconds */ ++#define AUFS_RDBLK_DEF 512 /* bytes */ ++#define AUFS_RDHASH_DEF 32 ++#define AUFS_WKQ_NAME AUFS_NAME "d" ++#define AUFS_MFS_DEF_SEC 30 /* seconds */ ++#define AUFS_MFS_MAX_SEC 3600 /* seconds */ ++#define AUFS_FHSM_CACHE_DEF_SEC 30 /* seconds */ ++#define AUFS_PLINK_WARN 50 /* number of plinks in a single bucket */ ++ ++/* pseudo-link maintenace under /proc */ ++#define AUFS_PLINK_MAINT_NAME "plink_maint" ++#define AUFS_PLINK_MAINT_DIR "fs/" AUFS_NAME ++#define AUFS_PLINK_MAINT_PATH AUFS_PLINK_MAINT_DIR "/" AUFS_PLINK_MAINT_NAME ++ ++/* dirren, renamed dir */ ++#define AUFS_DR_INFO_PFX AUFS_WH_PFX ".dr." ++#define AUFS_DR_BRHINO_NAME AUFS_WH_PFX "hino" ++/* whiteouted doubly */ ++#define AUFS_WH_DR_INFO_PFX AUFS_WH_PFX AUFS_DR_INFO_PFX ++#define AUFS_WH_DR_BRHINO AUFS_WH_PFX AUFS_DR_BRHINO_NAME ++ ++#define AUFS_DIROPQ_NAME AUFS_WH_PFX ".opq" /* whiteouted doubly */ ++#define AUFS_WH_DIROPQ AUFS_WH_PFX AUFS_DIROPQ_NAME ++ ++#define AUFS_BASE_NAME AUFS_WH_PFX AUFS_NAME ++#define AUFS_PLINKDIR_NAME AUFS_WH_PFX "plnk" ++#define AUFS_ORPHDIR_NAME AUFS_WH_PFX "orph" ++ ++/* doubly whiteouted */ ++#define AUFS_WH_BASE AUFS_WH_PFX AUFS_BASE_NAME ++#define AUFS_WH_PLINKDIR AUFS_WH_PFX AUFS_PLINKDIR_NAME ++#define AUFS_WH_ORPHDIR AUFS_WH_PFX AUFS_ORPHDIR_NAME ++ ++/* branch permissions and attributes */ ++#define AUFS_BRPERM_RW "rw" ++#define AUFS_BRPERM_RO "ro" ++#define AUFS_BRPERM_RR "rr" ++#define AUFS_BRATTR_COO_REG "coo_reg" ++#define AUFS_BRATTR_COO_ALL "coo_all" ++#define AUFS_BRATTR_FHSM "fhsm" ++#define AUFS_BRATTR_UNPIN "unpin" ++#define AUFS_BRATTR_ICEX "icex" ++#define AUFS_BRATTR_ICEX_SEC "icexsec" ++#define AUFS_BRATTR_ICEX_SYS "icexsys" ++#define AUFS_BRATTR_ICEX_TR "icextr" ++#define AUFS_BRATTR_ICEX_USR "icexusr" ++#define AUFS_BRATTR_ICEX_OTH "icexoth" ++#define AUFS_BRRATTR_WH "wh" ++#define AUFS_BRWATTR_NLWH "nolwh" ++#define AUFS_BRWATTR_MOO "moo" ++ ++#define AuBrPerm_RW 1 /* writable, hardlinkable wh */ ++#define AuBrPerm_RO (1 << 1) /* readonly */ ++#define AuBrPerm_RR (1 << 2) /* natively readonly */ ++#define AuBrPerm_Mask (AuBrPerm_RW | AuBrPerm_RO | AuBrPerm_RR) ++ ++#define AuBrAttr_COO_REG (1 << 3) /* copy-up on open */ ++#define AuBrAttr_COO_ALL (1 << 4) ++#define AuBrAttr_COO_Mask (AuBrAttr_COO_REG | AuBrAttr_COO_ALL) ++ ++#define AuBrAttr_FHSM (1 << 5) /* file-based hsm */ ++#define AuBrAttr_UNPIN (1 << 6) /* rename-able top dir of ++ branch. meaningless since ++ linux-3.18-rc1 */ ++ ++/* ignore error in copying XATTR */ ++#define AuBrAttr_ICEX_SEC (1 << 7) ++#define AuBrAttr_ICEX_SYS (1 << 8) ++#define AuBrAttr_ICEX_TR (1 << 9) ++#define AuBrAttr_ICEX_USR (1 << 10) ++#define AuBrAttr_ICEX_OTH (1 << 11) ++#define AuBrAttr_ICEX (AuBrAttr_ICEX_SEC \ ++ | AuBrAttr_ICEX_SYS \ ++ | AuBrAttr_ICEX_TR \ ++ | AuBrAttr_ICEX_USR \ ++ | AuBrAttr_ICEX_OTH) ++ ++#define AuBrRAttr_WH (1 << 12) /* whiteout-able */ ++#define AuBrRAttr_Mask AuBrRAttr_WH ++ ++#define AuBrWAttr_NoLinkWH (1 << 13) /* un-hardlinkable whiteouts */ ++#define AuBrWAttr_MOO (1 << 14) /* move-up on open */ ++#define AuBrWAttr_Mask (AuBrWAttr_NoLinkWH | AuBrWAttr_MOO) ++ ++#define AuBrAttr_CMOO_Mask (AuBrAttr_COO_Mask | AuBrWAttr_MOO) ++ ++/* #warning test userspace */ ++#ifdef __KERNEL__ ++#ifndef CONFIG_AUFS_FHSM ++#undef AuBrAttr_FHSM ++#define AuBrAttr_FHSM 0 ++#endif ++#ifndef CONFIG_AUFS_XATTR ++#undef AuBrAttr_ICEX ++#define AuBrAttr_ICEX 0 ++#undef AuBrAttr_ICEX_SEC ++#define AuBrAttr_ICEX_SEC 0 ++#undef AuBrAttr_ICEX_SYS ++#define AuBrAttr_ICEX_SYS 0 ++#undef AuBrAttr_ICEX_TR ++#define AuBrAttr_ICEX_TR 0 ++#undef AuBrAttr_ICEX_USR ++#define AuBrAttr_ICEX_USR 0 ++#undef AuBrAttr_ICEX_OTH ++#define AuBrAttr_ICEX_OTH 0 ++#endif ++#endif ++ ++/* the longest combination */ ++/* AUFS_BRATTR_ICEX and AUFS_BRATTR_ICEX_TR don't affect here */ ++#define AuBrPermStrSz sizeof(AUFS_BRPERM_RW \ ++ "+" AUFS_BRATTR_COO_REG \ ++ "+" AUFS_BRATTR_FHSM \ ++ "+" AUFS_BRATTR_UNPIN \ ++ "+" AUFS_BRATTR_ICEX_SEC \ ++ "+" AUFS_BRATTR_ICEX_SYS \ ++ "+" AUFS_BRATTR_ICEX_USR \ ++ "+" AUFS_BRATTR_ICEX_OTH \ ++ "+" AUFS_BRWATTR_NLWH) ++ ++typedef struct { ++ char a[AuBrPermStrSz]; ++} au_br_perm_str_t; ++ ++static inline int au_br_writable(int brperm) ++{ ++ return brperm & AuBrPerm_RW; ++} ++ ++static inline int au_br_whable(int brperm) ++{ ++ return brperm & (AuBrPerm_RW | AuBrRAttr_WH); ++} ++ ++static inline int au_br_wh_linkable(int brperm) ++{ ++ return !(brperm & AuBrWAttr_NoLinkWH); ++} ++ ++static inline int au_br_cmoo(int brperm) ++{ ++ return brperm & AuBrAttr_CMOO_Mask; ++} ++ ++static inline int au_br_fhsm(int brperm) ++{ ++ return brperm & AuBrAttr_FHSM; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ioctl */ ++enum { ++ /* readdir in userspace */ ++ AuCtl_RDU, ++ AuCtl_RDU_INO, ++ ++ AuCtl_WBR_FD, /* pathconf wrapper */ ++ AuCtl_IBUSY, /* busy inode */ ++ AuCtl_MVDOWN, /* move-down */ ++ AuCtl_BR, /* info about branches */ ++ AuCtl_FHSM_FD /* connection for fhsm */ ++}; ++ ++/* borrowed from linux/include/linux/kernel.h */ ++#ifndef ALIGN ++#ifdef _GNU_SOURCE ++#define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a)-1) ++#else ++#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) ++#endif ++#define __ALIGN_MASK(x, mask) (((x)+(mask))&~(mask)) ++#endif ++ ++/* borrowed from linux/include/linux/compiler-gcc3.h */ ++#ifndef __aligned ++#define __aligned(x) __attribute__((aligned(x))) ++#endif ++ ++#ifdef __KERNEL__ ++#ifndef __packed ++#define __packed __attribute__((packed)) ++#endif ++#endif ++ ++struct au_rdu_cookie { ++ uint64_t h_pos; ++ int16_t bindex; ++ uint8_t flags; ++ uint8_t pad; ++ uint32_t generation; ++} __aligned(8); ++ ++struct au_rdu_ent { ++ uint64_t ino; ++ int16_t bindex; ++ uint8_t type; ++ uint8_t nlen; ++ uint8_t wh; ++ char name[0]; ++} __aligned(8); ++ ++static inline int au_rdu_len(int nlen) ++{ ++ /* include the terminating NULL */ ++ return ALIGN(sizeof(struct au_rdu_ent) + nlen + 1, ++ sizeof(uint64_t)); ++} ++ ++union au_rdu_ent_ul { ++ struct au_rdu_ent __user *e; ++ uint64_t ul; ++}; ++ ++enum { ++ AufsCtlRduV_SZ, ++ AufsCtlRduV_End ++}; ++ ++struct aufs_rdu { ++ /* input */ ++ union { ++ uint64_t sz; /* AuCtl_RDU */ ++ uint64_t nent; /* AuCtl_RDU_INO */ ++ }; ++ union au_rdu_ent_ul ent; ++ uint16_t verify[AufsCtlRduV_End]; ++ ++ /* input/output */ ++ uint32_t blk; ++ ++ /* output */ ++ union au_rdu_ent_ul tail; ++ /* number of entries which were added in a single call */ ++ uint64_t rent; ++ uint8_t full; ++ uint8_t shwh; ++ ++ struct au_rdu_cookie cookie; ++} __aligned(8); ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* dirren. the branch is identified by the filename who contains this */ ++struct au_drinfo { ++ uint64_t ino; ++ union { ++ uint8_t oldnamelen; ++ uint64_t _padding; ++ }; ++ uint8_t oldname[0]; ++} __aligned(8); ++ ++struct au_drinfo_fdata { ++ uint32_t magic; ++ struct au_drinfo drinfo; ++} __aligned(8); ++ ++#define AUFS_DRINFO_MAGIC_V1 ('a' << 24 | 'd' << 16 | 'r' << 8 | 0x01) ++/* future */ ++#define AUFS_DRINFO_MAGIC_V2 ('a' << 24 | 'd' << 16 | 'r' << 8 | 0x02) ++ ++/* ---------------------------------------------------------------------- */ ++ ++struct aufs_wbr_fd { ++ uint32_t oflags; ++ int16_t brid; ++} __aligned(8); ++ ++/* ---------------------------------------------------------------------- */ ++ ++struct aufs_ibusy { ++ uint64_t ino, h_ino; ++ int16_t bindex; ++} __aligned(8); ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* error code for move-down */ ++/* the actual message strings are implemented in aufs-util.git */ ++enum { ++ EAU_MVDOWN_OPAQUE = 1, ++ EAU_MVDOWN_WHITEOUT, ++ EAU_MVDOWN_UPPER, ++ EAU_MVDOWN_BOTTOM, ++ EAU_MVDOWN_NOUPPER, ++ EAU_MVDOWN_NOLOWERBR, ++ EAU_Last ++}; ++ ++/* flags for move-down */ ++#define AUFS_MVDOWN_DMSG 1 ++#define AUFS_MVDOWN_OWLOWER (1 << 1) /* overwrite lower */ ++#define AUFS_MVDOWN_KUPPER (1 << 2) /* keep upper */ ++#define AUFS_MVDOWN_ROLOWER (1 << 3) /* do even if lower is RO */ ++#define AUFS_MVDOWN_ROLOWER_R (1 << 4) /* did on lower RO */ ++#define AUFS_MVDOWN_ROUPPER (1 << 5) /* do even if upper is RO */ ++#define AUFS_MVDOWN_ROUPPER_R (1 << 6) /* did on upper RO */ ++#define AUFS_MVDOWN_BRID_UPPER (1 << 7) /* upper brid */ ++#define AUFS_MVDOWN_BRID_LOWER (1 << 8) /* lower brid */ ++#define AUFS_MVDOWN_FHSM_LOWER (1 << 9) /* find fhsm attr for lower */ ++#define AUFS_MVDOWN_STFS (1 << 10) /* req. stfs */ ++#define AUFS_MVDOWN_STFS_FAILED (1 << 11) /* output: stfs is unusable */ ++#define AUFS_MVDOWN_BOTTOM (1 << 12) /* output: no more lowers */ ++ ++/* index for move-down */ ++enum { ++ AUFS_MVDOWN_UPPER, ++ AUFS_MVDOWN_LOWER, ++ AUFS_MVDOWN_NARRAY ++}; ++ ++/* ++ * additional info of move-down ++ * number of free blocks and inodes. ++ * subset of struct kstatfs, but smaller and always 64bit. ++ */ ++struct aufs_stfs { ++ uint64_t f_blocks; ++ uint64_t f_bavail; ++ uint64_t f_files; ++ uint64_t f_ffree; ++}; ++ ++struct aufs_stbr { ++ int16_t brid; /* optional input */ ++ int16_t bindex; /* output */ ++ struct aufs_stfs stfs; /* output when AUFS_MVDOWN_STFS set */ ++} __aligned(8); ++ ++struct aufs_mvdown { ++ uint32_t flags; /* input/output */ ++ struct aufs_stbr stbr[AUFS_MVDOWN_NARRAY]; /* input/output */ ++ int8_t au_errno; /* output */ ++} __aligned(8); ++ ++/* ---------------------------------------------------------------------- */ ++ ++union aufs_brinfo { ++ /* PATH_MAX may differ between kernel-space and user-space */ ++ char _spacer[4096]; ++ struct { ++ int16_t id; ++ int perm; ++ char path[0]; ++ }; ++} __aligned(8); ++ ++/* ---------------------------------------------------------------------- */ ++ ++#define AuCtlType 'A' ++#define AUFS_CTL_RDU _IOWR(AuCtlType, AuCtl_RDU, struct aufs_rdu) ++#define AUFS_CTL_RDU_INO _IOWR(AuCtlType, AuCtl_RDU_INO, struct aufs_rdu) ++#define AUFS_CTL_WBR_FD _IOW(AuCtlType, AuCtl_WBR_FD, \ ++ struct aufs_wbr_fd) ++#define AUFS_CTL_IBUSY _IOWR(AuCtlType, AuCtl_IBUSY, struct aufs_ibusy) ++#define AUFS_CTL_MVDOWN _IOWR(AuCtlType, AuCtl_MVDOWN, \ ++ struct aufs_mvdown) ++#define AUFS_CTL_BRINFO _IOW(AuCtlType, AuCtl_BR, union aufs_brinfo) ++#define AUFS_CTL_FHSM_FD _IOW(AuCtlType, AuCtl_FHSM_FD, int) ++ ++#endif /* __AUFS_TYPE_H__ */ +diff -Nurp linux-5.4/kernel/fork.c linux-5.4-aufs/kernel/fork.c +--- linux-5.4/kernel/fork.c 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/kernel/fork.c 2019-11-28 01:25:59.072925617 +0200 +@@ -562,7 +562,7 @@ static __latent_entropy int dup_mmap(str + struct inode *inode = file_inode(file); + struct address_space *mapping = file->f_mapping; + +- get_file(file); ++ vma_get_file(tmp); + if (tmp->vm_flags & VM_DENYWRITE) + atomic_dec(&inode->i_writecount); + i_mmap_lock_write(mapping); +diff -Nurp linux-5.4/kernel/locking/lockdep.c linux-5.4-aufs/kernel/locking/lockdep.c +--- linux-5.4/kernel/locking/lockdep.c 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/kernel/locking/lockdep.c 2019-11-28 01:25:59.072925617 +0200 +@@ -153,7 +153,7 @@ static + struct lock_class lock_classes[MAX_LOCKDEP_KEYS]; + static DECLARE_BITMAP(lock_classes_in_use, MAX_LOCKDEP_KEYS); + +-static inline struct lock_class *hlock_class(struct held_lock *hlock) ++inline struct lock_class *lockdep_hlock_class(struct held_lock *hlock) + { + unsigned int class_idx = hlock->class_idx; + +@@ -174,6 +174,7 @@ static inline struct lock_class *hlock_c + */ + return lock_classes + class_idx; + } ++#define hlock_class(hlock) lockdep_hlock_class(hlock) + + #ifdef CONFIG_LOCK_STAT + static DEFINE_PER_CPU(struct lock_class_stats[MAX_LOCKDEP_KEYS], cpu_lock_stats); +diff -Nurp linux-5.4/MAINTAINERS linux-5.4-aufs/MAINTAINERS +--- linux-5.4/MAINTAINERS 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/MAINTAINERS 2019-11-28 01:25:59.062925618 +0200 +@@ -2832,6 +2832,19 @@ F: include/linux/audit.h + F: include/uapi/linux/audit.h + F: kernel/audit* + ++AUFS (advanced multi layered unification filesystem) FILESYSTEM ++M: "J. R. Okajima" ++L: aufs-users@lists.sourceforge.net (members only) ++L: linux-unionfs@vger.kernel.org ++W: http://aufs.sourceforge.net ++T: git://github.com/sfjro/aufs4-linux.git ++S: Supported ++F: Documentation/filesystems/aufs/ ++F: Documentation/ABI/testing/debugfs-aufs ++F: Documentation/ABI/testing/sysfs-aufs ++F: fs/aufs/ ++F: include/uapi/linux/aufs_type.h ++ + AUXILIARY DISPLAY DRIVERS + M: Miguel Ojeda Sandonis + S: Maintained +diff -Nurp linux-5.4/mm/filemap.c linux-5.4-aufs/mm/filemap.c +--- linux-5.4/mm/filemap.c 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/mm/filemap.c 2019-11-28 01:25:59.072925617 +0200 +@@ -2696,7 +2696,7 @@ vm_fault_t filemap_page_mkwrite(struct v + vm_fault_t ret = VM_FAULT_LOCKED; + + sb_start_pagefault(inode->i_sb); +- file_update_time(vmf->vma->vm_file); ++ vma_file_update_time(vmf->vma); + lock_page(page); + if (page->mapping != inode->i_mapping) { + unlock_page(page); +diff -Nurp linux-5.4/mm/Makefile linux-5.4-aufs/mm/Makefile +--- linux-5.4/mm/Makefile 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/mm/Makefile 2019-11-28 01:25:59.072925617 +0200 +@@ -42,7 +42,7 @@ obj-y := filemap.o mempool.o oom_kill. + mm_init.o mmu_context.o percpu.o slab_common.o \ + compaction.o vmacache.o \ + interval_tree.o list_lru.o workingset.o \ +- debug.o gup.o $(mmu-y) ++ prfile.o debug.o gup.o $(mmu-y) + + # Give 'page_alloc' its own module-parameter namespace + page-alloc-y := page_alloc.o +diff -Nurp linux-5.4/mm/mmap.c linux-5.4-aufs/mm/mmap.c +--- linux-5.4/mm/mmap.c 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/mm/mmap.c 2019-11-28 01:25:59.073925617 +0200 +@@ -182,7 +182,7 @@ static struct vm_area_struct *remove_vma + if (vma->vm_ops && vma->vm_ops->close) + vma->vm_ops->close(vma); + if (vma->vm_file) +- fput(vma->vm_file); ++ vma_fput(vma); + mpol_put(vma_policy(vma)); + vm_area_free(vma); + return next; +@@ -940,7 +940,7 @@ again: + if (remove_next) { + if (file) { + uprobe_munmap(next, next->vm_start, next->vm_end); +- fput(file); ++ vma_fput(vma); + } + if (next->anon_vma) + anon_vma_merge(vma, next); +@@ -1865,8 +1865,8 @@ out: + return addr; + + unmap_and_free_vma: ++ vma_fput(vma); + vma->vm_file = NULL; +- fput(file); + + /* Undo any partial mapping done by a device driver. */ + unmap_region(mm, vma, prev, vma->vm_start, vma->vm_end); +@@ -2695,7 +2695,7 @@ int __split_vma(struct mm_struct *mm, st + goto out_free_mpol; + + if (new->vm_file) +- get_file(new->vm_file); ++ vma_get_file(new); + + if (new->vm_ops && new->vm_ops->open) + new->vm_ops->open(new); +@@ -2714,7 +2714,7 @@ int __split_vma(struct mm_struct *mm, st + if (new->vm_ops && new->vm_ops->close) + new->vm_ops->close(new); + if (new->vm_file) +- fput(new->vm_file); ++ vma_fput(new); + unlink_anon_vmas(new); + out_free_mpol: + mpol_put(vma_policy(new)); +@@ -2906,7 +2906,7 @@ SYSCALL_DEFINE5(remap_file_pages, unsign + struct vm_area_struct *vma; + unsigned long populate = 0; + unsigned long ret = -EINVAL; +- struct file *file; ++ struct file *file, *prfile; + + pr_warn_once("%s (%d) uses deprecated remap_file_pages() syscall. See Documentation/vm/remap_file_pages.rst.\n", + current->comm, current->pid); +@@ -2981,10 +2981,27 @@ SYSCALL_DEFINE5(remap_file_pages, unsign + } + } + +- file = get_file(vma->vm_file); ++ vma_get_file(vma); ++ file = vma->vm_file; ++ prfile = vma->vm_prfile; + ret = do_mmap_pgoff(vma->vm_file, start, size, + prot, flags, pgoff, &populate, NULL); ++ if (!IS_ERR_VALUE(ret) && file && prfile) { ++ struct vm_area_struct *new_vma; ++ ++ new_vma = find_vma(mm, ret); ++ if (!new_vma->vm_prfile) ++ new_vma->vm_prfile = prfile; ++ if (new_vma != vma) ++ get_file(prfile); ++ } ++ /* ++ * two fput()s instead of vma_fput(vma), ++ * coz vma may not be available anymore. ++ */ + fput(file); ++ if (prfile) ++ fput(prfile); + out: + up_write(&mm->mmap_sem); + if (populate) +@@ -3274,7 +3291,7 @@ struct vm_area_struct *copy_vma(struct v + if (anon_vma_clone(new_vma, vma)) + goto out_free_mempol; + if (new_vma->vm_file) +- get_file(new_vma->vm_file); ++ vma_get_file(new_vma); + if (new_vma->vm_ops && new_vma->vm_ops->open) + new_vma->vm_ops->open(new_vma); + vma_link(mm, new_vma, prev, rb_link, rb_parent); +diff -Nurp linux-5.4/mm/nommu.c linux-5.4-aufs/mm/nommu.c +--- linux-5.4/mm/nommu.c 2019-11-25 02:32:01.000000000 +0200 ++++ linux-5.4-aufs/mm/nommu.c 2019-11-28 01:25:59.073925617 +0200 +@@ -552,7 +552,7 @@ static void __put_nommu_region(struct vm + up_write(&nommu_region_sem); + + if (region->vm_file) +- fput(region->vm_file); ++ vmr_fput(region); + + /* IO memory and memory shared directly out of the pagecache + * from ramfs/tmpfs mustn't be released here */ +@@ -690,7 +690,7 @@ static void delete_vma(struct mm_struct + if (vma->vm_ops && vma->vm_ops->close) + vma->vm_ops->close(vma); + if (vma->vm_file) +- fput(vma->vm_file); ++ vma_fput(vma); + put_nommu_region(vma->vm_region); + vm_area_free(vma); + } +@@ -1213,7 +1213,7 @@ unsigned long do_mmap(struct file *file, + goto error_just_free; + } + } +- fput(region->vm_file); ++ vmr_fput(region); + kmem_cache_free(vm_region_jar, region); + region = pregion; + result = start; +@@ -1290,10 +1290,10 @@ error_just_free: + up_write(&nommu_region_sem); + error: + if (region->vm_file) +- fput(region->vm_file); ++ vmr_fput(region); + kmem_cache_free(vm_region_jar, region); + if (vma->vm_file) +- fput(vma->vm_file); ++ vma_fput(vma); + vm_area_free(vma); + return ret; + +diff -Nurp linux-5.4/mm/prfile.c linux-5.4-aufs/mm/prfile.c +--- linux-5.4/mm/prfile.c 1970-01-01 02:00:00.000000000 +0200 ++++ linux-5.4-aufs/mm/prfile.c 2019-11-28 01:25:59.073925617 +0200 +@@ -0,0 +1,86 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Mainly for aufs which mmap(2) different file and wants to print different ++ * path in /proc/PID/maps. ++ * Call these functions via macros defined in linux/mm.h. ++ * ++ * See Documentation/filesystems/aufs/design/06mmap.txt ++ * ++ * Copyright (c) 2014-2019 Junjro R. Okajima ++ * Copyright (c) 2014 Ian Campbell ++ */ ++ ++#include ++#include ++#include ++ ++/* #define PRFILE_TRACE */ ++static inline void prfile_trace(struct file *f, struct file *pr, ++ const char func[], int line, const char func2[]) ++{ ++#ifdef PRFILE_TRACE ++ if (pr) ++ pr_info("%s:%d: %s, %pD2\n", func, line, func2, f); ++#endif ++} ++ ++void vma_do_file_update_time(struct vm_area_struct *vma, const char func[], ++ int line) ++{ ++ struct file *f = vma->vm_file, *pr = vma->vm_prfile; ++ ++ prfile_trace(f, pr, func, line, __func__); ++ file_update_time(f); ++ if (f && pr) ++ file_update_time(pr); ++} ++ ++struct file *vma_do_pr_or_file(struct vm_area_struct *vma, const char func[], ++ int line) ++{ ++ struct file *f = vma->vm_file, *pr = vma->vm_prfile; ++ ++ prfile_trace(f, pr, func, line, __func__); ++ return (f && pr) ? pr : f; ++} ++ ++void vma_do_get_file(struct vm_area_struct *vma, const char func[], int line) ++{ ++ struct file *f = vma->vm_file, *pr = vma->vm_prfile; ++ ++ prfile_trace(f, pr, func, line, __func__); ++ get_file(f); ++ if (f && pr) ++ get_file(pr); ++} ++ ++void vma_do_fput(struct vm_area_struct *vma, const char func[], int line) ++{ ++ struct file *f = vma->vm_file, *pr = vma->vm_prfile; ++ ++ prfile_trace(f, pr, func, line, __func__); ++ fput(f); ++ if (f && pr) ++ fput(pr); ++} ++ ++#ifndef CONFIG_MMU ++struct file *vmr_do_pr_or_file(struct vm_region *region, const char func[], ++ int line) ++{ ++ struct file *f = region->vm_file, *pr = region->vm_prfile; ++ ++ prfile_trace(f, pr, func, line, __func__); ++ return (f && pr) ? pr : f; ++} ++ ++void vmr_do_fput(struct vm_region *region, const char func[], int line) ++{ ++ struct file *f = region->vm_file, *pr = region->vm_prfile; ++ ++ prfile_trace(f, pr, func, line, __func__); ++ fput(f); ++ if (f && pr) ++ fput(pr); ++} ++#endif /* !CONFIG_MMU */ diff --git a/kernel/tools/cpupowertools/files/patches/mageia/fs-vboxsf.patch b/kernel/tools/cpupowertools/files/patches/mageia/fs-vboxsf.patch new file mode 100644 index 00000000..434fdee6 --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/mageia/fs-vboxsf.patch @@ -0,0 +1,3410 @@ +From df4028658f9dd7f82fd190e9db5bd82c05f94625 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Mon, 28 Oct 2019 12:17:44 +0100 +Subject: staging: Add VirtualBox guest shared folder (vboxsf) support + +VirtualBox hosts can share folders with guests, this commit adds a +VFS driver implementing the Linux-guest side of this, allowing folders +exported by the host to be mounted under Linux. + +This driver depends on the guest <-> host IPC functions exported by +the vboxguest driver. + +Signed-off-by: Hans de Goede +Link: https://lore.kernel.org/r/20191028111744.143863-2-hdegoede@redhat.com +Signed-off-by: Greg Kroah-Hartman +--- + MAINTAINERS | 6 + + drivers/staging/Kconfig | 2 + + drivers/staging/Makefile | 1 + + drivers/staging/vboxsf/Kconfig | 10 + + drivers/staging/vboxsf/Makefile | 5 + + drivers/staging/vboxsf/TODO | 7 + + drivers/staging/vboxsf/dir.c | 418 ++++++++++++++ + drivers/staging/vboxsf/file.c | 370 +++++++++++++ + drivers/staging/vboxsf/shfl_hostintf.h | 901 +++++++++++++++++++++++++++++++ + drivers/staging/vboxsf/super.c | 499 +++++++++++++++++ + drivers/staging/vboxsf/utils.c | 550 +++++++++++++++++++ + drivers/staging/vboxsf/vboxsf_wrappers.c | 371 +++++++++++++ + drivers/staging/vboxsf/vfsmod.h | 138 +++++ + 13 files changed, 3278 insertions(+) + create mode 100644 drivers/staging/vboxsf/Kconfig + create mode 100644 drivers/staging/vboxsf/Makefile + create mode 100644 drivers/staging/vboxsf/TODO + create mode 100644 drivers/staging/vboxsf/dir.c + create mode 100644 drivers/staging/vboxsf/file.c + create mode 100644 drivers/staging/vboxsf/shfl_hostintf.h + create mode 100644 drivers/staging/vboxsf/super.c + create mode 100644 drivers/staging/vboxsf/utils.c + create mode 100644 drivers/staging/vboxsf/vboxsf_wrappers.c + create mode 100644 drivers/staging/vboxsf/vfsmod.h + +diff --git a/MAINTAINERS b/MAINTAINERS +index c6c34d04ce95..71789e42ed17 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -17335,6 +17335,12 @@ F: include/linux/vbox_utils.h + F: include/uapi/linux/vbox*.h + F: drivers/virt/vboxguest/ + ++VIRTUAL BOX SHARED FOLDER VFS DRIVER: ++M: Hans de Goede ++L: linux-fsdevel@vger.kernel.org ++S: Maintained ++F: drivers/staging/vboxsf/* ++ + VIRTUAL SERIO DEVICE DRIVER + M: Stephen Chandler Paul + S: Maintained +diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig +index 6f1fa4c849a1..927d29eb92c6 100644 +--- a/drivers/staging/Kconfig ++++ b/drivers/staging/Kconfig +@@ -125,4 +125,6 @@ source "drivers/staging/exfat/Kconfig" + + source "drivers/staging/qlge/Kconfig" + ++source "drivers/staging/vboxsf/Kconfig" ++ + endif # STAGING +diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile +index a90f9b308c8d..f01f04199073 100644 +--- a/drivers/staging/Makefile ++++ b/drivers/staging/Makefile +@@ -53,3 +53,4 @@ obj-$(CONFIG_UWB) += uwb/ + obj-$(CONFIG_USB_WUSB) += wusbcore/ + obj-$(CONFIG_EXFAT_FS) += exfat/ + obj-$(CONFIG_QLGE) += qlge/ ++obj-$(CONFIG_VBOXSF_FS) += vboxsf/ +diff --git a/drivers/staging/vboxsf/Kconfig b/drivers/staging/vboxsf/Kconfig +new file mode 100644 +index 000000000000..b84586ae08b3 +--- /dev/null ++++ b/drivers/staging/vboxsf/Kconfig +@@ -0,0 +1,10 @@ ++config VBOXSF_FS ++ tristate "VirtualBox guest shared folder (vboxsf) support" ++ depends on X86 && VBOXGUEST ++ select NLS ++ help ++ VirtualBox hosts can share folders with guests, this driver ++ implements the Linux-guest side of this allowing folders exported ++ by the host to be mounted under Linux. ++ ++ If you want to use shared folders in VirtualBox guests, answer Y or M. +diff --git a/drivers/staging/vboxsf/Makefile b/drivers/staging/vboxsf/Makefile +new file mode 100644 +index 000000000000..9e4328e79623 +--- /dev/null ++++ b/drivers/staging/vboxsf/Makefile +@@ -0,0 +1,5 @@ ++# SPDX-License-Identifier: MIT ++ ++obj-$(CONFIG_VBOXSF_FS) += vboxsf.o ++ ++vboxsf-y := dir.o file.o utils.o vboxsf_wrappers.o super.o +diff --git a/drivers/staging/vboxsf/TODO b/drivers/staging/vboxsf/TODO +new file mode 100644 +index 000000000000..8b9193d0d4f0 +--- /dev/null ++++ b/drivers/staging/vboxsf/TODO +@@ -0,0 +1,7 @@ ++TODO: ++- Find a file-system developer to review this and give their Reviewed-By ++- Address any items coming up during review ++- Move to fs/vboxfs ++ ++Please send any patches to Greg Kroah-Hartman ++and Hans de Goede +diff --git a/drivers/staging/vboxsf/dir.c b/drivers/staging/vboxsf/dir.c +new file mode 100644 +index 000000000000..f260b5cc1646 +--- /dev/null ++++ b/drivers/staging/vboxsf/dir.c +@@ -0,0 +1,418 @@ ++// SPDX-License-Identifier: MIT ++/* ++ * VirtualBox Guest Shared Folders support: Directory inode and file operations ++ * ++ * Copyright (C) 2006-2018 Oracle Corporation ++ */ ++ ++#include ++#include ++#include "vfsmod.h" ++ ++static int vboxsf_dir_open(struct inode *inode, struct file *file) ++{ ++ struct vboxsf_sbi *sbi = VBOXSF_SBI(inode->i_sb); ++ struct shfl_createparms params = {}; ++ struct vboxsf_dir_info *sf_d; ++ int err; ++ ++ sf_d = vboxsf_dir_info_alloc(); ++ if (!sf_d) ++ return -ENOMEM; ++ ++ params.handle = SHFL_HANDLE_NIL; ++ params.create_flags = SHFL_CF_DIRECTORY | SHFL_CF_ACT_OPEN_IF_EXISTS | ++ SHFL_CF_ACT_FAIL_IF_NEW | SHFL_CF_ACCESS_READ; ++ ++ err = vboxsf_create_at_dentry(file_dentry(file), ¶ms); ++ if (err) ++ goto err_free_dir_info; ++ ++ if (params.result != SHFL_FILE_EXISTS) { ++ err = -ENOENT; ++ goto err_close; ++ } ++ ++ err = vboxsf_dir_read_all(sbi, sf_d, params.handle); ++ if (err) ++ goto err_close; ++ ++ vboxsf_close(sbi->root, params.handle); ++ file->private_data = sf_d; ++ return 0; ++ ++err_close: ++ vboxsf_close(sbi->root, params.handle); ++err_free_dir_info: ++ vboxsf_dir_info_free(sf_d); ++ return err; ++} ++ ++static int vboxsf_dir_release(struct inode *inode, struct file *file) ++{ ++ if (file->private_data) ++ vboxsf_dir_info_free(file->private_data); ++ ++ return 0; ++} ++ ++static unsigned int vboxsf_get_d_type(u32 mode) ++{ ++ unsigned int d_type; ++ ++ switch (mode & SHFL_TYPE_MASK) { ++ case SHFL_TYPE_FIFO: ++ d_type = DT_FIFO; ++ break; ++ case SHFL_TYPE_DEV_CHAR: ++ d_type = DT_CHR; ++ break; ++ case SHFL_TYPE_DIRECTORY: ++ d_type = DT_DIR; ++ break; ++ case SHFL_TYPE_DEV_BLOCK: ++ d_type = DT_BLK; ++ break; ++ case SHFL_TYPE_FILE: ++ d_type = DT_REG; ++ break; ++ case SHFL_TYPE_SYMLINK: ++ d_type = DT_LNK; ++ break; ++ case SHFL_TYPE_SOCKET: ++ d_type = DT_SOCK; ++ break; ++ case SHFL_TYPE_WHITEOUT: ++ d_type = DT_WHT; ++ break; ++ default: ++ d_type = DT_UNKNOWN; ++ break; ++ } ++ return d_type; ++} ++ ++static bool vboxsf_dir_emit(struct file *dir, struct dir_context *ctx) ++{ ++ struct vboxsf_sbi *sbi = VBOXSF_SBI(file_inode(dir)->i_sb); ++ struct vboxsf_dir_info *sf_d = dir->private_data; ++ struct shfl_dirinfo *info; ++ struct vboxsf_dir_buf *b; ++ unsigned int d_type; ++ loff_t i, cur = 0; ++ ino_t fake_ino; ++ size_t size; ++ int err; ++ ++ list_for_each_entry(b, &sf_d->info_list, head) { ++try_next_entry: ++ if (ctx->pos >= cur + b->entries) { ++ cur += b->entries; ++ continue; ++ } ++ ++ /* ++ * Note the vboxsf_dir_info objects we are iterating over here ++ * are variable sized, so the info pointer may end up being ++ * unaligned. This is how we get the data from the host. ++ * Since vboxsf is only supported on x86 machines this is not ++ * a problem. ++ */ ++ for (i = 0, info = b->buf; i < ctx->pos - cur; i++) { ++ size = offsetof(struct shfl_dirinfo, name.string) + ++ info->name.size; ++ info = (struct shfl_dirinfo *)((uintptr_t)info + size); ++ } ++ ++ /* Info now points to the right entry, emit it. */ ++ d_type = vboxsf_get_d_type(info->info.attr.mode); ++ ++ /* ++ * On 32 bit systems pos is 64 signed, while ino is 32 bit ++ * unsigned so fake_ino may overflow, check for this. ++ */ ++ if ((ino_t)(ctx->pos + 1) != (u64)(ctx->pos + 1)) { ++ vbg_err("vboxsf: fake ino overflow, truncating dir\n"); ++ return false; ++ } ++ fake_ino = ctx->pos + 1; ++ ++ if (sbi->nls) { ++ char d_name[NAME_MAX]; ++ ++ err = vboxsf_nlscpy(sbi, d_name, NAME_MAX, ++ info->name.string.utf8, ++ info->name.length); ++ if (err) { ++ /* skip erroneous entry and proceed */ ++ ctx->pos += 1; ++ goto try_next_entry; ++ } ++ ++ return dir_emit(ctx, d_name, strlen(d_name), ++ fake_ino, d_type); ++ } ++ ++ return dir_emit(ctx, info->name.string.utf8, info->name.length, ++ fake_ino, d_type); ++ } ++ ++ return false; ++} ++ ++static int vboxsf_dir_iterate(struct file *dir, struct dir_context *ctx) ++{ ++ bool keep_iterating; ++ ++ for (keep_iterating = true; keep_iterating; ctx->pos += 1) ++ keep_iterating = vboxsf_dir_emit(dir, ctx); ++ ++ return 0; ++} ++ ++const struct file_operations vboxsf_dir_fops = { ++ .open = vboxsf_dir_open, ++ .iterate = vboxsf_dir_iterate, ++ .release = vboxsf_dir_release, ++ .read = generic_read_dir, ++ .llseek = generic_file_llseek, ++}; ++ ++/* ++ * This is called during name resolution/lookup to check if the @dentry in ++ * the cache is still valid. the job is handled by vboxsf_inode_revalidate. ++ */ ++static int vboxsf_dentry_revalidate(struct dentry *dentry, unsigned int flags) ++{ ++ if (flags & LOOKUP_RCU) ++ return -ECHILD; ++ ++ if (d_really_is_positive(dentry)) ++ return vboxsf_inode_revalidate(dentry) == 0; ++ else ++ return vboxsf_stat_dentry(dentry, NULL) == -ENOENT; ++} ++ ++const struct dentry_operations vboxsf_dentry_ops = { ++ .d_revalidate = vboxsf_dentry_revalidate ++}; ++ ++/* iops */ ++ ++static struct dentry *vboxsf_dir_lookup(struct inode *parent, ++ struct dentry *dentry, ++ unsigned int flags) ++{ ++ struct vboxsf_sbi *sbi = VBOXSF_SBI(parent->i_sb); ++ struct shfl_fsobjinfo fsinfo; ++ struct inode *inode; ++ int err; ++ ++ dentry->d_time = jiffies; ++ ++ err = vboxsf_stat_dentry(dentry, &fsinfo); ++ if (err) { ++ inode = (err == -ENOENT) ? NULL : ERR_PTR(err); ++ } else { ++ inode = vboxsf_new_inode(parent->i_sb); ++ if (!IS_ERR(inode)) ++ vboxsf_init_inode(sbi, inode, &fsinfo); ++ } ++ ++ return d_splice_alias(inode, dentry); ++} ++ ++static int vboxsf_dir_instantiate(struct inode *parent, struct dentry *dentry, ++ struct shfl_fsobjinfo *info) ++{ ++ struct vboxsf_sbi *sbi = VBOXSF_SBI(parent->i_sb); ++ struct vboxsf_inode *sf_i; ++ struct inode *inode; ++ ++ inode = vboxsf_new_inode(parent->i_sb); ++ if (IS_ERR(inode)) ++ return PTR_ERR(inode); ++ ++ sf_i = VBOXSF_I(inode); ++ /* The host may have given us different attr then requested */ ++ sf_i->force_restat = 1; ++ vboxsf_init_inode(sbi, inode, info); ++ ++ d_instantiate(dentry, inode); ++ ++ return 0; ++} ++ ++static int vboxsf_dir_create(struct inode *parent, struct dentry *dentry, ++ umode_t mode, int is_dir) ++{ ++ struct vboxsf_inode *sf_parent_i = VBOXSF_I(parent); ++ struct vboxsf_sbi *sbi = VBOXSF_SBI(parent->i_sb); ++ struct shfl_createparms params = {}; ++ int err; ++ ++ params.handle = SHFL_HANDLE_NIL; ++ params.create_flags = SHFL_CF_ACT_CREATE_IF_NEW | ++ SHFL_CF_ACT_FAIL_IF_EXISTS | ++ SHFL_CF_ACCESS_READWRITE | ++ (is_dir ? SHFL_CF_DIRECTORY : 0); ++ params.info.attr.mode = (mode & 0777) | ++ (is_dir ? SHFL_TYPE_DIRECTORY : SHFL_TYPE_FILE); ++ params.info.attr.additional = SHFLFSOBJATTRADD_NOTHING; ++ ++ err = vboxsf_create_at_dentry(dentry, ¶ms); ++ if (err) ++ return err; ++ ++ if (params.result != SHFL_FILE_CREATED) ++ return -EPERM; ++ ++ vboxsf_close(sbi->root, params.handle); ++ ++ err = vboxsf_dir_instantiate(parent, dentry, ¶ms.info); ++ if (err) ++ return err; ++ ++ /* parent directory access/change time changed */ ++ sf_parent_i->force_restat = 1; ++ ++ return 0; ++} ++ ++static int vboxsf_dir_mkfile(struct inode *parent, struct dentry *dentry, ++ umode_t mode, bool excl) ++{ ++ return vboxsf_dir_create(parent, dentry, mode, 0); ++} ++ ++static int vboxsf_dir_mkdir(struct inode *parent, struct dentry *dentry, ++ umode_t mode) ++{ ++ return vboxsf_dir_create(parent, dentry, mode, 1); ++} ++ ++static int vboxsf_dir_unlink(struct inode *parent, struct dentry *dentry) ++{ ++ struct vboxsf_sbi *sbi = VBOXSF_SBI(parent->i_sb); ++ struct vboxsf_inode *sf_parent_i = VBOXSF_I(parent); ++ struct inode *inode = d_inode(dentry); ++ struct shfl_string *path; ++ u32 flags; ++ int err; ++ ++ if (S_ISDIR(inode->i_mode)) ++ flags = SHFL_REMOVE_DIR; ++ else ++ flags = SHFL_REMOVE_FILE; ++ ++ if (S_ISLNK(inode->i_mode)) ++ flags |= SHFL_REMOVE_SYMLINK; ++ ++ path = vboxsf_path_from_dentry(sbi, dentry); ++ if (IS_ERR(path)) ++ return PTR_ERR(path); ++ ++ err = vboxsf_remove(sbi->root, path, flags); ++ __putname(path); ++ if (err) ++ return err; ++ ++ /* parent directory access/change time changed */ ++ sf_parent_i->force_restat = 1; ++ ++ return 0; ++} ++ ++static int vboxsf_dir_rename(struct inode *old_parent, ++ struct dentry *old_dentry, ++ struct inode *new_parent, ++ struct dentry *new_dentry, ++ unsigned int flags) ++{ ++ struct vboxsf_sbi *sbi = VBOXSF_SBI(old_parent->i_sb); ++ struct vboxsf_inode *sf_old_parent_i = VBOXSF_I(old_parent); ++ struct vboxsf_inode *sf_new_parent_i = VBOXSF_I(new_parent); ++ u32 shfl_flags = SHFL_RENAME_FILE | SHFL_RENAME_REPLACE_IF_EXISTS; ++ struct shfl_string *old_path, *new_path; ++ int err; ++ ++ if (flags) ++ return -EINVAL; ++ ++ old_path = vboxsf_path_from_dentry(sbi, old_dentry); ++ if (IS_ERR(old_path)) ++ return PTR_ERR(old_path); ++ ++ new_path = vboxsf_path_from_dentry(sbi, new_dentry); ++ if (IS_ERR(new_path)) { ++ err = PTR_ERR(new_path); ++ goto err_put_old_path; ++ } ++ ++ if (d_inode(old_dentry)->i_mode & S_IFDIR) ++ shfl_flags = 0; ++ ++ err = vboxsf_rename(sbi->root, old_path, new_path, shfl_flags); ++ if (err == 0) { ++ /* parent directories access/change time changed */ ++ sf_new_parent_i->force_restat = 1; ++ sf_old_parent_i->force_restat = 1; ++ } ++ ++ __putname(new_path); ++err_put_old_path: ++ __putname(old_path); ++ return err; ++} ++ ++static int vboxsf_dir_symlink(struct inode *parent, struct dentry *dentry, ++ const char *symname) ++{ ++ struct vboxsf_inode *sf_parent_i = VBOXSF_I(parent); ++ struct vboxsf_sbi *sbi = VBOXSF_SBI(parent->i_sb); ++ int symname_size = strlen(symname) + 1; ++ struct shfl_string *path, *ssymname; ++ struct shfl_fsobjinfo info; ++ int err; ++ ++ path = vboxsf_path_from_dentry(sbi, dentry); ++ if (IS_ERR(path)) ++ return PTR_ERR(path); ++ ++ ssymname = kmalloc(SHFLSTRING_HEADER_SIZE + symname_size, GFP_KERNEL); ++ if (!ssymname) { ++ __putname(path); ++ return -ENOMEM; ++ } ++ ssymname->length = symname_size - 1; ++ ssymname->size = symname_size; ++ memcpy(ssymname->string.utf8, symname, symname_size); ++ ++ err = vboxsf_symlink(sbi->root, path, ssymname, &info); ++ kfree(ssymname); ++ __putname(path); ++ if (err) { ++ /* -EROFS means symlinks are note support -> -EPERM */ ++ return (err == -EROFS) ? -EPERM : err; ++ } ++ ++ err = vboxsf_dir_instantiate(parent, dentry, &info); ++ if (err) ++ return err; ++ ++ /* parent directory access/change time changed */ ++ sf_parent_i->force_restat = 1; ++ return 0; ++} ++ ++const struct inode_operations vboxsf_dir_iops = { ++ .lookup = vboxsf_dir_lookup, ++ .create = vboxsf_dir_mkfile, ++ .mkdir = vboxsf_dir_mkdir, ++ .rmdir = vboxsf_dir_unlink, ++ .unlink = vboxsf_dir_unlink, ++ .rename = vboxsf_dir_rename, ++ .symlink = vboxsf_dir_symlink, ++ .getattr = vboxsf_getattr, ++ .setattr = vboxsf_setattr, ++}; +diff --git a/drivers/staging/vboxsf/file.c b/drivers/staging/vboxsf/file.c +new file mode 100644 +index 000000000000..4b61ccf83fca +--- /dev/null ++++ b/drivers/staging/vboxsf/file.c +@@ -0,0 +1,370 @@ ++// SPDX-License-Identifier: MIT ++/* ++ * VirtualBox Guest Shared Folders support: Regular file inode and file ops. ++ * ++ * Copyright (C) 2006-2018 Oracle Corporation ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include "vfsmod.h" ++ ++struct vboxsf_handle { ++ u64 handle; ++ u32 root; ++ u32 access_flags; ++ struct kref refcount; ++ struct list_head head; ++}; ++ ++static int vboxsf_file_open(struct inode *inode, struct file *file) ++{ ++ struct vboxsf_inode *sf_i = VBOXSF_I(inode); ++ struct shfl_createparms params = {}; ++ struct vboxsf_handle *sf_handle; ++ u32 access_flags = 0; ++ int err; ++ ++ sf_handle = kmalloc(sizeof(*sf_handle), GFP_KERNEL); ++ if (!sf_handle) ++ return -ENOMEM; ++ ++ /* ++ * We check the value of params.handle afterwards to find out if ++ * the call succeeded or failed, as the API does not seem to cleanly ++ * distinguish error and informational messages. ++ * ++ * Furthermore, we must set params.handle to SHFL_HANDLE_NIL to ++ * make the shared folders host service use our mode parameter. ++ */ ++ params.handle = SHFL_HANDLE_NIL; ++ if (file->f_flags & O_CREAT) { ++ params.create_flags |= SHFL_CF_ACT_CREATE_IF_NEW; ++ /* ++ * We ignore O_EXCL, as the Linux kernel seems to call create ++ * beforehand itself, so O_EXCL should always fail. ++ */ ++ if (file->f_flags & O_TRUNC) ++ params.create_flags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS; ++ else ++ params.create_flags |= SHFL_CF_ACT_OPEN_IF_EXISTS; ++ } else { ++ params.create_flags |= SHFL_CF_ACT_FAIL_IF_NEW; ++ if (file->f_flags & O_TRUNC) ++ params.create_flags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS; ++ } ++ ++ switch (file->f_flags & O_ACCMODE) { ++ case O_RDONLY: ++ access_flags |= SHFL_CF_ACCESS_READ; ++ break; ++ ++ case O_WRONLY: ++ access_flags |= SHFL_CF_ACCESS_WRITE; ++ break; ++ ++ case O_RDWR: ++ access_flags |= SHFL_CF_ACCESS_READWRITE; ++ break; ++ ++ default: ++ WARN_ON(1); ++ } ++ ++ if (file->f_flags & O_APPEND) ++ access_flags |= SHFL_CF_ACCESS_APPEND; ++ ++ params.create_flags |= access_flags; ++ params.info.attr.mode = inode->i_mode; ++ ++ err = vboxsf_create_at_dentry(file_dentry(file), ¶ms); ++ if (err == 0 && params.handle == SHFL_HANDLE_NIL) ++ err = (params.result == SHFL_FILE_EXISTS) ? -EEXIST : -ENOENT; ++ if (err) { ++ kfree(sf_handle); ++ return err; ++ } ++ ++ /* the host may have given us different attr then requested */ ++ sf_i->force_restat = 1; ++ ++ /* init our handle struct and add it to the inode's handles list */ ++ sf_handle->handle = params.handle; ++ sf_handle->root = VBOXSF_SBI(inode->i_sb)->root; ++ sf_handle->access_flags = access_flags; ++ kref_init(&sf_handle->refcount); ++ ++ mutex_lock(&sf_i->handle_list_mutex); ++ list_add(&sf_handle->head, &sf_i->handle_list); ++ mutex_unlock(&sf_i->handle_list_mutex); ++ ++ file->private_data = sf_handle; ++ return 0; ++} ++ ++static void vboxsf_handle_release(struct kref *refcount) ++{ ++ struct vboxsf_handle *sf_handle = ++ container_of(refcount, struct vboxsf_handle, refcount); ++ ++ vboxsf_close(sf_handle->root, sf_handle->handle); ++ kfree(sf_handle); ++} ++ ++static int vboxsf_file_release(struct inode *inode, struct file *file) ++{ ++ struct vboxsf_inode *sf_i = VBOXSF_I(inode); ++ struct vboxsf_handle *sf_handle = file->private_data; ++ ++ /* ++ * When a file is closed on our (the guest) side, we want any subsequent ++ * accesses done on the host side to see all changes done from our side. ++ */ ++ filemap_write_and_wait(inode->i_mapping); ++ ++ mutex_lock(&sf_i->handle_list_mutex); ++ list_del(&sf_handle->head); ++ mutex_unlock(&sf_i->handle_list_mutex); ++ ++ kref_put(&sf_handle->refcount, vboxsf_handle_release); ++ return 0; ++} ++ ++/* ++ * Write back dirty pages now, because there may not be any suitable ++ * open files later ++ */ ++static void vboxsf_vma_close(struct vm_area_struct *vma) ++{ ++ filemap_write_and_wait(vma->vm_file->f_mapping); ++} ++ ++static const struct vm_operations_struct vboxsf_file_vm_ops = { ++ .close = vboxsf_vma_close, ++ .fault = filemap_fault, ++ .map_pages = filemap_map_pages, ++}; ++ ++static int vboxsf_file_mmap(struct file *file, struct vm_area_struct *vma) ++{ ++ int err; ++ ++ err = generic_file_mmap(file, vma); ++ if (!err) ++ vma->vm_ops = &vboxsf_file_vm_ops; ++ ++ return err; ++} ++ ++/* ++ * Note that since we are accessing files on the host's filesystem, files ++ * may always be changed underneath us by the host! ++ * ++ * The vboxsf API between the guest and the host does not offer any functions ++ * to deal with this. There is no inode-generation to check for changes, no ++ * events / callback on changes and no way to lock files. ++ * ++ * To avoid returning stale data when a file gets *opened* on our (the guest) ++ * side, we do a "stat" on the host side, then compare the mtime with the ++ * last known mtime and invalidate the page-cache if they differ. ++ * This is done from vboxsf_inode_revalidate(). ++ * ++ * When reads are done through the read_iter fop, it is possible to do ++ * further cache revalidation then, there are 3 options to deal with this: ++ * ++ * 1) Rely solely on the revalidation done at open time ++ * 2) Do another "stat" and compare mtime again. Unfortunately the vboxsf ++ * host API does not allow stat on handles, so we would need to use ++ * file->f_path.dentry and the stat will then fail if the file was unlinked ++ * or renamed (and there is no thing like NFS' silly-rename). So we get: ++ * 2a) "stat" and compare mtime, on stat failure invalidate the cache ++ * 2b) "stat" and compare mtime, on stat failure do nothing ++ * 3) Simply always call invalidate_inode_pages2_range on the range of the read ++ * ++ * Currently we are keeping things KISS and using option 1. this allows ++ * directly using generic_file_read_iter without wrapping it. ++ * ++ * This means that only data written on the host side before open() on ++ * the guest side is guaranteed to be seen by the guest. If necessary ++ * we may provide other read-cache strategies in the future and make this ++ * configurable through a mount option. ++ */ ++const struct file_operations vboxsf_reg_fops = { ++ .llseek = generic_file_llseek, ++ .read_iter = generic_file_read_iter, ++ .write_iter = generic_file_write_iter, ++ .mmap = vboxsf_file_mmap, ++ .open = vboxsf_file_open, ++ .release = vboxsf_file_release, ++ .fsync = noop_fsync, ++ .splice_read = generic_file_splice_read, ++}; ++ ++const struct inode_operations vboxsf_reg_iops = { ++ .getattr = vboxsf_getattr, ++ .setattr = vboxsf_setattr ++}; ++ ++static int vboxsf_readpage(struct file *file, struct page *page) ++{ ++ struct vboxsf_handle *sf_handle = file->private_data; ++ loff_t off = page_offset(page); ++ u32 nread = PAGE_SIZE; ++ u8 *buf; ++ int err; ++ ++ buf = kmap(page); ++ ++ err = vboxsf_read(sf_handle->root, sf_handle->handle, off, &nread, buf); ++ if (err == 0) { ++ memset(&buf[nread], 0, PAGE_SIZE - nread); ++ flush_dcache_page(page); ++ SetPageUptodate(page); ++ } else { ++ SetPageError(page); ++ } ++ ++ kunmap(page); ++ unlock_page(page); ++ return err; ++} ++ ++static struct vboxsf_handle *vboxsf_get_write_handle(struct vboxsf_inode *sf_i) ++{ ++ struct vboxsf_handle *h, *sf_handle = NULL; ++ ++ mutex_lock(&sf_i->handle_list_mutex); ++ list_for_each_entry(h, &sf_i->handle_list, head) { ++ if (h->access_flags == SHFL_CF_ACCESS_WRITE || ++ h->access_flags == SHFL_CF_ACCESS_READWRITE) { ++ kref_get(&h->refcount); ++ sf_handle = h; ++ break; ++ } ++ } ++ mutex_unlock(&sf_i->handle_list_mutex); ++ ++ return sf_handle; ++} ++ ++static int vboxsf_writepage(struct page *page, struct writeback_control *wbc) ++{ ++ struct inode *inode = page->mapping->host; ++ struct vboxsf_inode *sf_i = VBOXSF_I(inode); ++ struct vboxsf_handle *sf_handle; ++ loff_t off = page_offset(page); ++ loff_t size = i_size_read(inode); ++ u32 nwrite = PAGE_SIZE; ++ u8 *buf; ++ int err; ++ ++ if (off + PAGE_SIZE > size) ++ nwrite = size & ~PAGE_MASK; ++ ++ sf_handle = vboxsf_get_write_handle(sf_i); ++ if (!sf_handle) ++ return -EBADF; ++ ++ buf = kmap(page); ++ err = vboxsf_write(sf_handle->root, sf_handle->handle, ++ off, &nwrite, buf); ++ kunmap(page); ++ ++ kref_put(&sf_handle->refcount, vboxsf_handle_release); ++ ++ if (err == 0) { ++ ClearPageError(page); ++ /* mtime changed */ ++ sf_i->force_restat = 1; ++ } else { ++ ClearPageUptodate(page); ++ } ++ ++ unlock_page(page); ++ return err; ++} ++ ++static int vboxsf_write_end(struct file *file, struct address_space *mapping, ++ loff_t pos, unsigned int len, unsigned int copied, ++ struct page *page, void *fsdata) ++{ ++ struct inode *inode = mapping->host; ++ struct vboxsf_handle *sf_handle = file->private_data; ++ unsigned int from = pos & ~PAGE_MASK; ++ u32 nwritten = len; ++ u8 *buf; ++ int err; ++ ++ buf = kmap(page); ++ err = vboxsf_write(sf_handle->root, sf_handle->handle, ++ pos, &nwritten, buf + from); ++ kunmap(page); ++ ++ if (err) { ++ nwritten = 0; ++ goto out; ++ } ++ ++ /* mtime changed */ ++ VBOXSF_I(inode)->force_restat = 1; ++ ++ if (!PageUptodate(page) && nwritten == PAGE_SIZE) ++ SetPageUptodate(page); ++ ++ pos += nwritten; ++ if (pos > inode->i_size) ++ i_size_write(inode, pos); ++ ++out: ++ unlock_page(page); ++ put_page(page); ++ ++ return nwritten; ++} ++ ++const struct address_space_operations vboxsf_reg_aops = { ++ .readpage = vboxsf_readpage, ++ .writepage = vboxsf_writepage, ++ .set_page_dirty = __set_page_dirty_nobuffers, ++ .write_begin = simple_write_begin, ++ .write_end = vboxsf_write_end, ++}; ++ ++static const char *vboxsf_get_link(struct dentry *dentry, struct inode *inode, ++ struct delayed_call *done) ++{ ++ struct vboxsf_sbi *sbi = VBOXSF_SBI(inode->i_sb); ++ struct shfl_string *path; ++ char *link; ++ int err; ++ ++ if (!dentry) ++ return ERR_PTR(-ECHILD); ++ ++ path = vboxsf_path_from_dentry(sbi, dentry); ++ if (IS_ERR(path)) ++ return (char *)path; ++ ++ link = kzalloc(PATH_MAX, GFP_KERNEL); ++ if (!link) { ++ __putname(path); ++ return ERR_PTR(-ENOMEM); ++ } ++ ++ err = vboxsf_readlink(sbi->root, path, PATH_MAX, link); ++ __putname(path); ++ if (err) { ++ kfree(link); ++ return ERR_PTR(err); ++ } ++ ++ set_delayed_call(done, kfree_link, link); ++ return link; ++} ++ ++const struct inode_operations vboxsf_lnk_iops = { ++ .get_link = vboxsf_get_link ++}; +diff --git a/drivers/staging/vboxsf/shfl_hostintf.h b/drivers/staging/vboxsf/shfl_hostintf.h +new file mode 100644 +index 000000000000..aca829062c12 +--- /dev/null ++++ b/drivers/staging/vboxsf/shfl_hostintf.h +@@ -0,0 +1,901 @@ ++/* SPDX-License-Identifier: MIT */ ++/* ++ * VirtualBox Shared Folders: host interface definition. ++ * ++ * Copyright (C) 2006-2018 Oracle Corporation ++ */ ++ ++#ifndef SHFL_HOSTINTF_H ++#define SHFL_HOSTINTF_H ++ ++#include ++ ++/* The max in/out buffer size for a FN_READ or FN_WRITE call */ ++#define SHFL_MAX_RW_COUNT (16 * SZ_1M) ++ ++/* ++ * Structures shared between guest and the service ++ * can be relocated and use offsets to point to variable ++ * length parts. ++ * ++ * Shared folders protocol works with handles. ++ * Before doing any action on a file system object, ++ * one have to obtain the object handle via a SHFL_FN_CREATE ++ * request. A handle must be closed with SHFL_FN_CLOSE. ++ */ ++ ++enum { ++ SHFL_FN_QUERY_MAPPINGS = 1, /* Query mappings changes. */ ++ SHFL_FN_QUERY_MAP_NAME = 2, /* Query map name. */ ++ SHFL_FN_CREATE = 3, /* Open/create object. */ ++ SHFL_FN_CLOSE = 4, /* Close object handle. */ ++ SHFL_FN_READ = 5, /* Read object content. */ ++ SHFL_FN_WRITE = 6, /* Write new object content. */ ++ SHFL_FN_LOCK = 7, /* Lock/unlock a range in the object. */ ++ SHFL_FN_LIST = 8, /* List object content. */ ++ SHFL_FN_INFORMATION = 9, /* Query/set object information. */ ++ /* Note function number 10 is not used! */ ++ SHFL_FN_REMOVE = 11, /* Remove object */ ++ SHFL_FN_MAP_FOLDER_OLD = 12, /* Map folder (legacy) */ ++ SHFL_FN_UNMAP_FOLDER = 13, /* Unmap folder */ ++ SHFL_FN_RENAME = 14, /* Rename object */ ++ SHFL_FN_FLUSH = 15, /* Flush file */ ++ SHFL_FN_SET_UTF8 = 16, /* Select UTF8 filename encoding */ ++ SHFL_FN_MAP_FOLDER = 17, /* Map folder */ ++ SHFL_FN_READLINK = 18, /* Read symlink dest (as of VBox 4.0) */ ++ SHFL_FN_SYMLINK = 19, /* Create symlink (as of VBox 4.0) */ ++ SHFL_FN_SET_SYMLINKS = 20, /* Ask host to show symlinks (4.0+) */ ++}; ++ ++/* Root handles for a mapping are of type u32, Root handles are unique. */ ++#define SHFL_ROOT_NIL UINT_MAX ++ ++/* Shared folders handle for an opened object are of type u64. */ ++#define SHFL_HANDLE_NIL ULLONG_MAX ++ ++/* Hardcoded maximum length (in chars) of a shared folder name. */ ++#define SHFL_MAX_LEN (256) ++/* Hardcoded maximum number of shared folder mapping available to the guest. */ ++#define SHFL_MAX_MAPPINGS (64) ++ ++/** Shared folder string buffer structure. */ ++struct shfl_string { ++ /** Allocated size of the string member in bytes. */ ++ u16 size; ++ ++ /** Length of string without trailing nul in bytes. */ ++ u16 length; ++ ++ /** UTF-8 or UTF-16 string. Nul terminated. */ ++ union { ++ u8 utf8[2]; ++ u16 utf16[1]; ++ u16 ucs2[1]; /* misnomer, use utf16. */ ++ } string; ++}; ++VMMDEV_ASSERT_SIZE(shfl_string, 6); ++ ++/* The size of shfl_string w/o the string part. */ ++#define SHFLSTRING_HEADER_SIZE 4 ++ ++/* Calculate size of the string. */ ++static inline u32 shfl_string_buf_size(const struct shfl_string *string) ++{ ++ return string ? SHFLSTRING_HEADER_SIZE + string->size : 0; ++} ++ ++/* Set user id on execution (S_ISUID). */ ++#define SHFL_UNIX_ISUID 0004000U ++/* Set group id on execution (S_ISGID). */ ++#define SHFL_UNIX_ISGID 0002000U ++/* Sticky bit (S_ISVTX / S_ISTXT). */ ++#define SHFL_UNIX_ISTXT 0001000U ++ ++/* Owner readable (S_IRUSR). */ ++#define SHFL_UNIX_IRUSR 0000400U ++/* Owner writable (S_IWUSR). */ ++#define SHFL_UNIX_IWUSR 0000200U ++/* Owner executable (S_IXUSR). */ ++#define SHFL_UNIX_IXUSR 0000100U ++ ++/* Group readable (S_IRGRP). */ ++#define SHFL_UNIX_IRGRP 0000040U ++/* Group writable (S_IWGRP). */ ++#define SHFL_UNIX_IWGRP 0000020U ++/* Group executable (S_IXGRP). */ ++#define SHFL_UNIX_IXGRP 0000010U ++ ++/* Other readable (S_IROTH). */ ++#define SHFL_UNIX_IROTH 0000004U ++/* Other writable (S_IWOTH). */ ++#define SHFL_UNIX_IWOTH 0000002U ++/* Other executable (S_IXOTH). */ ++#define SHFL_UNIX_IXOTH 0000001U ++ ++/* Named pipe (fifo) (S_IFIFO). */ ++#define SHFL_TYPE_FIFO 0010000U ++/* Character device (S_IFCHR). */ ++#define SHFL_TYPE_DEV_CHAR 0020000U ++/* Directory (S_IFDIR). */ ++#define SHFL_TYPE_DIRECTORY 0040000U ++/* Block device (S_IFBLK). */ ++#define SHFL_TYPE_DEV_BLOCK 0060000U ++/* Regular file (S_IFREG). */ ++#define SHFL_TYPE_FILE 0100000U ++/* Symbolic link (S_IFLNK). */ ++#define SHFL_TYPE_SYMLINK 0120000U ++/* Socket (S_IFSOCK). */ ++#define SHFL_TYPE_SOCKET 0140000U ++/* Whiteout (S_IFWHT). */ ++#define SHFL_TYPE_WHITEOUT 0160000U ++/* Type mask (S_IFMT). */ ++#define SHFL_TYPE_MASK 0170000U ++ ++/* Checks the mode flags indicate a directory (S_ISDIR). */ ++#define SHFL_IS_DIRECTORY(m) (((m) & SHFL_TYPE_MASK) == SHFL_TYPE_DIRECTORY) ++/* Checks the mode flags indicate a symbolic link (S_ISLNK). */ ++#define SHFL_IS_SYMLINK(m) (((m) & SHFL_TYPE_MASK) == SHFL_TYPE_SYMLINK) ++ ++/** The available additional information in a shfl_fsobjattr object. */ ++enum shfl_fsobjattr_add { ++ /** No additional information is available / requested. */ ++ SHFLFSOBJATTRADD_NOTHING = 1, ++ /** ++ * The additional unix attributes (shfl_fsobjattr::u::unix_attr) are ++ * available / requested. ++ */ ++ SHFLFSOBJATTRADD_UNIX, ++ /** ++ * The additional extended attribute size (shfl_fsobjattr::u::size) is ++ * available / requested. ++ */ ++ SHFLFSOBJATTRADD_EASIZE, ++ /** ++ * The last valid item (inclusive). ++ * The valid range is SHFLFSOBJATTRADD_NOTHING thru ++ * SHFLFSOBJATTRADD_LAST. ++ */ ++ SHFLFSOBJATTRADD_LAST = SHFLFSOBJATTRADD_EASIZE, ++ ++ /** The usual 32-bit hack. */ ++ SHFLFSOBJATTRADD_32BIT_SIZE_HACK = 0x7fffffff ++}; ++ ++/** ++ * Additional unix Attributes, these are available when ++ * shfl_fsobjattr.additional == SHFLFSOBJATTRADD_UNIX. ++ */ ++struct shfl_fsobjattr_unix { ++ /** ++ * The user owning the filesystem object (st_uid). ++ * This field is ~0U if not supported. ++ */ ++ u32 uid; ++ ++ /** ++ * The group the filesystem object is assigned (st_gid). ++ * This field is ~0U if not supported. ++ */ ++ u32 gid; ++ ++ /** ++ * Number of hard links to this filesystem object (st_nlink). ++ * This field is 1 if the filesystem doesn't support hardlinking or ++ * the information isn't available. ++ */ ++ u32 hardlinks; ++ ++ /** ++ * The device number of the device which this filesystem object resides ++ * on (st_dev). This field is 0 if this information is not available. ++ */ ++ u32 inode_id_device; ++ ++ /** ++ * The unique identifier (within the filesystem) of this filesystem ++ * object (st_ino). Together with inode_id_device, this field can be ++ * used as a OS wide unique id, when both their values are not 0. ++ * This field is 0 if the information is not available. ++ */ ++ u64 inode_id; ++ ++ /** ++ * User flags (st_flags). ++ * This field is 0 if this information is not available. ++ */ ++ u32 flags; ++ ++ /** ++ * The current generation number (st_gen). ++ * This field is 0 if this information is not available. ++ */ ++ u32 generation_id; ++ ++ /** ++ * The device number of a char. or block device type object (st_rdev). ++ * This field is 0 if the file isn't a char. or block device or when ++ * the OS doesn't use the major+minor device idenfication scheme. ++ */ ++ u32 device; ++} __packed; ++ ++/** Extended attribute size. */ ++struct shfl_fsobjattr_easize { ++ /** Size of EAs. */ ++ s64 cb; ++} __packed; ++ ++/** Shared folder filesystem object attributes. */ ++struct shfl_fsobjattr { ++ /** Mode flags (st_mode). SHFL_UNIX_*, SHFL_TYPE_*, and SHFL_DOS_*. */ ++ u32 mode; ++ ++ /** The additional attributes available. */ ++ enum shfl_fsobjattr_add additional; ++ ++ /** ++ * Additional attributes. ++ * ++ * Unless explicitly specified to an API, the API can provide additional ++ * data as it is provided by the underlying OS. ++ */ ++ union { ++ struct shfl_fsobjattr_unix unix_attr; ++ struct shfl_fsobjattr_easize size; ++ } __packed u; ++} __packed; ++VMMDEV_ASSERT_SIZE(shfl_fsobjattr, 44); ++ ++struct shfl_timespec { ++ s64 ns_relative_to_unix_epoch; ++}; ++ ++/** Filesystem object information structure. */ ++struct shfl_fsobjinfo { ++ /** ++ * Logical size (st_size). ++ * For normal files this is the size of the file. ++ * For symbolic links, this is the length of the path name contained ++ * in the symbolic link. ++ * For other objects this fields needs to be specified. ++ */ ++ s64 size; ++ ++ /** Disk allocation size (st_blocks * DEV_BSIZE). */ ++ s64 allocated; ++ ++ /** Time of last access (st_atime). */ ++ struct shfl_timespec access_time; ++ ++ /** Time of last data modification (st_mtime). */ ++ struct shfl_timespec modification_time; ++ ++ /** ++ * Time of last status change (st_ctime). ++ * If not available this is set to modification_time. ++ */ ++ struct shfl_timespec change_time; ++ ++ /** ++ * Time of file birth (st_birthtime). ++ * If not available this is set to change_time. ++ */ ++ struct shfl_timespec birth_time; ++ ++ /** Attributes. */ ++ struct shfl_fsobjattr attr; ++ ++} __packed; ++VMMDEV_ASSERT_SIZE(shfl_fsobjinfo, 92); ++ ++/** ++ * result of an open/create request. ++ * Along with handle value the result code ++ * identifies what has happened while ++ * trying to open the object. ++ */ ++enum shfl_create_result { ++ SHFL_NO_RESULT, ++ /** Specified path does not exist. */ ++ SHFL_PATH_NOT_FOUND, ++ /** Path to file exists, but the last component does not. */ ++ SHFL_FILE_NOT_FOUND, ++ /** File already exists and either has been opened or not. */ ++ SHFL_FILE_EXISTS, ++ /** New file was created. */ ++ SHFL_FILE_CREATED, ++ /** Existing file was replaced or overwritten. */ ++ SHFL_FILE_REPLACED ++}; ++ ++/* No flags. Initialization value. */ ++#define SHFL_CF_NONE (0x00000000) ++ ++/* ++ * Only lookup the object, do not return a handle. When this is set all other ++ * flags are ignored. ++ */ ++#define SHFL_CF_LOOKUP (0x00000001) ++ ++/* ++ * Open parent directory of specified object. ++ * Useful for the corresponding Windows FSD flag ++ * and for opening paths like \\dir\\*.* to search the 'dir'. ++ */ ++#define SHFL_CF_OPEN_TARGET_DIRECTORY (0x00000002) ++ ++/* Create/open a directory. */ ++#define SHFL_CF_DIRECTORY (0x00000004) ++ ++/* ++ * Open/create action to do if object exists ++ * and if the object does not exists. ++ * REPLACE file means atomically DELETE and CREATE. ++ * OVERWRITE file means truncating the file to 0 and ++ * setting new size. ++ * When opening an existing directory REPLACE and OVERWRITE ++ * actions are considered invalid, and cause returning ++ * FILE_EXISTS with NIL handle. ++ */ ++#define SHFL_CF_ACT_MASK_IF_EXISTS (0x000000f0) ++#define SHFL_CF_ACT_MASK_IF_NEW (0x00000f00) ++ ++/* What to do if object exists. */ ++#define SHFL_CF_ACT_OPEN_IF_EXISTS (0x00000000) ++#define SHFL_CF_ACT_FAIL_IF_EXISTS (0x00000010) ++#define SHFL_CF_ACT_REPLACE_IF_EXISTS (0x00000020) ++#define SHFL_CF_ACT_OVERWRITE_IF_EXISTS (0x00000030) ++ ++/* What to do if object does not exist. */ ++#define SHFL_CF_ACT_CREATE_IF_NEW (0x00000000) ++#define SHFL_CF_ACT_FAIL_IF_NEW (0x00000100) ++ ++/* Read/write requested access for the object. */ ++#define SHFL_CF_ACCESS_MASK_RW (0x00003000) ++ ++/* No access requested. */ ++#define SHFL_CF_ACCESS_NONE (0x00000000) ++/* Read access requested. */ ++#define SHFL_CF_ACCESS_READ (0x00001000) ++/* Write access requested. */ ++#define SHFL_CF_ACCESS_WRITE (0x00002000) ++/* Read/Write access requested. */ ++#define SHFL_CF_ACCESS_READWRITE (0x00003000) ++ ++/* Requested share access for the object. */ ++#define SHFL_CF_ACCESS_MASK_DENY (0x0000c000) ++ ++/* Allow any access. */ ++#define SHFL_CF_ACCESS_DENYNONE (0x00000000) ++/* Do not allow read. */ ++#define SHFL_CF_ACCESS_DENYREAD (0x00004000) ++/* Do not allow write. */ ++#define SHFL_CF_ACCESS_DENYWRITE (0x00008000) ++/* Do not allow access. */ ++#define SHFL_CF_ACCESS_DENYALL (0x0000c000) ++ ++/* Requested access to attributes of the object. */ ++#define SHFL_CF_ACCESS_MASK_ATTR (0x00030000) ++ ++/* No access requested. */ ++#define SHFL_CF_ACCESS_ATTR_NONE (0x00000000) ++/* Read access requested. */ ++#define SHFL_CF_ACCESS_ATTR_READ (0x00010000) ++/* Write access requested. */ ++#define SHFL_CF_ACCESS_ATTR_WRITE (0x00020000) ++/* Read/Write access requested. */ ++#define SHFL_CF_ACCESS_ATTR_READWRITE (0x00030000) ++ ++/* ++ * The file is opened in append mode. ++ * Ignored if SHFL_CF_ACCESS_WRITE is not set. ++ */ ++#define SHFL_CF_ACCESS_APPEND (0x00040000) ++ ++/** Create parameters buffer struct for SHFL_FN_CREATE call */ ++struct shfl_createparms { ++ /** Returned handle of opened object. */ ++ u64 handle; ++ ++ /** Returned result of the operation */ ++ enum shfl_create_result result; ++ ++ /** SHFL_CF_* */ ++ u32 create_flags; ++ ++ /** ++ * Attributes of object to create and ++ * returned actual attributes of opened/created object. ++ */ ++ struct shfl_fsobjinfo info; ++} __packed; ++ ++/** Shared Folder directory information */ ++struct shfl_dirinfo { ++ /** Full information about the object. */ ++ struct shfl_fsobjinfo info; ++ /** ++ * The length of the short field (number of UTF16 chars). ++ * It is 16-bit for reasons of alignment. ++ */ ++ u16 short_name_len; ++ /** ++ * The short name for 8.3 compatibility. ++ * Empty string if not available. ++ */ ++ u16 short_name[14]; ++ struct shfl_string name; ++}; ++ ++/** Shared folder filesystem properties. */ ++struct shfl_fsproperties { ++ /** ++ * The maximum size of a filesystem object name. ++ * This does not include the '\\0'. ++ */ ++ u32 max_component_len; ++ ++ /** ++ * True if the filesystem is remote. ++ * False if the filesystem is local. ++ */ ++ bool remote; ++ ++ /** ++ * True if the filesystem is case sensitive. ++ * False if the filesystem is case insensitive. ++ */ ++ bool case_sensitive; ++ ++ /** ++ * True if the filesystem is mounted read only. ++ * False if the filesystem is mounted read write. ++ */ ++ bool read_only; ++ ++ /** ++ * True if the filesystem can encode unicode object names. ++ * False if it can't. ++ */ ++ bool supports_unicode; ++ ++ /** ++ * True if the filesystem is compresses. ++ * False if it isn't or we don't know. ++ */ ++ bool compressed; ++ ++ /** ++ * True if the filesystem compresses of individual files. ++ * False if it doesn't or we don't know. ++ */ ++ bool file_compression; ++}; ++VMMDEV_ASSERT_SIZE(shfl_fsproperties, 12); ++ ++struct shfl_volinfo { ++ s64 total_allocation_bytes; ++ s64 available_allocation_bytes; ++ u32 bytes_per_allocation_unit; ++ u32 bytes_per_sector; ++ u32 serial; ++ struct shfl_fsproperties properties; ++}; ++ ++ ++/** SHFL_FN_MAP_FOLDER Parameters structure. */ ++struct shfl_map_folder { ++ /** ++ * pointer, in: ++ * Points to struct shfl_string buffer. ++ */ ++ struct vmmdev_hgcm_function_parameter path; ++ ++ /** ++ * pointer, out: SHFLROOT (u32) ++ * Root handle of the mapping which name is queried. ++ */ ++ struct vmmdev_hgcm_function_parameter root; ++ ++ /** ++ * pointer, in: UTF16 ++ * Path delimiter ++ */ ++ struct vmmdev_hgcm_function_parameter delimiter; ++ ++ /** ++ * pointer, in: SHFLROOT (u32) ++ * Case senstive flag ++ */ ++ struct vmmdev_hgcm_function_parameter case_sensitive; ++ ++}; ++ ++/* Number of parameters */ ++#define SHFL_CPARMS_MAP_FOLDER (4) ++ ++ ++/** SHFL_FN_UNMAP_FOLDER Parameters structure. */ ++struct shfl_unmap_folder { ++ /** ++ * pointer, in: SHFLROOT (u32) ++ * Root handle of the mapping which name is queried. ++ */ ++ struct vmmdev_hgcm_function_parameter root; ++ ++}; ++ ++/* Number of parameters */ ++#define SHFL_CPARMS_UNMAP_FOLDER (1) ++ ++ ++/** SHFL_FN_CREATE Parameters structure. */ ++struct shfl_create { ++ /** ++ * pointer, in: SHFLROOT (u32) ++ * Root handle of the mapping which name is queried. ++ */ ++ struct vmmdev_hgcm_function_parameter root; ++ ++ /** ++ * pointer, in: ++ * Points to struct shfl_string buffer. ++ */ ++ struct vmmdev_hgcm_function_parameter path; ++ ++ /** ++ * pointer, in/out: ++ * Points to struct shfl_createparms buffer. ++ */ ++ struct vmmdev_hgcm_function_parameter parms; ++ ++}; ++ ++/* Number of parameters */ ++#define SHFL_CPARMS_CREATE (3) ++ ++ ++/** SHFL_FN_CLOSE Parameters structure. */ ++struct shfl_close { ++ /** ++ * pointer, in: SHFLROOT (u32) ++ * Root handle of the mapping which name is queried. ++ */ ++ struct vmmdev_hgcm_function_parameter root; ++ ++ /** ++ * value64, in: ++ * SHFLHANDLE (u64) of object to close. ++ */ ++ struct vmmdev_hgcm_function_parameter handle; ++ ++}; ++ ++/* Number of parameters */ ++#define SHFL_CPARMS_CLOSE (2) ++ ++ ++/** SHFL_FN_READ Parameters structure. */ ++struct shfl_read { ++ /** ++ * pointer, in: SHFLROOT (u32) ++ * Root handle of the mapping which name is queried. ++ */ ++ struct vmmdev_hgcm_function_parameter root; ++ ++ /** ++ * value64, in: ++ * SHFLHANDLE (u64) of object to read from. ++ */ ++ struct vmmdev_hgcm_function_parameter handle; ++ ++ /** ++ * value64, in: ++ * Offset to read from. ++ */ ++ struct vmmdev_hgcm_function_parameter offset; ++ ++ /** ++ * value64, in/out: ++ * Bytes to read/How many were read. ++ */ ++ struct vmmdev_hgcm_function_parameter cb; ++ ++ /** ++ * pointer, out: ++ * Buffer to place data to. ++ */ ++ struct vmmdev_hgcm_function_parameter buffer; ++ ++}; ++ ++/* Number of parameters */ ++#define SHFL_CPARMS_READ (5) ++ ++ ++/** SHFL_FN_WRITE Parameters structure. */ ++struct shfl_write { ++ /** ++ * pointer, in: SHFLROOT (u32) ++ * Root handle of the mapping which name is queried. ++ */ ++ struct vmmdev_hgcm_function_parameter root; ++ ++ /** ++ * value64, in: ++ * SHFLHANDLE (u64) of object to write to. ++ */ ++ struct vmmdev_hgcm_function_parameter handle; ++ ++ /** ++ * value64, in: ++ * Offset to write to. ++ */ ++ struct vmmdev_hgcm_function_parameter offset; ++ ++ /** ++ * value64, in/out: ++ * Bytes to write/How many were written. ++ */ ++ struct vmmdev_hgcm_function_parameter cb; ++ ++ /** ++ * pointer, in: ++ * Data to write. ++ */ ++ struct vmmdev_hgcm_function_parameter buffer; ++ ++}; ++ ++/* Number of parameters */ ++#define SHFL_CPARMS_WRITE (5) ++ ++ ++/* ++ * SHFL_FN_LIST ++ * Listing information includes variable length RTDIRENTRY[EX] structures. ++ */ ++ ++#define SHFL_LIST_NONE 0 ++#define SHFL_LIST_RETURN_ONE 1 ++ ++/** SHFL_FN_LIST Parameters structure. */ ++struct shfl_list { ++ /** ++ * pointer, in: SHFLROOT (u32) ++ * Root handle of the mapping which name is queried. ++ */ ++ struct vmmdev_hgcm_function_parameter root; ++ ++ /** ++ * value64, in: ++ * SHFLHANDLE (u64) of object to be listed. ++ */ ++ struct vmmdev_hgcm_function_parameter handle; ++ ++ /** ++ * value32, in: ++ * List flags SHFL_LIST_*. ++ */ ++ struct vmmdev_hgcm_function_parameter flags; ++ ++ /** ++ * value32, in/out: ++ * Bytes to be used for listing information/How many bytes were used. ++ */ ++ struct vmmdev_hgcm_function_parameter cb; ++ ++ /** ++ * pointer, in/optional ++ * Points to struct shfl_string buffer that specifies a search path. ++ */ ++ struct vmmdev_hgcm_function_parameter path; ++ ++ /** ++ * pointer, out: ++ * Buffer to place listing information to. (struct shfl_dirinfo) ++ */ ++ struct vmmdev_hgcm_function_parameter buffer; ++ ++ /** ++ * value32, in/out: ++ * Indicates a key where the listing must be resumed. ++ * in: 0 means start from begin of object. ++ * out: 0 means listing completed. ++ */ ++ struct vmmdev_hgcm_function_parameter resume_point; ++ ++ /** ++ * pointer, out: ++ * Number of files returned ++ */ ++ struct vmmdev_hgcm_function_parameter file_count; ++}; ++ ++/* Number of parameters */ ++#define SHFL_CPARMS_LIST (8) ++ ++ ++/** SHFL_FN_READLINK Parameters structure. */ ++struct shfl_readLink { ++ /** ++ * pointer, in: SHFLROOT (u32) ++ * Root handle of the mapping which name is queried. ++ */ ++ struct vmmdev_hgcm_function_parameter root; ++ ++ /** ++ * pointer, in: ++ * Points to struct shfl_string buffer. ++ */ ++ struct vmmdev_hgcm_function_parameter path; ++ ++ /** ++ * pointer, out: ++ * Buffer to place data to. ++ */ ++ struct vmmdev_hgcm_function_parameter buffer; ++ ++}; ++ ++/* Number of parameters */ ++#define SHFL_CPARMS_READLINK (3) ++ ++ ++/* SHFL_FN_INFORMATION */ ++ ++/* Mask of Set/Get bit. */ ++#define SHFL_INFO_MODE_MASK (0x1) ++/* Get information */ ++#define SHFL_INFO_GET (0x0) ++/* Set information */ ++#define SHFL_INFO_SET (0x1) ++ ++/* Get name of the object. */ ++#define SHFL_INFO_NAME (0x2) ++/* Set size of object (extend/trucate); only applies to file objects */ ++#define SHFL_INFO_SIZE (0x4) ++/* Get/Set file object info. */ ++#define SHFL_INFO_FILE (0x8) ++/* Get volume information. */ ++#define SHFL_INFO_VOLUME (0x10) ++ ++/** SHFL_FN_INFORMATION Parameters structure. */ ++struct shfl_information { ++ /** ++ * pointer, in: SHFLROOT (u32) ++ * Root handle of the mapping which name is queried. ++ */ ++ struct vmmdev_hgcm_function_parameter root; ++ ++ /** ++ * value64, in: ++ * SHFLHANDLE (u64) of object to be listed. ++ */ ++ struct vmmdev_hgcm_function_parameter handle; ++ ++ /** ++ * value32, in: ++ * SHFL_INFO_* ++ */ ++ struct vmmdev_hgcm_function_parameter flags; ++ ++ /** ++ * value32, in/out: ++ * Bytes to be used for information/How many bytes were used. ++ */ ++ struct vmmdev_hgcm_function_parameter cb; ++ ++ /** ++ * pointer, in/out: ++ * Information to be set/get (shfl_fsobjinfo or shfl_string). Do not ++ * forget to set the shfl_fsobjinfo::attr::additional for a get ++ * operation as well. ++ */ ++ struct vmmdev_hgcm_function_parameter info; ++ ++}; ++ ++/* Number of parameters */ ++#define SHFL_CPARMS_INFORMATION (5) ++ ++ ++/* SHFL_FN_REMOVE */ ++ ++#define SHFL_REMOVE_FILE (0x1) ++#define SHFL_REMOVE_DIR (0x2) ++#define SHFL_REMOVE_SYMLINK (0x4) ++ ++/** SHFL_FN_REMOVE Parameters structure. */ ++struct shfl_remove { ++ /** ++ * pointer, in: SHFLROOT (u32) ++ * Root handle of the mapping which name is queried. ++ */ ++ struct vmmdev_hgcm_function_parameter root; ++ ++ /** ++ * pointer, in: ++ * Points to struct shfl_string buffer. ++ */ ++ struct vmmdev_hgcm_function_parameter path; ++ ++ /** ++ * value32, in: ++ * remove flags (file/directory) ++ */ ++ struct vmmdev_hgcm_function_parameter flags; ++ ++}; ++ ++#define SHFL_CPARMS_REMOVE (3) ++ ++ ++/* SHFL_FN_RENAME */ ++ ++#define SHFL_RENAME_FILE (0x1) ++#define SHFL_RENAME_DIR (0x2) ++#define SHFL_RENAME_REPLACE_IF_EXISTS (0x4) ++ ++/** SHFL_FN_RENAME Parameters structure. */ ++struct shfl_rename { ++ /** ++ * pointer, in: SHFLROOT (u32) ++ * Root handle of the mapping which name is queried. ++ */ ++ struct vmmdev_hgcm_function_parameter root; ++ ++ /** ++ * pointer, in: ++ * Points to struct shfl_string src. ++ */ ++ struct vmmdev_hgcm_function_parameter src; ++ ++ /** ++ * pointer, in: ++ * Points to struct shfl_string dest. ++ */ ++ struct vmmdev_hgcm_function_parameter dest; ++ ++ /** ++ * value32, in: ++ * rename flags (file/directory) ++ */ ++ struct vmmdev_hgcm_function_parameter flags; ++ ++}; ++ ++#define SHFL_CPARMS_RENAME (4) ++ ++ ++/** SHFL_FN_SYMLINK Parameters structure. */ ++struct shfl_symlink { ++ /** ++ * pointer, in: SHFLROOT (u32) ++ * Root handle of the mapping which name is queried. ++ */ ++ struct vmmdev_hgcm_function_parameter root; ++ ++ /** ++ * pointer, in: ++ * Points to struct shfl_string of path for the new symlink. ++ */ ++ struct vmmdev_hgcm_function_parameter new_path; ++ ++ /** ++ * pointer, in: ++ * Points to struct shfl_string of destination for symlink. ++ */ ++ struct vmmdev_hgcm_function_parameter old_path; ++ ++ /** ++ * pointer, out: ++ * Information about created symlink. ++ */ ++ struct vmmdev_hgcm_function_parameter info; ++ ++}; ++ ++#define SHFL_CPARMS_SYMLINK (4) ++ ++#endif +diff --git a/drivers/staging/vboxsf/super.c b/drivers/staging/vboxsf/super.c +new file mode 100644 +index 000000000000..3913ffafa83b +--- /dev/null ++++ b/drivers/staging/vboxsf/super.c +@@ -0,0 +1,499 @@ ++// SPDX-License-Identifier: MIT ++/* ++ * VirtualBox Guest Shared Folders support: Virtual File System. ++ * ++ * Module initialization/finalization ++ * File system registration/deregistration ++ * Superblock reading ++ * Few utility functions ++ * ++ * Copyright (C) 2006-2018 Oracle Corporation ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "vfsmod.h" ++ ++#define VBOXSF_SUPER_MAGIC 0x786f4256 /* 'VBox' little endian */ ++ ++#define VBSF_MOUNT_SIGNATURE_BYTE_0 ('\000') ++#define VBSF_MOUNT_SIGNATURE_BYTE_1 ('\377') ++#define VBSF_MOUNT_SIGNATURE_BYTE_2 ('\376') ++#define VBSF_MOUNT_SIGNATURE_BYTE_3 ('\375') ++ ++static int follow_symlinks; ++module_param(follow_symlinks, int, 0444); ++MODULE_PARM_DESC(follow_symlinks, ++ "Let host resolve symlinks rather than showing them"); ++ ++static DEFINE_IDA(vboxsf_bdi_ida); ++static DEFINE_MUTEX(vboxsf_setup_mutex); ++static bool vboxsf_setup_done; ++static struct super_operations vboxsf_super_ops; /* forward declaration */ ++static struct kmem_cache *vboxsf_inode_cachep; ++ ++static char * const vboxsf_default_nls = CONFIG_NLS_DEFAULT; ++ ++enum { opt_nls, opt_uid, opt_gid, opt_ttl, opt_dmode, opt_fmode, ++ opt_dmask, opt_fmask }; ++ ++static const struct fs_parameter_spec vboxsf_param_specs[] = { ++ fsparam_string ("nls", opt_nls), ++ fsparam_u32 ("uid", opt_uid), ++ fsparam_u32 ("gid", opt_gid), ++ fsparam_u32 ("ttl", opt_ttl), ++ fsparam_u32oct ("dmode", opt_dmode), ++ fsparam_u32oct ("fmode", opt_fmode), ++ fsparam_u32oct ("dmask", opt_dmask), ++ fsparam_u32oct ("fmask", opt_fmask), ++ {} ++}; ++ ++static const struct fs_parameter_description vboxsf_fs_parameters = { ++ .name = "vboxsf", ++ .specs = vboxsf_param_specs, ++}; ++ ++static int vboxsf_parse_param(struct fs_context *fc, struct fs_parameter *param) ++{ ++ struct vboxsf_fs_context *ctx = fc->fs_private; ++ struct fs_parse_result result; ++ kuid_t uid; ++ kgid_t gid; ++ int opt; ++ ++ opt = fs_parse(fc, &vboxsf_fs_parameters, param, &result); ++ if (opt < 0) ++ return opt; ++ ++ switch (opt) { ++ case opt_nls: ++ if (fc->purpose != FS_CONTEXT_FOR_MOUNT) { ++ vbg_err("vboxsf: Cannot reconfigure nls option\n"); ++ return -EINVAL; ++ } ++ ctx->nls_name = param->string; ++ param->string = NULL; ++ break; ++ case opt_uid: ++ uid = make_kuid(current_user_ns(), result.uint_32); ++ if (!uid_valid(uid)) ++ return -EINVAL; ++ ctx->o.uid = uid; ++ break; ++ case opt_gid: ++ gid = make_kgid(current_user_ns(), result.uint_32); ++ if (!gid_valid(gid)) ++ return -EINVAL; ++ ctx->o.gid = gid; ++ break; ++ case opt_ttl: ++ ctx->o.ttl = msecs_to_jiffies(result.uint_32); ++ break; ++ case opt_dmode: ++ if (result.uint_32 & ~0777) ++ return -EINVAL; ++ ctx->o.dmode = result.uint_32; ++ ctx->o.dmode_set = true; ++ break; ++ case opt_fmode: ++ if (result.uint_32 & ~0777) ++ return -EINVAL; ++ ctx->o.fmode = result.uint_32; ++ ctx->o.fmode_set = true; ++ break; ++ case opt_dmask: ++ if (result.uint_32 & ~07777) ++ return -EINVAL; ++ ctx->o.dmask = result.uint_32; ++ break; ++ case opt_fmask: ++ if (result.uint_32 & ~07777) ++ return -EINVAL; ++ ctx->o.fmask = result.uint_32; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int vboxsf_fill_super(struct super_block *sb, struct fs_context *fc) ++{ ++ struct vboxsf_fs_context *ctx = fc->fs_private; ++ struct shfl_string *folder_name, root_path; ++ struct vboxsf_sbi *sbi; ++ struct dentry *droot; ++ struct inode *iroot; ++ char *nls_name; ++ size_t size; ++ int err; ++ ++ if (!fc->source) ++ return -EINVAL; ++ ++ sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); ++ if (!sbi) ++ return -ENOMEM; ++ ++ sbi->o = ctx->o; ++ idr_init(&sbi->ino_idr); ++ spin_lock_init(&sbi->ino_idr_lock); ++ sbi->next_generation = 1; ++ sbi->bdi_id = -1; ++ ++ /* Load nls if not utf8 */ ++ nls_name = ctx->nls_name ? ctx->nls_name : vboxsf_default_nls; ++ if (strcmp(nls_name, "utf8") != 0) { ++ if (nls_name == vboxsf_default_nls) ++ sbi->nls = load_nls_default(); ++ else ++ sbi->nls = load_nls(nls_name); ++ ++ if (!sbi->nls) { ++ vbg_err("vboxsf: Count not load '%s' nls\n", nls_name); ++ err = -EINVAL; ++ goto fail_free; ++ } ++ } ++ ++ sbi->bdi_id = ida_simple_get(&vboxsf_bdi_ida, 0, 0, GFP_KERNEL); ++ if (sbi->bdi_id < 0) { ++ err = sbi->bdi_id; ++ goto fail_free; ++ } ++ ++ err = super_setup_bdi_name(sb, "vboxsf-%s.%d", fc->source, sbi->bdi_id); ++ if (err) ++ goto fail_free; ++ ++ /* Turn source into a shfl_string and map the folder */ ++ size = strlen(fc->source) + 1; ++ folder_name = kmalloc(SHFLSTRING_HEADER_SIZE + size, GFP_KERNEL); ++ if (!folder_name) ++ goto fail_free; ++ folder_name->size = size; ++ folder_name->length = size - 1; ++ strlcpy(folder_name->string.utf8, fc->source, size); ++ err = vboxsf_map_folder(folder_name, &sbi->root); ++ kfree(folder_name); ++ if (err) { ++ vbg_err("vboxsf: Host rejected mount of '%s' with error %d\n", ++ fc->source, err); ++ goto fail_free; ++ } ++ ++ root_path.length = 1; ++ root_path.size = 2; ++ root_path.string.utf8[0] = '/'; ++ root_path.string.utf8[1] = 0; ++ err = vboxsf_stat(sbi, &root_path, &sbi->root_info); ++ if (err) ++ goto fail_unmap; ++ ++ sb->s_magic = VBOXSF_SUPER_MAGIC; ++ sb->s_blocksize = 1024; ++ sb->s_maxbytes = MAX_LFS_FILESIZE; ++ sb->s_op = &vboxsf_super_ops; ++ sb->s_d_op = &vboxsf_dentry_ops; ++ ++ iroot = iget_locked(sb, 0); ++ if (!iroot) { ++ err = -ENOMEM; ++ goto fail_unmap; ++ } ++ vboxsf_init_inode(sbi, iroot, &sbi->root_info); ++ unlock_new_inode(iroot); ++ ++ droot = d_make_root(iroot); ++ if (!droot) { ++ err = -ENOMEM; ++ goto fail_unmap; ++ } ++ ++ sb->s_root = droot; ++ sb->s_fs_info = sbi; ++ return 0; ++ ++fail_unmap: ++ vboxsf_unmap_folder(sbi->root); ++fail_free: ++ if (sbi->bdi_id >= 0) ++ ida_simple_remove(&vboxsf_bdi_ida, sbi->bdi_id); ++ if (sbi->nls) ++ unload_nls(sbi->nls); ++ idr_destroy(&sbi->ino_idr); ++ kfree(sbi); ++ return err; ++} ++ ++static void vboxsf_inode_init_once(void *data) ++{ ++ struct vboxsf_inode *sf_i = data; ++ ++ mutex_init(&sf_i->handle_list_mutex); ++ inode_init_once(&sf_i->vfs_inode); ++} ++ ++static struct inode *vboxsf_alloc_inode(struct super_block *sb) ++{ ++ struct vboxsf_inode *sf_i; ++ ++ sf_i = kmem_cache_alloc(vboxsf_inode_cachep, GFP_NOFS); ++ if (!sf_i) ++ return NULL; ++ ++ sf_i->force_restat = 0; ++ INIT_LIST_HEAD(&sf_i->handle_list); ++ ++ return &sf_i->vfs_inode; ++} ++ ++static void vboxsf_free_inode(struct inode *inode) ++{ ++ struct vboxsf_sbi *sbi = VBOXSF_SBI(inode->i_sb); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&sbi->ino_idr_lock, flags); ++ idr_remove(&sbi->ino_idr, inode->i_ino); ++ spin_unlock_irqrestore(&sbi->ino_idr_lock, flags); ++ kmem_cache_free(vboxsf_inode_cachep, VBOXSF_I(inode)); ++} ++ ++static void vboxsf_put_super(struct super_block *sb) ++{ ++ struct vboxsf_sbi *sbi = VBOXSF_SBI(sb); ++ ++ vboxsf_unmap_folder(sbi->root); ++ if (sbi->bdi_id >= 0) ++ ida_simple_remove(&vboxsf_bdi_ida, sbi->bdi_id); ++ if (sbi->nls) ++ unload_nls(sbi->nls); ++ ++ /* ++ * vboxsf_free_inode uses the idr, make sure all delayed rcu free ++ * inodes are flushed. ++ */ ++ rcu_barrier(); ++ idr_destroy(&sbi->ino_idr); ++ kfree(sbi); ++} ++ ++static int vboxsf_statfs(struct dentry *dentry, struct kstatfs *stat) ++{ ++ struct super_block *sb = dentry->d_sb; ++ struct shfl_volinfo shfl_volinfo; ++ struct vboxsf_sbi *sbi; ++ u32 buf_len; ++ int err; ++ ++ sbi = VBOXSF_SBI(sb); ++ buf_len = sizeof(shfl_volinfo); ++ err = vboxsf_fsinfo(sbi->root, 0, SHFL_INFO_GET | SHFL_INFO_VOLUME, ++ &buf_len, &shfl_volinfo); ++ if (err) ++ return err; ++ ++ stat->f_type = VBOXSF_SUPER_MAGIC; ++ stat->f_bsize = shfl_volinfo.bytes_per_allocation_unit; ++ ++ do_div(shfl_volinfo.total_allocation_bytes, ++ shfl_volinfo.bytes_per_allocation_unit); ++ stat->f_blocks = shfl_volinfo.total_allocation_bytes; ++ ++ do_div(shfl_volinfo.available_allocation_bytes, ++ shfl_volinfo.bytes_per_allocation_unit); ++ stat->f_bfree = shfl_volinfo.available_allocation_bytes; ++ stat->f_bavail = shfl_volinfo.available_allocation_bytes; ++ ++ stat->f_files = 1000; ++ /* ++ * Don't return 0 here since the guest may then think that it is not ++ * possible to create any more files. ++ */ ++ stat->f_ffree = 1000000; ++ stat->f_fsid.val[0] = 0; ++ stat->f_fsid.val[1] = 0; ++ stat->f_namelen = 255; ++ return 0; ++} ++ ++static struct super_operations vboxsf_super_ops = { ++ .alloc_inode = vboxsf_alloc_inode, ++ .free_inode = vboxsf_free_inode, ++ .put_super = vboxsf_put_super, ++ .statfs = vboxsf_statfs, ++}; ++ ++static int vboxsf_setup(void) ++{ ++ int err; ++ ++ mutex_lock(&vboxsf_setup_mutex); ++ ++ if (vboxsf_setup_done) ++ goto success; ++ ++ vboxsf_inode_cachep = ++ kmem_cache_create("vboxsf_inode_cache", ++ sizeof(struct vboxsf_inode), 0, ++ (SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD | ++ SLAB_ACCOUNT), ++ vboxsf_inode_init_once); ++ if (!vboxsf_inode_cachep) { ++ err = -ENOMEM; ++ goto fail_nomem; ++ } ++ ++ err = vboxsf_connect(); ++ if (err) { ++ vbg_err("vboxsf: err %d connecting to guest PCI-device\n", err); ++ vbg_err("vboxsf: make sure you are inside a VirtualBox VM\n"); ++ vbg_err("vboxsf: and check dmesg for vboxguest errors\n"); ++ goto fail_free_cache; ++ } ++ ++ err = vboxsf_set_utf8(); ++ if (err) { ++ vbg_err("vboxsf_setutf8 error %d\n", err); ++ goto fail_disconnect; ++ } ++ ++ if (!follow_symlinks) { ++ err = vboxsf_set_symlinks(); ++ if (err) ++ vbg_warn("vboxsf: Unable to show symlinks: %d\n", err); ++ } ++ ++ vboxsf_setup_done = true; ++success: ++ mutex_unlock(&vboxsf_setup_mutex); ++ return 0; ++ ++fail_disconnect: ++ vboxsf_disconnect(); ++fail_free_cache: ++ kmem_cache_destroy(vboxsf_inode_cachep); ++fail_nomem: ++ mutex_unlock(&vboxsf_setup_mutex); ++ return err; ++} ++ ++static int vboxsf_parse_monolithic(struct fs_context *fc, void *data) ++{ ++ char *options = data; ++ ++ if (options && options[0] == VBSF_MOUNT_SIGNATURE_BYTE_0 && ++ options[1] == VBSF_MOUNT_SIGNATURE_BYTE_1 && ++ options[2] == VBSF_MOUNT_SIGNATURE_BYTE_2 && ++ options[3] == VBSF_MOUNT_SIGNATURE_BYTE_3) { ++ vbg_err("vboxsf: Old binary mount data not supported, remove obsolete mount.vboxsf and/or update your VBoxService.\n"); ++ return -EINVAL; ++ } ++ ++ return generic_parse_monolithic(fc, data); ++} ++ ++static int vboxsf_get_tree(struct fs_context *fc) ++{ ++ int err; ++ ++ err = vboxsf_setup(); ++ if (err) ++ return err; ++ ++ return vfs_get_super(fc, vfs_get_independent_super, vboxsf_fill_super); ++} ++ ++static int vboxsf_reconfigure(struct fs_context *fc) ++{ ++ struct vboxsf_sbi *sbi = VBOXSF_SBI(fc->root->d_sb); ++ struct vboxsf_fs_context *ctx = fc->fs_private; ++ struct inode *iroot; ++ ++ iroot = ilookup(fc->root->d_sb, 0); ++ if (!iroot) ++ return -ENOENT; ++ ++ /* Apply changed options to the root inode */ ++ sbi->o = ctx->o; ++ vboxsf_init_inode(sbi, iroot, &sbi->root_info); ++ ++ return 0; ++} ++ ++static void vboxsf_free_fc(struct fs_context *fc) ++{ ++ struct vboxsf_fs_context *ctx = fc->fs_private; ++ ++ kfree(ctx->nls_name); ++ kfree(ctx); ++} ++ ++static const struct fs_context_operations vboxsf_context_ops = { ++ .free = vboxsf_free_fc, ++ .parse_param = vboxsf_parse_param, ++ .parse_monolithic = vboxsf_parse_monolithic, ++ .get_tree = vboxsf_get_tree, ++ .reconfigure = vboxsf_reconfigure, ++}; ++ ++static int vboxsf_init_fs_context(struct fs_context *fc) ++{ ++ struct vboxsf_fs_context *ctx; ++ ++ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); ++ if (!ctx) ++ return -ENOMEM; ++ ++ current_uid_gid(&ctx->o.uid, &ctx->o.gid); ++ ++ fc->fs_private = ctx; ++ fc->ops = &vboxsf_context_ops; ++ return 0; ++} ++ ++static struct file_system_type vboxsf_fs_type = { ++ .owner = THIS_MODULE, ++ .name = "vboxsf", ++ .init_fs_context = vboxsf_init_fs_context, ++ .parameters = &vboxsf_fs_parameters, ++ .kill_sb = kill_anon_super ++}; ++ ++/* Module initialization/finalization handlers */ ++static int __init vboxsf_init(void) ++{ ++ return register_filesystem(&vboxsf_fs_type); ++} ++ ++static void __exit vboxsf_fini(void) ++{ ++ unregister_filesystem(&vboxsf_fs_type); ++ ++ mutex_lock(&vboxsf_setup_mutex); ++ if (vboxsf_setup_done) { ++ vboxsf_disconnect(); ++ /* ++ * Make sure all delayed rcu free inodes are flushed ++ * before we destroy the cache. ++ */ ++ rcu_barrier(); ++ kmem_cache_destroy(vboxsf_inode_cachep); ++ } ++ mutex_unlock(&vboxsf_setup_mutex); ++} ++ ++module_init(vboxsf_init); ++module_exit(vboxsf_fini); ++ ++MODULE_DESCRIPTION("Oracle VM VirtualBox Module for Host File System Access"); ++MODULE_AUTHOR("Oracle Corporation"); ++MODULE_LICENSE("GPL v2"); ++MODULE_ALIAS_FS("vboxsf"); +diff --git a/drivers/staging/vboxsf/utils.c b/drivers/staging/vboxsf/utils.c +new file mode 100644 +index 000000000000..1870b69c824e +--- /dev/null ++++ b/drivers/staging/vboxsf/utils.c +@@ -0,0 +1,550 @@ ++// SPDX-License-Identifier: MIT ++/* ++ * VirtualBox Guest Shared Folders support: Utility functions. ++ * Mainly conversion from/to VirtualBox/Linux data structures. ++ * ++ * Copyright (C) 2006-2018 Oracle Corporation ++ */ ++ ++#include ++#include ++#include ++#include ++#include "vfsmod.h" ++ ++struct inode *vboxsf_new_inode(struct super_block *sb) ++{ ++ struct vboxsf_sbi *sbi = VBOXSF_SBI(sb); ++ struct inode *inode; ++ unsigned long flags; ++ int cursor, ret; ++ u32 gen; ++ ++ inode = new_inode(sb); ++ if (!inode) ++ return ERR_PTR(-ENOMEM); ++ ++ idr_preload(GFP_KERNEL); ++ spin_lock_irqsave(&sbi->ino_idr_lock, flags); ++ cursor = idr_get_cursor(&sbi->ino_idr); ++ ret = idr_alloc_cyclic(&sbi->ino_idr, inode, 1, 0, GFP_ATOMIC); ++ if (ret >= 0 && ret < cursor) ++ sbi->next_generation++; ++ gen = sbi->next_generation; ++ spin_unlock_irqrestore(&sbi->ino_idr_lock, flags); ++ idr_preload_end(); ++ ++ if (ret < 0) { ++ iput(inode); ++ return ERR_PTR(ret); ++ } ++ ++ inode->i_ino = ret; ++ inode->i_generation = gen; ++ return inode; ++} ++ ++/* set [inode] attributes based on [info], uid/gid based on [sbi] */ ++void vboxsf_init_inode(struct vboxsf_sbi *sbi, struct inode *inode, ++ const struct shfl_fsobjinfo *info) ++{ ++ const struct shfl_fsobjattr *attr; ++ s64 allocated; ++ int mode; ++ ++ attr = &info->attr; ++ ++#define mode_set(r) ((attr->mode & (SHFL_UNIX_##r)) ? (S_##r) : 0) ++ ++ mode = mode_set(IRUSR); ++ mode |= mode_set(IWUSR); ++ mode |= mode_set(IXUSR); ++ ++ mode |= mode_set(IRGRP); ++ mode |= mode_set(IWGRP); ++ mode |= mode_set(IXGRP); ++ ++ mode |= mode_set(IROTH); ++ mode |= mode_set(IWOTH); ++ mode |= mode_set(IXOTH); ++ ++#undef mode_set ++ ++ /* We use the host-side values for these */ ++ inode->i_flags |= S_NOATIME | S_NOCMTIME; ++ inode->i_mapping->a_ops = &vboxsf_reg_aops; ++ ++ if (SHFL_IS_DIRECTORY(attr->mode)) { ++ inode->i_mode = sbi->o.dmode_set ? sbi->o.dmode : mode; ++ inode->i_mode &= ~sbi->o.dmask; ++ inode->i_mode |= S_IFDIR; ++ inode->i_op = &vboxsf_dir_iops; ++ inode->i_fop = &vboxsf_dir_fops; ++ /* ++ * XXX: this probably should be set to the number of entries ++ * in the directory plus two (. ..) ++ */ ++ set_nlink(inode, 1); ++ } else if (SHFL_IS_SYMLINK(attr->mode)) { ++ inode->i_mode = sbi->o.fmode_set ? sbi->o.fmode : mode; ++ inode->i_mode &= ~sbi->o.fmask; ++ inode->i_mode |= S_IFLNK; ++ inode->i_op = &vboxsf_lnk_iops; ++ set_nlink(inode, 1); ++ } else { ++ inode->i_mode = sbi->o.fmode_set ? sbi->o.fmode : mode; ++ inode->i_mode &= ~sbi->o.fmask; ++ inode->i_mode |= S_IFREG; ++ inode->i_op = &vboxsf_reg_iops; ++ inode->i_fop = &vboxsf_reg_fops; ++ set_nlink(inode, 1); ++ } ++ ++ inode->i_uid = sbi->o.uid; ++ inode->i_gid = sbi->o.gid; ++ ++ inode->i_size = info->size; ++ inode->i_blkbits = 12; ++ /* i_blocks always in units of 512 bytes! */ ++ allocated = info->allocated + 511; ++ do_div(allocated, 512); ++ inode->i_blocks = allocated; ++ ++ inode->i_atime = ns_to_timespec64( ++ info->access_time.ns_relative_to_unix_epoch); ++ inode->i_ctime = ns_to_timespec64( ++ info->change_time.ns_relative_to_unix_epoch); ++ inode->i_mtime = ns_to_timespec64( ++ info->modification_time.ns_relative_to_unix_epoch); ++} ++ ++int vboxsf_create_at_dentry(struct dentry *dentry, ++ struct shfl_createparms *params) ++{ ++ struct vboxsf_sbi *sbi = VBOXSF_SBI(dentry->d_sb); ++ struct shfl_string *path; ++ int err; ++ ++ path = vboxsf_path_from_dentry(sbi, dentry); ++ if (IS_ERR(path)) ++ return PTR_ERR(path); ++ ++ err = vboxsf_create(sbi->root, path, params); ++ __putname(path); ++ ++ return err; ++} ++ ++int vboxsf_stat(struct vboxsf_sbi *sbi, struct shfl_string *path, ++ struct shfl_fsobjinfo *info) ++{ ++ struct shfl_createparms params = {}; ++ int err; ++ ++ params.handle = SHFL_HANDLE_NIL; ++ params.create_flags = SHFL_CF_LOOKUP | SHFL_CF_ACT_FAIL_IF_NEW; ++ ++ err = vboxsf_create(sbi->root, path, ¶ms); ++ if (err) ++ return err; ++ ++ if (params.result != SHFL_FILE_EXISTS) ++ return -ENOENT; ++ ++ if (info) ++ *info = params.info; ++ ++ return 0; ++} ++ ++int vboxsf_stat_dentry(struct dentry *dentry, struct shfl_fsobjinfo *info) ++{ ++ struct vboxsf_sbi *sbi = VBOXSF_SBI(dentry->d_sb); ++ struct shfl_string *path; ++ int err; ++ ++ path = vboxsf_path_from_dentry(sbi, dentry); ++ if (IS_ERR(path)) ++ return PTR_ERR(path); ++ ++ err = vboxsf_stat(sbi, path, info); ++ __putname(path); ++ return err; ++} ++ ++int vboxsf_inode_revalidate(struct dentry *dentry) ++{ ++ struct vboxsf_sbi *sbi = VBOXSF_SBI(dentry->d_sb); ++ struct vboxsf_inode *sf_i; ++ struct shfl_fsobjinfo info; ++ struct timespec64 prev_mtime; ++ struct inode *inode; ++ int err; ++ ++ if (!dentry || !d_really_is_positive(dentry)) ++ return -EINVAL; ++ ++ inode = d_inode(dentry); ++ prev_mtime = inode->i_mtime; ++ sf_i = VBOXSF_I(inode); ++ if (!sf_i->force_restat) { ++ if (time_before(jiffies, dentry->d_time + sbi->o.ttl)) ++ return 0; ++ } ++ ++ err = vboxsf_stat_dentry(dentry, &info); ++ if (err) ++ return err; ++ ++ dentry->d_time = jiffies; ++ sf_i->force_restat = 0; ++ vboxsf_init_inode(sbi, inode, &info); ++ ++ /* ++ * If the file was changed on the host side we need to invalidate the ++ * page-cache for it. Note this also gets triggered by our own writes, ++ * this is unavoidable. ++ */ ++ if (timespec64_compare(&inode->i_mtime, &prev_mtime) > 0) ++ invalidate_inode_pages2(inode->i_mapping); ++ ++ return 0; ++} ++ ++int vboxsf_getattr(const struct path *path, struct kstat *kstat, ++ u32 request_mask, unsigned int flags) ++{ ++ int err; ++ struct dentry *dentry = path->dentry; ++ struct inode *inode = d_inode(dentry); ++ struct vboxsf_inode *sf_i = VBOXSF_I(inode); ++ ++ switch (flags & AT_STATX_SYNC_TYPE) { ++ case AT_STATX_DONT_SYNC: ++ err = 0; ++ break; ++ case AT_STATX_FORCE_SYNC: ++ sf_i->force_restat = 1; ++ /* fall-through */ ++ default: ++ err = vboxsf_inode_revalidate(dentry); ++ } ++ if (err) ++ return err; ++ ++ generic_fillattr(d_inode(dentry), kstat); ++ return 0; ++} ++ ++int vboxsf_setattr(struct dentry *dentry, struct iattr *iattr) ++{ ++ struct vboxsf_inode *sf_i = VBOXSF_I(d_inode(dentry)); ++ struct vboxsf_sbi *sbi = VBOXSF_SBI(dentry->d_sb); ++ struct shfl_createparms params = {}; ++ struct shfl_fsobjinfo info = {}; ++ u32 buf_len; ++ int err; ++ ++ params.handle = SHFL_HANDLE_NIL; ++ params.create_flags = SHFL_CF_ACT_OPEN_IF_EXISTS | ++ SHFL_CF_ACT_FAIL_IF_NEW | ++ SHFL_CF_ACCESS_ATTR_WRITE; ++ ++ /* this is at least required for Posix hosts */ ++ if (iattr->ia_valid & ATTR_SIZE) ++ params.create_flags |= SHFL_CF_ACCESS_WRITE; ++ ++ err = vboxsf_create_at_dentry(dentry, ¶ms); ++ if (err || params.result != SHFL_FILE_EXISTS) ++ return err ? err : -ENOENT; ++ ++#define mode_set(r) ((iattr->ia_mode & (S_##r)) ? SHFL_UNIX_##r : 0) ++ ++ /* ++ * Setting the file size and setting the other attributes has to ++ * be handled separately. ++ */ ++ if (iattr->ia_valid & (ATTR_MODE | ATTR_ATIME | ATTR_MTIME)) { ++ if (iattr->ia_valid & ATTR_MODE) { ++ info.attr.mode = mode_set(IRUSR); ++ info.attr.mode |= mode_set(IWUSR); ++ info.attr.mode |= mode_set(IXUSR); ++ info.attr.mode |= mode_set(IRGRP); ++ info.attr.mode |= mode_set(IWGRP); ++ info.attr.mode |= mode_set(IXGRP); ++ info.attr.mode |= mode_set(IROTH); ++ info.attr.mode |= mode_set(IWOTH); ++ info.attr.mode |= mode_set(IXOTH); ++ ++ if (iattr->ia_mode & S_IFDIR) ++ info.attr.mode |= SHFL_TYPE_DIRECTORY; ++ else ++ info.attr.mode |= SHFL_TYPE_FILE; ++ } ++ ++ if (iattr->ia_valid & ATTR_ATIME) ++ info.access_time.ns_relative_to_unix_epoch = ++ timespec64_to_ns(&iattr->ia_atime); ++ ++ if (iattr->ia_valid & ATTR_MTIME) ++ info.modification_time.ns_relative_to_unix_epoch = ++ timespec64_to_ns(&iattr->ia_mtime); ++ ++ /* ++ * Ignore ctime (inode change time) as it can't be set ++ * from userland anyway. ++ */ ++ ++ buf_len = sizeof(info); ++ err = vboxsf_fsinfo(sbi->root, params.handle, ++ SHFL_INFO_SET | SHFL_INFO_FILE, &buf_len, ++ &info); ++ if (err) { ++ vboxsf_close(sbi->root, params.handle); ++ return err; ++ } ++ ++ /* the host may have given us different attr then requested */ ++ sf_i->force_restat = 1; ++ } ++ ++#undef mode_set ++ ++ if (iattr->ia_valid & ATTR_SIZE) { ++ memset(&info, 0, sizeof(info)); ++ info.size = iattr->ia_size; ++ buf_len = sizeof(info); ++ err = vboxsf_fsinfo(sbi->root, params.handle, ++ SHFL_INFO_SET | SHFL_INFO_SIZE, &buf_len, ++ &info); ++ if (err) { ++ vboxsf_close(sbi->root, params.handle); ++ return err; ++ } ++ ++ /* the host may have given us different attr then requested */ ++ sf_i->force_restat = 1; ++ } ++ ++ vboxsf_close(sbi->root, params.handle); ++ ++ /* Update the inode with what the host has actually given us. */ ++ if (sf_i->force_restat) ++ vboxsf_inode_revalidate(dentry); ++ ++ return 0; ++} ++ ++/* ++ * [dentry] contains string encoded in coding system that corresponds ++ * to [sbi]->nls, we must convert it to UTF8 here. ++ * Returns a shfl_string allocated through __getname (must be freed using ++ * __putname), or an ERR_PTR on error. ++ */ ++struct shfl_string *vboxsf_path_from_dentry(struct vboxsf_sbi *sbi, ++ struct dentry *dentry) ++{ ++ struct shfl_string *shfl_path; ++ int path_len, out_len, nb; ++ char *buf, *path; ++ wchar_t uni; ++ u8 *out; ++ ++ buf = __getname(); ++ if (!buf) ++ return ERR_PTR(-ENOMEM); ++ ++ path = dentry_path_raw(dentry, buf, PATH_MAX); ++ if (IS_ERR(path)) { ++ __putname(buf); ++ return (struct shfl_string *)path; ++ } ++ path_len = strlen(path); ++ ++ if (sbi->nls) { ++ shfl_path = __getname(); ++ if (!shfl_path) { ++ __putname(buf); ++ return ERR_PTR(-ENOMEM); ++ } ++ ++ out = shfl_path->string.utf8; ++ out_len = PATH_MAX - SHFLSTRING_HEADER_SIZE - 1; ++ ++ while (path_len) { ++ nb = sbi->nls->char2uni(path, path_len, &uni); ++ if (nb < 0) { ++ __putname(shfl_path); ++ __putname(buf); ++ return ERR_PTR(-EINVAL); ++ } ++ path += nb; ++ path_len -= nb; ++ ++ nb = utf32_to_utf8(uni, out, out_len); ++ if (nb < 0) { ++ __putname(shfl_path); ++ __putname(buf); ++ return ERR_PTR(-ENAMETOOLONG); ++ } ++ out += nb; ++ out_len -= nb; ++ } ++ *out = 0; ++ shfl_path->length = out - shfl_path->string.utf8; ++ shfl_path->size = shfl_path->length + 1; ++ __putname(buf); ++ } else { ++ if ((SHFLSTRING_HEADER_SIZE + path_len + 1) > PATH_MAX) { ++ __putname(buf); ++ return ERR_PTR(-ENAMETOOLONG); ++ } ++ /* ++ * dentry_path stores the name at the end of buf, but the ++ * shfl_string string we return must be properly aligned. ++ */ ++ shfl_path = (struct shfl_string *)buf; ++ memmove(shfl_path->string.utf8, path, path_len); ++ shfl_path->string.utf8[path_len] = 0; ++ shfl_path->length = path_len; ++ shfl_path->size = path_len + 1; ++ } ++ ++ return shfl_path; ++} ++ ++int vboxsf_nlscpy(struct vboxsf_sbi *sbi, char *name, size_t name_bound_len, ++ const unsigned char *utf8_name, size_t utf8_len) ++{ ++ const char *in; ++ char *out; ++ size_t out_len; ++ size_t out_bound_len; ++ size_t in_bound_len; ++ ++ in = utf8_name; ++ in_bound_len = utf8_len; ++ ++ out = name; ++ out_len = 0; ++ /* Reserve space for terminating 0 */ ++ out_bound_len = name_bound_len - 1; ++ ++ while (in_bound_len) { ++ int nb; ++ unicode_t uni; ++ ++ nb = utf8_to_utf32(in, in_bound_len, &uni); ++ if (nb < 0) ++ return -EINVAL; ++ ++ in += nb; ++ in_bound_len -= nb; ++ ++ nb = sbi->nls->uni2char(uni, out, out_bound_len); ++ if (nb < 0) ++ return nb; ++ ++ out += nb; ++ out_bound_len -= nb; ++ out_len += nb; ++ } ++ ++ *out = 0; ++ ++ return 0; ++} ++ ++static struct vboxsf_dir_buf *vboxsf_dir_buf_alloc(struct list_head *list) ++{ ++ struct vboxsf_dir_buf *b; ++ ++ b = kmalloc(sizeof(*b), GFP_KERNEL); ++ if (!b) ++ return NULL; ++ ++ b->buf = kmalloc(DIR_BUFFER_SIZE, GFP_KERNEL); ++ if (!b->buf) { ++ kfree(b); ++ return NULL; ++ } ++ ++ b->entries = 0; ++ b->used = 0; ++ b->free = DIR_BUFFER_SIZE; ++ list_add(&b->head, list); ++ ++ return b; ++} ++ ++static void vboxsf_dir_buf_free(struct vboxsf_dir_buf *b) ++{ ++ list_del(&b->head); ++ kfree(b->buf); ++ kfree(b); ++} ++ ++struct vboxsf_dir_info *vboxsf_dir_info_alloc(void) ++{ ++ struct vboxsf_dir_info *p; ++ ++ p = kmalloc(sizeof(*p), GFP_KERNEL); ++ if (!p) ++ return NULL; ++ ++ INIT_LIST_HEAD(&p->info_list); ++ return p; ++} ++ ++void vboxsf_dir_info_free(struct vboxsf_dir_info *p) ++{ ++ struct list_head *list, *pos, *tmp; ++ ++ list = &p->info_list; ++ list_for_each_safe(pos, tmp, list) { ++ struct vboxsf_dir_buf *b; ++ ++ b = list_entry(pos, struct vboxsf_dir_buf, head); ++ vboxsf_dir_buf_free(b); ++ } ++ kfree(p); ++} ++ ++int vboxsf_dir_read_all(struct vboxsf_sbi *sbi, struct vboxsf_dir_info *sf_d, ++ u64 handle) ++{ ++ struct vboxsf_dir_buf *b; ++ u32 entries, size; ++ int err = 0; ++ void *buf; ++ ++ /* vboxsf_dirinfo returns 1 on end of dir */ ++ while (err == 0) { ++ b = vboxsf_dir_buf_alloc(&sf_d->info_list); ++ if (!b) { ++ err = -ENOMEM; ++ break; ++ } ++ ++ buf = b->buf; ++ size = b->free; ++ ++ err = vboxsf_dirinfo(sbi->root, handle, NULL, 0, 0, ++ &size, buf, &entries); ++ if (err < 0) ++ break; ++ ++ b->entries += entries; ++ b->free -= size; ++ b->used += size; ++ } ++ ++ if (b && b->used == 0) ++ vboxsf_dir_buf_free(b); ++ ++ /* -EILSEQ means the host could not translate a filename, ignore */ ++ if (err > 0 || err == -EILSEQ) ++ err = 0; ++ ++ return err; ++} +diff --git a/drivers/staging/vboxsf/vboxsf_wrappers.c b/drivers/staging/vboxsf/vboxsf_wrappers.c +new file mode 100644 +index 000000000000..bfc78a097dae +--- /dev/null ++++ b/drivers/staging/vboxsf/vboxsf_wrappers.c +@@ -0,0 +1,371 @@ ++// SPDX-License-Identifier: MIT ++/* ++ * Wrapper functions for the shfl host calls. ++ * ++ * Copyright (C) 2006-2018 Oracle Corporation ++ */ ++ ++#include ++#include ++#include ++#include ++#include "vfsmod.h" ++ ++#define SHFL_REQUEST \ ++ (VMMDEV_REQUESTOR_KERNEL | VMMDEV_REQUESTOR_USR_DRV_OTHER | \ ++ VMMDEV_REQUESTOR_CON_DONT_KNOW | VMMDEV_REQUESTOR_TRUST_NOT_GIVEN) ++ ++static u32 vboxsf_client_id; ++ ++int vboxsf_connect(void) ++{ ++ struct vbg_dev *gdev; ++ struct vmmdev_hgcm_service_location loc; ++ int err, vbox_status; ++ ++ loc.type = VMMDEV_HGCM_LOC_LOCALHOST_EXISTING; ++ strcpy(loc.u.localhost.service_name, "VBoxSharedFolders"); ++ ++ gdev = vbg_get_gdev(); ++ if (IS_ERR(gdev)) ++ return -ENODEV; /* No guest-device */ ++ ++ err = vbg_hgcm_connect(gdev, SHFL_REQUEST, &loc, ++ &vboxsf_client_id, &vbox_status); ++ vbg_put_gdev(gdev); ++ ++ return err ? err : vbg_status_code_to_errno(vbox_status); ++} ++ ++void vboxsf_disconnect(void) ++{ ++ struct vbg_dev *gdev; ++ int vbox_status; ++ ++ gdev = vbg_get_gdev(); ++ if (IS_ERR(gdev)) ++ return; /* guest-device is gone, already disconnected */ ++ ++ vbg_hgcm_disconnect(gdev, SHFL_REQUEST, vboxsf_client_id, &vbox_status); ++ vbg_put_gdev(gdev); ++} ++ ++static int vboxsf_call(u32 function, void *parms, u32 parm_count, int *status) ++{ ++ struct vbg_dev *gdev; ++ int err, vbox_status; ++ ++ gdev = vbg_get_gdev(); ++ if (IS_ERR(gdev)) ++ return -ESHUTDOWN; /* guest-dev removed underneath us */ ++ ++ err = vbg_hgcm_call(gdev, SHFL_REQUEST, vboxsf_client_id, function, ++ U32_MAX, parms, parm_count, &vbox_status); ++ vbg_put_gdev(gdev); ++ ++ if (err < 0) ++ return err; ++ ++ if (status) ++ *status = vbox_status; ++ ++ return vbg_status_code_to_errno(vbox_status); ++} ++ ++int vboxsf_map_folder(struct shfl_string *folder_name, u32 *root) ++{ ++ struct shfl_map_folder parms; ++ int err, status; ++ ++ parms.path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL; ++ parms.path.u.pointer.size = shfl_string_buf_size(folder_name); ++ parms.path.u.pointer.u.linear_addr = (uintptr_t)folder_name; ++ ++ parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; ++ parms.root.u.value32 = 0; ++ ++ parms.delimiter.type = VMMDEV_HGCM_PARM_TYPE_32BIT; ++ parms.delimiter.u.value32 = '/'; ++ ++ parms.case_sensitive.type = VMMDEV_HGCM_PARM_TYPE_32BIT; ++ parms.case_sensitive.u.value32 = 1; ++ ++ err = vboxsf_call(SHFL_FN_MAP_FOLDER, &parms, SHFL_CPARMS_MAP_FOLDER, ++ &status); ++ if (err == -ENOSYS && status == VERR_NOT_IMPLEMENTED) ++ vbg_err("%s: Error host is too old\n", __func__); ++ ++ *root = parms.root.u.value32; ++ return err; ++} ++ ++int vboxsf_unmap_folder(u32 root) ++{ ++ struct shfl_unmap_folder parms; ++ ++ parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; ++ parms.root.u.value32 = root; ++ ++ return vboxsf_call(SHFL_FN_UNMAP_FOLDER, &parms, ++ SHFL_CPARMS_UNMAP_FOLDER, NULL); ++} ++ ++/** ++ * vboxsf_create - Create a new file or folder ++ * @root: Root of the shared folder in which to create the file ++ * @parsed_path: The path of the file or folder relative to the shared folder ++ * @param: create_parms Parameters for file/folder creation. ++ * ++ * Create a new file or folder or open an existing one in a shared folder. ++ * Note this function always returns 0 / success unless an exceptional condition ++ * occurs - out of memory, invalid arguments, etc. If the file or folder could ++ * not be opened or created, create_parms->handle will be set to ++ * SHFL_HANDLE_NIL on return. In this case the value in create_parms->result ++ * provides information as to why (e.g. SHFL_FILE_EXISTS), create_parms->result ++ * is also set on success as additional information. ++ * ++ * Returns: ++ * 0 or negative errno value. ++ */ ++int vboxsf_create(u32 root, struct shfl_string *parsed_path, ++ struct shfl_createparms *create_parms) ++{ ++ struct shfl_create parms; ++ ++ parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; ++ parms.root.u.value32 = root; ++ ++ parms.path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL; ++ parms.path.u.pointer.size = shfl_string_buf_size(parsed_path); ++ parms.path.u.pointer.u.linear_addr = (uintptr_t)parsed_path; ++ ++ parms.parms.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL; ++ parms.parms.u.pointer.size = sizeof(struct shfl_createparms); ++ parms.parms.u.pointer.u.linear_addr = (uintptr_t)create_parms; ++ ++ return vboxsf_call(SHFL_FN_CREATE, &parms, SHFL_CPARMS_CREATE, NULL); ++} ++ ++int vboxsf_close(u32 root, u64 handle) ++{ ++ struct shfl_close parms; ++ ++ parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; ++ parms.root.u.value32 = root; ++ ++ parms.handle.type = VMMDEV_HGCM_PARM_TYPE_64BIT; ++ parms.handle.u.value64 = handle; ++ ++ return vboxsf_call(SHFL_FN_CLOSE, &parms, SHFL_CPARMS_CLOSE, NULL); ++} ++ ++int vboxsf_remove(u32 root, struct shfl_string *parsed_path, u32 flags) ++{ ++ struct shfl_remove parms; ++ ++ parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; ++ parms.root.u.value32 = root; ++ ++ parms.path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN; ++ parms.path.u.pointer.size = shfl_string_buf_size(parsed_path); ++ parms.path.u.pointer.u.linear_addr = (uintptr_t)parsed_path; ++ ++ parms.flags.type = VMMDEV_HGCM_PARM_TYPE_32BIT; ++ parms.flags.u.value32 = flags; ++ ++ return vboxsf_call(SHFL_FN_REMOVE, &parms, SHFL_CPARMS_REMOVE, NULL); ++} ++ ++int vboxsf_rename(u32 root, struct shfl_string *src_path, ++ struct shfl_string *dest_path, u32 flags) ++{ ++ struct shfl_rename parms; ++ ++ parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; ++ parms.root.u.value32 = root; ++ ++ parms.src.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN; ++ parms.src.u.pointer.size = shfl_string_buf_size(src_path); ++ parms.src.u.pointer.u.linear_addr = (uintptr_t)src_path; ++ ++ parms.dest.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN; ++ parms.dest.u.pointer.size = shfl_string_buf_size(dest_path); ++ parms.dest.u.pointer.u.linear_addr = (uintptr_t)dest_path; ++ ++ parms.flags.type = VMMDEV_HGCM_PARM_TYPE_32BIT; ++ parms.flags.u.value32 = flags; ++ ++ return vboxsf_call(SHFL_FN_RENAME, &parms, SHFL_CPARMS_RENAME, NULL); ++} ++ ++int vboxsf_read(u32 root, u64 handle, u64 offset, u32 *buf_len, u8 *buf) ++{ ++ struct shfl_read parms; ++ int err; ++ ++ parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; ++ parms.root.u.value32 = root; ++ ++ parms.handle.type = VMMDEV_HGCM_PARM_TYPE_64BIT; ++ parms.handle.u.value64 = handle; ++ parms.offset.type = VMMDEV_HGCM_PARM_TYPE_64BIT; ++ parms.offset.u.value64 = offset; ++ parms.cb.type = VMMDEV_HGCM_PARM_TYPE_32BIT; ++ parms.cb.u.value32 = *buf_len; ++ parms.buffer.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_OUT; ++ parms.buffer.u.pointer.size = *buf_len; ++ parms.buffer.u.pointer.u.linear_addr = (uintptr_t)buf; ++ ++ err = vboxsf_call(SHFL_FN_READ, &parms, SHFL_CPARMS_READ, NULL); ++ ++ *buf_len = parms.cb.u.value32; ++ return err; ++} ++ ++int vboxsf_write(u32 root, u64 handle, u64 offset, u32 *buf_len, u8 *buf) ++{ ++ struct shfl_write parms; ++ int err; ++ ++ parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; ++ parms.root.u.value32 = root; ++ ++ parms.handle.type = VMMDEV_HGCM_PARM_TYPE_64BIT; ++ parms.handle.u.value64 = handle; ++ parms.offset.type = VMMDEV_HGCM_PARM_TYPE_64BIT; ++ parms.offset.u.value64 = offset; ++ parms.cb.type = VMMDEV_HGCM_PARM_TYPE_32BIT; ++ parms.cb.u.value32 = *buf_len; ++ parms.buffer.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN; ++ parms.buffer.u.pointer.size = *buf_len; ++ parms.buffer.u.pointer.u.linear_addr = (uintptr_t)buf; ++ ++ err = vboxsf_call(SHFL_FN_WRITE, &parms, SHFL_CPARMS_WRITE, NULL); ++ ++ *buf_len = parms.cb.u.value32; ++ return err; ++} ++ ++/* Returns 0 on success, 1 on end-of-dir, negative errno otherwise */ ++int vboxsf_dirinfo(u32 root, u64 handle, ++ struct shfl_string *parsed_path, u32 flags, u32 index, ++ u32 *buf_len, struct shfl_dirinfo *buf, u32 *file_count) ++{ ++ struct shfl_list parms; ++ int err, status; ++ ++ parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; ++ parms.root.u.value32 = root; ++ ++ parms.handle.type = VMMDEV_HGCM_PARM_TYPE_64BIT; ++ parms.handle.u.value64 = handle; ++ parms.flags.type = VMMDEV_HGCM_PARM_TYPE_32BIT; ++ parms.flags.u.value32 = flags; ++ parms.cb.type = VMMDEV_HGCM_PARM_TYPE_32BIT; ++ parms.cb.u.value32 = *buf_len; ++ if (parsed_path) { ++ parms.path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN; ++ parms.path.u.pointer.size = shfl_string_buf_size(parsed_path); ++ parms.path.u.pointer.u.linear_addr = (uintptr_t)parsed_path; ++ } else { ++ parms.path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_IN; ++ parms.path.u.pointer.size = 0; ++ parms.path.u.pointer.u.linear_addr = 0; ++ } ++ ++ parms.buffer.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_OUT; ++ parms.buffer.u.pointer.size = *buf_len; ++ parms.buffer.u.pointer.u.linear_addr = (uintptr_t)buf; ++ ++ parms.resume_point.type = VMMDEV_HGCM_PARM_TYPE_32BIT; ++ parms.resume_point.u.value32 = index; ++ parms.file_count.type = VMMDEV_HGCM_PARM_TYPE_32BIT; ++ parms.file_count.u.value32 = 0; /* out parameter only */ ++ ++ err = vboxsf_call(SHFL_FN_LIST, &parms, SHFL_CPARMS_LIST, &status); ++ if (err == -ENODATA && status == VERR_NO_MORE_FILES) ++ err = 1; ++ ++ *buf_len = parms.cb.u.value32; ++ *file_count = parms.file_count.u.value32; ++ return err; ++} ++ ++int vboxsf_fsinfo(u32 root, u64 handle, u32 flags, ++ u32 *buf_len, void *buf) ++{ ++ struct shfl_information parms; ++ int err; ++ ++ parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; ++ parms.root.u.value32 = root; ++ ++ parms.handle.type = VMMDEV_HGCM_PARM_TYPE_64BIT; ++ parms.handle.u.value64 = handle; ++ parms.flags.type = VMMDEV_HGCM_PARM_TYPE_32BIT; ++ parms.flags.u.value32 = flags; ++ parms.cb.type = VMMDEV_HGCM_PARM_TYPE_32BIT; ++ parms.cb.u.value32 = *buf_len; ++ parms.info.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL; ++ parms.info.u.pointer.size = *buf_len; ++ parms.info.u.pointer.u.linear_addr = (uintptr_t)buf; ++ ++ err = vboxsf_call(SHFL_FN_INFORMATION, &parms, SHFL_CPARMS_INFORMATION, ++ NULL); ++ ++ *buf_len = parms.cb.u.value32; ++ return err; ++} ++ ++int vboxsf_readlink(u32 root, struct shfl_string *parsed_path, ++ u32 buf_len, u8 *buf) ++{ ++ struct shfl_readLink parms; ++ ++ parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; ++ parms.root.u.value32 = root; ++ ++ parms.path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN; ++ parms.path.u.pointer.size = shfl_string_buf_size(parsed_path); ++ parms.path.u.pointer.u.linear_addr = (uintptr_t)parsed_path; ++ ++ parms.buffer.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_OUT; ++ parms.buffer.u.pointer.size = buf_len; ++ parms.buffer.u.pointer.u.linear_addr = (uintptr_t)buf; ++ ++ return vboxsf_call(SHFL_FN_READLINK, &parms, SHFL_CPARMS_READLINK, ++ NULL); ++} ++ ++int vboxsf_symlink(u32 root, struct shfl_string *new_path, ++ struct shfl_string *old_path, struct shfl_fsobjinfo *buf) ++{ ++ struct shfl_symlink parms; ++ ++ parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; ++ parms.root.u.value32 = root; ++ ++ parms.new_path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN; ++ parms.new_path.u.pointer.size = shfl_string_buf_size(new_path); ++ parms.new_path.u.pointer.u.linear_addr = (uintptr_t)new_path; ++ ++ parms.old_path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN; ++ parms.old_path.u.pointer.size = shfl_string_buf_size(old_path); ++ parms.old_path.u.pointer.u.linear_addr = (uintptr_t)old_path; ++ ++ parms.info.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_OUT; ++ parms.info.u.pointer.size = sizeof(struct shfl_fsobjinfo); ++ parms.info.u.pointer.u.linear_addr = (uintptr_t)buf; ++ ++ return vboxsf_call(SHFL_FN_SYMLINK, &parms, SHFL_CPARMS_SYMLINK, NULL); ++} ++ ++int vboxsf_set_utf8(void) ++{ ++ return vboxsf_call(SHFL_FN_SET_UTF8, NULL, 0, NULL); ++} ++ ++int vboxsf_set_symlinks(void) ++{ ++ return vboxsf_call(SHFL_FN_SET_SYMLINKS, NULL, 0, NULL); ++} +diff --git a/drivers/staging/vboxsf/vfsmod.h b/drivers/staging/vboxsf/vfsmod.h +new file mode 100644 +index 000000000000..de650d65fbe4 +--- /dev/null ++++ b/drivers/staging/vboxsf/vfsmod.h +@@ -0,0 +1,138 @@ ++/* SPDX-License-Identifier: MIT */ ++/* ++ * VirtualBox Guest Shared Folders support: module header. ++ * ++ * Copyright (C) 2006-2018 Oracle Corporation ++ */ ++ ++#ifndef VFSMOD_H ++#define VFSMOD_H ++ ++#include ++#include ++#include ++#include "shfl_hostintf.h" ++ ++#define DIR_BUFFER_SIZE SZ_16K ++ ++/* The cast is to prevent assignment of void * to pointers of arbitrary type */ ++#define VBOXSF_SBI(sb) ((struct vboxsf_sbi *)(sb)->s_fs_info) ++#define VBOXSF_I(i) container_of(i, struct vboxsf_inode, vfs_inode) ++ ++struct vboxsf_options { ++ unsigned long ttl; ++ kuid_t uid; ++ kgid_t gid; ++ bool dmode_set; ++ bool fmode_set; ++ umode_t dmode; ++ umode_t fmode; ++ umode_t dmask; ++ umode_t fmask; ++}; ++ ++struct vboxsf_fs_context { ++ struct vboxsf_options o; ++ char *nls_name; ++}; ++ ++/* per-shared folder information */ ++struct vboxsf_sbi { ++ struct vboxsf_options o; ++ struct shfl_fsobjinfo root_info; ++ struct idr ino_idr; ++ spinlock_t ino_idr_lock; /* This protects ino_idr */ ++ struct nls_table *nls; ++ u32 next_generation; ++ u32 root; ++ int bdi_id; ++}; ++ ++/* per-inode information */ ++struct vboxsf_inode { ++ /* some information was changed, update data on next revalidate */ ++ int force_restat; ++ /* list of open handles for this inode + lock protecting it */ ++ struct list_head handle_list; ++ /* This mutex protects handle_list accesses */ ++ struct mutex handle_list_mutex; ++ /* The VFS inode struct */ ++ struct inode vfs_inode; ++}; ++ ++struct vboxsf_dir_info { ++ struct list_head info_list; ++}; ++ ++struct vboxsf_dir_buf { ++ size_t entries; ++ size_t free; ++ size_t used; ++ void *buf; ++ struct list_head head; ++}; ++ ++/* globals */ ++extern const struct inode_operations vboxsf_dir_iops; ++extern const struct inode_operations vboxsf_lnk_iops; ++extern const struct inode_operations vboxsf_reg_iops; ++extern const struct file_operations vboxsf_dir_fops; ++extern const struct file_operations vboxsf_reg_fops; ++extern const struct address_space_operations vboxsf_reg_aops; ++extern const struct dentry_operations vboxsf_dentry_ops; ++ ++/* from utils.c */ ++struct inode *vboxsf_new_inode(struct super_block *sb); ++void vboxsf_init_inode(struct vboxsf_sbi *sbi, struct inode *inode, ++ const struct shfl_fsobjinfo *info); ++int vboxsf_create_at_dentry(struct dentry *dentry, ++ struct shfl_createparms *params); ++int vboxsf_stat(struct vboxsf_sbi *sbi, struct shfl_string *path, ++ struct shfl_fsobjinfo *info); ++int vboxsf_stat_dentry(struct dentry *dentry, struct shfl_fsobjinfo *info); ++int vboxsf_inode_revalidate(struct dentry *dentry); ++int vboxsf_getattr(const struct path *path, struct kstat *kstat, ++ u32 request_mask, unsigned int query_flags); ++int vboxsf_setattr(struct dentry *dentry, struct iattr *iattr); ++struct shfl_string *vboxsf_path_from_dentry(struct vboxsf_sbi *sbi, ++ struct dentry *dentry); ++int vboxsf_nlscpy(struct vboxsf_sbi *sbi, char *name, size_t name_bound_len, ++ const unsigned char *utf8_name, size_t utf8_len); ++struct vboxsf_dir_info *vboxsf_dir_info_alloc(void); ++void vboxsf_dir_info_free(struct vboxsf_dir_info *p); ++int vboxsf_dir_read_all(struct vboxsf_sbi *sbi, struct vboxsf_dir_info *sf_d, ++ u64 handle); ++ ++/* from vboxsf_wrappers.c */ ++int vboxsf_connect(void); ++void vboxsf_disconnect(void); ++ ++int vboxsf_create(u32 root, struct shfl_string *parsed_path, ++ struct shfl_createparms *create_parms); ++ ++int vboxsf_close(u32 root, u64 handle); ++int vboxsf_remove(u32 root, struct shfl_string *parsed_path, u32 flags); ++int vboxsf_rename(u32 root, struct shfl_string *src_path, ++ struct shfl_string *dest_path, u32 flags); ++ ++int vboxsf_read(u32 root, u64 handle, u64 offset, u32 *buf_len, u8 *buf); ++int vboxsf_write(u32 root, u64 handle, u64 offset, u32 *buf_len, u8 *buf); ++ ++int vboxsf_dirinfo(u32 root, u64 handle, ++ struct shfl_string *parsed_path, u32 flags, u32 index, ++ u32 *buf_len, struct shfl_dirinfo *buf, u32 *file_count); ++int vboxsf_fsinfo(u32 root, u64 handle, u32 flags, ++ u32 *buf_len, void *buf); ++ ++int vboxsf_map_folder(struct shfl_string *folder_name, u32 *root); ++int vboxsf_unmap_folder(u32 root); ++ ++int vboxsf_readlink(u32 root, struct shfl_string *parsed_path, ++ u32 buf_len, u8 *buf); ++int vboxsf_symlink(u32 root, struct shfl_string *new_path, ++ struct shfl_string *old_path, struct shfl_fsobjinfo *buf); ++ ++int vboxsf_set_utf8(void); ++int vboxsf_set_symlinks(void); ++ ++#endif +-- +cgit 1.2-0.3.lf.el7 + diff --git a/kernel/tools/cpupowertools/files/patches/mageia/input-goodix-add-support-for-GDIX1002.patch b/kernel/tools/cpupowertools/files/patches/mageia/input-goodix-add-support-for-GDIX1002.patch new file mode 100644 index 00000000..8f263bee --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/mageia/input-goodix-add-support-for-GDIX1002.patch @@ -0,0 +1,18 @@ +--- a/drivers/input/touchscreen/goodix.c ++++ a/drivers/input/touchscreen/goodix.c +@@ -947,6 +954,7 @@ static SIMPLE_DEV_PM_OPS(goodix_pm_ops, goodix_suspend, goodix_resume); + + static const struct i2c_device_id goodix_ts_id[] = { + { "GDIX1001:00", 0 }, ++ { "GDIX1002:00", 0 }, + { } + }; + MODULE_DEVICE_TABLE(i2c, goodix_ts_id); +@@ -954,6 +962,7 @@ MODULE_DEVICE_TABLE(i2c, goodix_ts_id); + #ifdef CONFIG_ACPI + static const struct acpi_device_id goodix_acpi_match[] = { + { "GDIX1001", 0 }, ++ { "GDIX1002", 0 }, + { } + }; + MODULE_DEVICE_TABLE(acpi, goodix_acpi_match); diff --git a/kernel/tools/cpupowertools/files/patches/mageia/input-goodix-disable-IRQs-while-suspended.patch b/kernel/tools/cpupowertools/files/patches/mageia/input-goodix-disable-IRQs-while-suspended.patch new file mode 100644 index 00000000..e946f0d3 --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/mageia/input-goodix-disable-IRQs-while-suspended.patch @@ -0,0 +1,60 @@ +From faec44b6838312484d63e82286087cf2d5ebb891 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Fri, 12 Jan 2018 00:36:48 -0800 +Subject: [PATCH] Input: goodix - disable IRQs while suspended + +We should not try to do any i2c transfers before the controller is +resumed (which happens before our resume method gets called). + +So we need to disable our IRQ while suspended to enforce this. The +code paths for devices with GPIOs for the int and reset pins already +disable the IRQ the through goodix_free_irq(). + +This commit also disables the IRQ while suspended for devices without +GPIOs for the int and reset pins. + +This fixes the i2c bus sometimes getting stuck after a suspend/resume +causing the touchscreen to sometimes not work after a suspend/resume. +This has been tested on a GPD pocked device. + +BugLink: https://github.com/nexus511/gpd-ubuntu-packages/issues/10 +BugLink: https://www.reddit.com/r/GPDPocket/comments/7niut2/fix_for_broken_touch_after_resume_all_linux/ +Tested-by: Hans de Goede +Signed-off-by: Hans de Goede +Reviewed-by: Bastien Nocera +Signed-off-by: Dmitry Torokhov +--- + drivers/input/touchscreen/goodix.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c +index 69d0b8cbc71f..ecec8eb17f28 100644 +--- a/drivers/input/touchscreen/goodix.c ++++ b/drivers/input/touchscreen/goodix.c +@@ -878,8 +878,10 @@ static int __maybe_unused goodix_suspend(struct device *dev) + int error; + + /* We need gpio pins to suspend/resume */ +- if (!ts->gpiod_int || !ts->gpiod_rst) ++ if (!ts->gpiod_int || !ts->gpiod_rst) { ++ disable_irq(client->irq); + return 0; ++ } + + wait_for_completion(&ts->firmware_loading_complete); + +@@ -919,8 +921,10 @@ static int __maybe_unused goodix_resume(struct device *dev) + struct goodix_ts_data *ts = i2c_get_clientdata(client); + int error; + +- if (!ts->gpiod_int || !ts->gpiod_rst) ++ if (!ts->gpiod_int || !ts->gpiod_rst) { ++ enable_irq(client->irq); + return 0; ++ } + + /* + * Exit sleep mode by outputting HIGH level to INT pin +-- +2.16.2 + diff --git a/kernel/tools/cpupowertools/files/patches/mageia/net-WireGuard.patch b/kernel/tools/cpupowertools/files/patches/mageia/net-WireGuard.patch index e42e438c..fce4fe44 100644 --- a/kernel/tools/cpupowertools/files/patches/mageia/net-WireGuard.patch +++ b/kernel/tools/cpupowertools/files/patches/mageia/net-WireGuard.patch @@ -1,6 +1,6 @@ ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/allowedips.c 2018-02-18 22:22:31.000000000 +0200 -@@ -0,0 +1,327 @@ +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/allowedips.c 2018-03-04 19:51:33.000000000 +0200 +@@ -0,0 +1,328 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2015-2018 Jason A. Donenfeld . All Rights Reserved. @@ -142,7 +142,8 @@ +/* This could be much faster if it actually just compared the common bits properly, + * by precomputing a mask bswap(~0 << (32 - cidr)), and the rest, but it turns out that + * common_bits is already super fast on modern processors, even taking into account -+ * the unfortunate bswap. So, we just inline it like this instead. */ ++ * the unfortunate bswap. So, we just inline it like this instead. ++ */ +#define prefix_matches(node, key, bits) (common_bits(node, key, bits) >= node->cidr) + +static __always_inline struct allowedips_node *find_node(struct allowedips_node *trie, u8 bits, const u8 *key) @@ -328,8 +329,8 @@ +} + +#include "selftest/allowedips.h" ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/cookie.c 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/cookie.c 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,195 @@ +/* SPDX-License-Identifier: GPL-2.0 + * @@ -526,8 +527,8 @@ +out: + peer_put(entry->peer); +} ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/device.c 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/device.c 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,421 @@ +/* SPDX-License-Identifier: GPL-2.0 + * @@ -950,8 +951,8 @@ +#endif + rcu_barrier_bh(); +} ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/hashtables.c 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/hashtables.c 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,168 @@ +/* SPDX-License-Identifier: GPL-2.0 + * @@ -1121,8 +1122,8 @@ + rcu_read_unlock_bh(); + return entry; +} ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/main.c 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/main.c 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,69 @@ +/* SPDX-License-Identifier: GPL-2.0 + * @@ -1193,8 +1194,8 @@ +MODULE_VERSION(WIREGUARD_VERSION); +MODULE_ALIAS_RTNL_LINK(KBUILD_MODNAME); +MODULE_ALIAS_GENL_FAMILY(WG_GENL_NAME); ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/netlink.c 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/netlink.c 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,517 @@ +/* SPDX-License-Identifier: GPL-2.0 + * @@ -1713,8 +1714,8 @@ +{ + genl_unregister_family(&genl_family); +} ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/noise.c 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/noise.c 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,635 @@ +/* SPDX-License-Identifier: GPL-2.0 + * @@ -2351,8 +2352,8 @@ + up_write(&handshake->lock); + return false; +} ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/peer.c 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/peer.c 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,136 @@ +/* SPDX-License-Identifier: GPL-2.0 + * @@ -2490,8 +2491,8 @@ + list_for_each_entry_safe(peer, temp, &wg->peer_list, peer_list) + peer_remove(peer); +} ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/queueing.c 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/queueing.c 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: GPL-2.0 + * @@ -2539,8 +2540,8 @@ + WARN_ON(!ptr_ring_empty_bh(&queue->ring)); + ptr_ring_cleanup(&queue->ring, NULL); +} ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/ratelimiter.c 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/ratelimiter.c 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,199 @@ +/* SPDX-License-Identifier: GPL-2.0 + * @@ -2741,8 +2742,8 @@ +} + +#include "selftest/ratelimiter.h" ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/receive.c 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/receive.c 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,490 @@ +/* SPDX-License-Identifier: GPL-2.0 + * @@ -3234,8 +3235,8 @@ +err: + dev_kfree_skb(skb); +} ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/send.c 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/send.c 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,348 @@ +/* SPDX-License-Identifier: GPL-2.0 + * @@ -3585,8 +3586,8 @@ + */ + packet_send_queued_handshake_initiation(peer, false); +} ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/socket.c 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/socket.c 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,393 @@ +/* SPDX-License-Identifier: GPL-2.0 + * @@ -3981,8 +3982,8 @@ + sock_free(old4); + sock_free(old6); +} ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/timers.c 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/timers.c 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,199 @@ +/* SPDX-License-Identifier: GPL-2.0 + * @@ -4183,8 +4184,8 @@ + del_timer_sync(&peer->timer_persistent_keepalive); + flush_work(&peer->clear_peer_work); +} ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/allowedips.h 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/allowedips.h 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: GPL-2.0 + * @@ -4230,8 +4231,8 @@ +#endif + +#endif /* _WG_ALLOWEDIPS_H */ ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/cookie.h 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/cookie.h 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: GPL-2.0 + * @@ -4285,8 +4286,8 @@ +void cookie_message_consume(struct message_handshake_cookie *src, struct wireguard_device *wg); + +#endif /* _WG_COOKIE_H */ ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/device.h 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/device.h 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: GPL-2.0 + * @@ -4352,8 +4353,8 @@ +void device_uninit(void); + +#endif /* _WG_DEVICE_H */ ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/hashtables.h 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/hashtables.h 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: GPL-2.0 + * @@ -4407,9 +4408,9 @@ +struct index_hashtable_entry *index_hashtable_lookup(struct index_hashtable *table, const enum index_hashtable_type type_mask, const __le32 index); + +#endif /* _WG_HASHTABLES_H */ ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/messages.h 2018-02-18 22:22:31.000000000 +0200 -@@ -0,0 +1,129 @@ +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/messages.h 2018-03-04 19:51:33.000000000 +0200 +@@ -0,0 +1,128 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2015-2018 Jason A. Donenfeld . All Rights Reserved. @@ -4472,8 +4473,7 @@ + MESSAGE_HANDSHAKE_INITIATION = 1, + MESSAGE_HANDSHAKE_RESPONSE = 2, + MESSAGE_HANDSHAKE_COOKIE = 3, -+ MESSAGE_DATA = 4, -+ MESSAGE_TOTAL = 5 ++ MESSAGE_DATA = 4 +}; + +struct message_header { @@ -4539,8 +4539,8 @@ +}; + +#endif /* _WG_MESSAGES_H */ ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/netlink.h 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/netlink.h 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0 + * @@ -4554,8 +4554,8 @@ +void genetlink_uninit(void); + +#endif /* _WG_NETLINK_H */ ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/noise.h 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/noise.h 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,117 @@ +/* SPDX-License-Identifier: GPL-2.0 + * @@ -4613,10 +4613,10 @@ +}; + +struct noise_static_identity { -+ bool has_identity; + u8 static_public[NOISE_PUBLIC_KEY_LEN]; + u8 static_private[NOISE_PUBLIC_KEY_LEN]; + struct rw_semaphore lock; ++ bool has_identity; +}; + +enum noise_handshake_state { @@ -4668,14 +4668,14 @@ +bool noise_handshake_create_initiation(struct message_handshake_initiation *dst, struct noise_handshake *handshake); +struct wireguard_peer *noise_handshake_consume_initiation(struct message_handshake_initiation *src, struct wireguard_device *wg); + -+bool noise_handshake_create_response(struct message_handshake_response *dst, struct noise_handshake *peer); ++bool noise_handshake_create_response(struct message_handshake_response *dst, struct noise_handshake *handshake); +struct wireguard_peer *noise_handshake_consume_response(struct message_handshake_response *src, struct wireguard_device *wg); + +bool noise_handshake_begin_session(struct noise_handshake *handshake, struct noise_keypairs *keypairs); + +#endif /* _WG_NOISE_H */ ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/peer.h 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/peer.h 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,73 @@ +/* SPDX-License-Identifier: GPL-2.0 + * @@ -4750,8 +4750,8 @@ +struct wireguard_peer *peer_lookup_by_index(struct wireguard_device *wg, u32 index); + +#endif /* _WG_PEER_H */ ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/queueing.h 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/queueing.h 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,142 @@ +/* SPDX-License-Identifier: GPL-2.0 + * @@ -4818,7 +4818,7 @@ + +static inline void skb_reset(struct sk_buff *skb) +{ -+ skb_scrub_packet(skb, false); ++ skb_scrub_packet(skb, true); + memset(&skb->headers_start, 0, offsetof(struct sk_buff, headers_end) - offsetof(struct sk_buff, headers_start)); + skb->queue_mapping = 0; + skb->nohdr = 0; @@ -4895,8 +4895,8 @@ +#endif + +#endif /* _WG_QUEUEING_H */ ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/ratelimiter.h 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/ratelimiter.h 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0 + * @@ -4917,8 +4917,8 @@ +#endif + +#endif /* _WG_RATELIMITER_H */ ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/socket.h 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/socket.h 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: GPL-2.0 + * @@ -4955,8 +4955,8 @@ +#endif + +#endif /* _WG_SOCKET_H */ ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/timers.h 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/timers.h 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0 + * @@ -4979,12 +4979,12 @@ +void timers_any_authenticated_packet_traversal(struct wireguard_peer *peer); + +#endif /* _WG_TIMERS_H */ ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/version.h 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/version.h 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1 @@ -+#define WIREGUARD_VERSION "0.0.20180218" ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/uapi/wireguard.h 2018-02-18 22:22:31.000000000 +0200 ++#define WIREGUARD_VERSION "0.0.20180304" +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/uapi/wireguard.h 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,182 @@ +/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR MIT) + * @@ -5168,8 +5168,8 @@ +#define WGALLOWEDIP_A_MAX (__WGALLOWEDIP_A_LAST - 1) + +#endif /* _WG_UAPI_WIREGUARD_H */ ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/selftest/allowedips.h 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/selftest/allowedips.h 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,514 @@ +/* SPDX-License-Identifier: GPL-2.0 + * @@ -5685,8 +5685,8 @@ +#undef init_peer + +#endif ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/selftest/blake2s.h 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/selftest/blake2s.h 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,559 @@ +/* SPDX-License-Identifier: GPL-2.0 + * @@ -6247,8 +6247,8 @@ + return success; +} +#endif ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/selftest/chacha20poly1305.h 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/selftest/chacha20poly1305.h 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,333 @@ +/* SPDX-License-Identifier: GPL-2.0 + * @@ -6583,8 +6583,8 @@ + return success; +} +#endif ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/selftest/counter.h 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/selftest/counter.h 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,92 @@ +/* SPDX-License-Identifier: GPL-2.0 + * @@ -6678,8 +6678,8 @@ + return success; +} +#endif ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/selftest/curve25519.h 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/selftest/curve25519.h 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,103 @@ +/* SPDX-License-Identifier: GPL-2.0 + * @@ -6784,8 +6784,8 @@ + return success; +} +#endif ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/selftest/poly1305.h 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/selftest/poly1305.h 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,1566 @@ +/* SPDX-License-Identifier: GPL-2.0 + * @@ -8353,8 +8353,8 @@ + return success; +} +#endif ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/selftest/ratelimiter.h 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/selftest/ratelimiter.h 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,157 @@ +/* SPDX-License-Identifier: GPL-2.0 + * @@ -8513,8 +8513,8 @@ + return ret; +} +#endif ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/crypto/blake2s.c 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/crypto/blake2s.c 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,294 @@ +/* SPDX-License-Identifier: GPL-2.0 + * @@ -8631,8 +8631,8 @@ +#include +#include +#include -+static bool blake2s_use_avx __read_mostly; -+static bool blake2s_use_avx512 __read_mostly; ++static bool blake2s_use_avx __ro_after_init; ++static bool blake2s_use_avx512 __ro_after_init; +void __init blake2s_fpu_init(void) +{ +#ifndef CONFIG_UML @@ -8810,8 +8810,8 @@ +} + +#include "../selftest/blake2s.h" ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/crypto/chacha20poly1305.c 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/crypto/chacha20poly1305.c 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,852 @@ +/* SPDX-License-Identifier: OpenSSL OR (BSD-3-Clause OR GPL-2.0) + * @@ -8853,11 +8853,11 @@ +asmlinkage void poly1305_blocks_avx512(void *ctx, const u8 *inp, size_t len, u32 padbit); +#endif + -+static bool chacha20poly1305_use_ssse3 __read_mostly; -+static bool chacha20poly1305_use_avx __read_mostly; -+static bool chacha20poly1305_use_avx2 __read_mostly; -+static bool chacha20poly1305_use_avx512 __read_mostly; -+static bool chacha20poly1305_use_avx512vl __read_mostly; ++static bool chacha20poly1305_use_ssse3 __ro_after_init; ++static bool chacha20poly1305_use_avx __ro_after_init; ++static bool chacha20poly1305_use_avx2 __ro_after_init; ++static bool chacha20poly1305_use_avx512 __ro_after_init; ++static bool chacha20poly1305_use_avx512vl __ro_after_init; + +void __init chacha20poly1305_fpu_init(void) +{ @@ -8889,7 +8889,7 @@ +asmlinkage void poly1305_emit_neon(void *ctx, u8 mac[16], const u32 nonce[4]); +asmlinkage void chacha20_neon(u8 *out, const u8 *in, size_t len, const u32 key[8], const u32 counter[4]); +#endif -+static bool chacha20poly1305_use_neon __read_mostly; ++static bool chacha20poly1305_use_neon __ro_after_init; +void __init chacha20poly1305_fpu_init(void) +{ +#if defined(CONFIG_ARM64) @@ -9665,8 +9665,8 @@ + +#include "../selftest/chacha20poly1305.h" +#include "../selftest/poly1305.h" ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/crypto/curve25519.c 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/crypto/curve25519.c 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,81 @@ +/* SPDX-License-Identifier: GPL-2.0 + * @@ -9749,8 +9749,8 @@ +} + +#include "../selftest/curve25519.h" ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/crypto/blake2s.h 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/crypto/blake2s.h 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,94 @@ +/* SPDX-License-Identifier: GPL-2.0 + * @@ -9846,8 +9846,8 @@ +#endif + +#endif /* _WG_BLAKE2S_H */ ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/crypto/chacha20poly1305.h 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/crypto/chacha20poly1305.h 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,93 @@ +/* SPDX-License-Identifier: GPL-2.0 + * @@ -9942,8 +9942,8 @@ +#endif + +#endif /* _WG_CHACHA20POLY1305_H */ ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/crypto/curve25519-arm.h 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/crypto/curve25519-arm.h 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0 + * @@ -9954,13 +9954,13 @@ +#include +#include +asmlinkage void curve25519_neon(u8 mypublic[CURVE25519_POINT_SIZE], const u8 secret[CURVE25519_POINT_SIZE], const u8 basepoint[CURVE25519_POINT_SIZE]); -+static bool curve25519_use_neon __read_mostly; ++static bool curve25519_use_neon __ro_after_init; +void __init curve25519_fpu_init(void) +{ + curve25519_use_neon = elf_hwcap & HWCAP_NEON; +} ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/crypto/curve25519-fiat32.h 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/crypto/curve25519-fiat32.h 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,838 @@ +/* SPDX-License-Identifier: GPL-2.0 + * @@ -10800,8 +10800,8 @@ + memzero_explicit(&tmp1l, sizeof(tmp1l)); + memzero_explicit(&e, sizeof(e)); +} ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/crypto/curve25519.h 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/crypto/curve25519.h 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0 + * @@ -10828,8 +10828,8 @@ +#endif + +#endif /* _WG_CURVE25519_H */ ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/crypto/curve25519-hacl64.h 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/crypto/curve25519-hacl64.h 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,751 @@ +/* SPDX-License-Identifier: GPL-2.0 + * @@ -11582,9 +11582,9 @@ + } + memzero_explicit(buf0, sizeof(buf0)); +} ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/crypto/curve25519-x86_64.h 2018-02-18 22:22:31.000000000 +0200 -@@ -0,0 +1,175 @@ +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/crypto/curve25519-x86_64.h 2018-03-04 19:51:33.000000000 +0200 +@@ -0,0 +1,176 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2015-2018 Jason A. Donenfeld . All Rights Reserved. @@ -11596,7 +11596,8 @@ +#include +#include +#include -+static bool curve25519_use_avx __read_mostly; ++ ++static bool curve25519_use_avx __ro_after_init; +void __init curve25519_fpu_init(void) +{ +#ifndef CONFIG_UML @@ -11760,8 +11761,8 @@ + memzero_explicit(x_51, sizeof(x_51)); + memzero_explicit(z_51, sizeof(z_51)); +} ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/crypto/blake2s-x86_64.S 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/crypto/blake2s-x86_64.S 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,685 @@ +/* SPDX-License-Identifier: GPL-2.0 + * @@ -12448,8 +12449,8 @@ + retq +ENDPROC(blake2s_compress_avx512) +#endif /* CONFIG_AS_AVX512 */ ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/crypto/chacha20-arm64.S 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/crypto/chacha20-arm64.S 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,1940 @@ +/* SPDX-License-Identifier: OpenSSL OR (BSD-3-Clause OR GPL-2.0) + * @@ -14391,8 +14392,8 @@ +.Labort_neon: + ret +ENDPROC(chacha20_neon) ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/crypto/chacha20-arm.S 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/crypto/chacha20-arm.S 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,1471 @@ +/* SPDX-License-Identifier: OpenSSL OR (BSD-3-Clause OR GPL-2.0) + * @@ -15865,8 +15866,8 @@ +.Lno_data_arm: + ldmia sp!,{r4-r11,pc} +ENDPROC(chacha20_arm) ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/crypto/chacha20-x86_64.S 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/crypto/chacha20-x86_64.S 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,2630 @@ +/* SPDX-License-Identifier: OpenSSL OR (BSD-3-Clause OR GPL-2.0) + * @@ -18498,8 +18499,8 @@ +ENDPROC(chacha20_avx512vl) + +#endif /* CONFIG_AS_AVX512 */ ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/crypto/curve25519-arm.S 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/crypto/curve25519-arm.S 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,2110 @@ +/* SPDX-License-Identifier: GPL-2.0 + * @@ -20611,8 +20612,8 @@ + bx lr +ENDPROC(curve25519_neon) +#endif ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/crypto/curve25519-x86_64.S 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/crypto/curve25519-x86_64.S 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,3261 @@ +/* SPDX-License-Identifier: GPL-2.0 + * @@ -23875,8 +23876,8 @@ + ret +ENDPROC(curve25519_sandy2x_ladder_base) +#endif /* CONFIG_AS_AVX */ ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/crypto/poly1305-arm64.S 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/crypto/poly1305-arm64.S 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,820 @@ +/* SPDX-License-Identifier: OpenSSL OR (BSD-3-Clause OR GPL-2.0) + * @@ -24698,8 +24699,8 @@ +.align 5 +.Lzeros: +.long 0,0,0,0,0,0,0,0 ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/crypto/poly1305-arm.S 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/crypto/poly1305-arm.S 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,1115 @@ +/* SPDX-License-Identifier: OpenSSL OR (BSD-3-Clause OR GPL-2.0) + * @@ -25816,8 +25817,8 @@ +.Lzeros: +.long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +#endif ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/crypto/poly1305-mips64.S 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/crypto/poly1305-mips64.S 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,357 @@ +/* SPDX-License-Identifier: OpenSSL OR (BSD-3-Clause OR GPL-2.0) + * @@ -26176,8 +26177,8 @@ + + jr $31 +.end poly1305_emit_mips ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/crypto/poly1305-x86_64.S 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/crypto/poly1305-x86_64.S 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,2803 @@ +/* SPDX-License-Identifier: OpenSSL OR (BSD-3-Clause OR GPL-2.0) + * @@ -28982,8 +28983,8 @@ + +ENDPROC(poly1305_blocks_avx512) +#endif /* CONFIG_AS_AVX512 */ ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/Makefile 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/Makefile 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0 +# @@ -29004,13 +29005,14 @@ +include $(src)/compat/Makefile.include + +obj-$(if $(KBUILD_EXTMOD),m,$(CONFIG_WIREGUARD)) := wireguard.o ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/Kconfig 2018-02-18 22:22:31.000000000 +0200 -@@ -0,0 +1,30 @@ +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/Kconfig 2018-03-04 19:51:33.000000000 +0200 +@@ -0,0 +1,31 @@ +config WIREGUARD + tristate "IP: WireGuard secure network tunnel" + depends on NET && INET + select NET_UDP_TUNNEL ++ select DST_CACHE + select CRYPTO_BLKCIPHER + select VFP + select VFPv3 @@ -29037,12 +29039,12 @@ + only useful for debugging. + + Say N here unless you know what you're doing. ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/compat/simd/include/asm/simd.h 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/compat/simd/include/asm/simd.h 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1 @@ +#include ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/compat/udp_tunnel/udp_tunnel_partial_compat.h 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/compat/udp_tunnel/udp_tunnel_partial_compat.h 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,226 @@ +/* SPDX-License-Identifier: GPL-2.0 + * @@ -29270,8 +29272,8 @@ +#define udp_port_cfg udp_port_cfg_new +#define udp_sock_create(a, b, c) udp_sock_create_new(a, b, c) +#endif ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/compat/udp_tunnel/include/net/udp_tunnel.h 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/compat/udp_tunnel/include/net/udp_tunnel.h 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,94 @@ +#ifndef _WG_NET_UDP_TUNNEL_H +#define _WG_NET_UDP_TUNNEL_H @@ -29367,8 +29369,8 @@ +void udp_tunnel_sock_release(struct socket *sock); + +#endif /* _WG_NET_UDP_TUNNEL_H */ ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/compat/udp_tunnel/udp_tunnel.c 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/compat/udp_tunnel/udp_tunnel.c 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,385 @@ +#include +#include @@ -29755,12 +29757,12 @@ + return 0; +} +#endif ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/compat/fpu/include/asm/fpu/api.h 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/compat/fpu/include/asm/fpu/api.h 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1 @@ +#include ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/compat/checksum/checksum_partial_compat.h 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/compat/checksum/checksum_partial_compat.h 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,208 @@ +/* SPDX-License-Identifier: GPL-2.0 + * @@ -29970,21 +29972,22 @@ + } + return err; +} ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/compat/Makefile.include 2018-02-18 22:22:31.000000000 +0200 -@@ -0,0 +1,70 @@ +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/compat/Makefile.include 2018-03-04 19:51:33.000000000 +0200 +@@ -0,0 +1,71 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright (C) 2015-2018 Jason A. Donenfeld . All Rights Reserved. + +ifeq ($(wildcard $(src)/compat/compat.h),) -+ccflags-y += -include $(srctree)/$(src)/compat/compat.h -+asflags-y += -include $(srctree)/$(src)/compat/compat-asm.h ++cmd_include_path_prefix := $(srctree)/$(src) +else -+ccflags-y += -include $(src)/compat/compat.h -+asflags-y += -include $(src)/compat/compat-asm.h ++cmd_include_path_prefix := $(src) +endif + ++ccflags-y += -include $(cmd_include_path_prefix)/compat/compat.h ++asflags-y += -include $(cmd_include_path_prefix)/compat/compat-asm.h ++ +ifeq ($(wildcard $(srctree)/include/linux/ptr_ring.h),) +ccflags-y += -I$(src)/compat/ptr_ring/include +endif @@ -30017,7 +30020,7 @@ +endif + +ifeq ($(shell grep -F "int crypto_memneq" "$(srctree)/include/crypto/algapi.h"),) -+ccflags-y += -include $(src)/compat/memneq/include.h ++ccflags-y += -include $(cmd_include_path_prefix)/compat/memneq/include.h +wireguard-y += compat/memneq/memneq.o +endif + @@ -30043,8 +30046,8 @@ + asflags-y += $(avx512_instr) + endif +endif ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/compat/siphash/siphash.c 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/compat/siphash/siphash.c 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,539 @@ +/* Copyright (C) 2015-2018 Jason A. Donenfeld . All Rights Reserved. + * @@ -30585,8 +30588,8 @@ + HPOSTAMBLE +} +#endif ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/compat/siphash/include/linux/siphash.h 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/compat/siphash/include/linux/siphash.h 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,140 @@ +/* Copyright (C) 2015-2018 Jason A. Donenfeld . All Rights Reserved. + * @@ -30728,8 +30731,8 @@ +} + +#endif /* _WG_LINUX_SIPHASH_H */ ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/compat/intel-family/include/asm/intel-family.h 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/compat/intel-family/include/asm/intel-family.h 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,73 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_X86_INTEL_FAMILY_H @@ -30804,8 +30807,8 @@ +#define INTEL_FAM6_XEON_PHI_KNM 0x85 /* Knights Mill */ + +#endif /* _ASM_X86_INTEL_FAMILY_H */ ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/compat/compat.h 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/compat/compat.h 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,632 @@ +/* SPDX-License-Identifier: GPL-2.0 + * @@ -31291,7 +31294,7 @@ +#else +#define ___COMPAT_NETLINK_DUMP_BLOCK return get_device_dump_real(skb, cb); +#endif -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 14) && LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)) || LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 63) ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 16, 0) +#define get_device_dump(a, b) get_device_dump_real(a, b); \ +static int get_device_dump(a, b) { \ + struct wireguard_device *wg = (struct wireguard_device *)cb->args[0]; \ @@ -31439,8 +31442,8 @@ +#endif + +#endif /* _WG_COMPAT_H */ ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/compat/ptr_ring/include/linux/ptr_ring.h 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/compat/ptr_ring/include/linux/ptr_ring.h 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,640 @@ +/* + * Definitions for the 'struct ptr_ring' datastructure. @@ -32082,16 +32085,16 @@ +} + +#endif /* _LINUX_PTR_RING_H */ ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/compat/memneq/include.h 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/compat/memneq/include.h 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,5 @@ +extern noinline unsigned long __crypto_memneq(const void *a, const void *b, size_t size); +static inline int crypto_memneq(const void *a, const void *b, size_t size) +{ + return __crypto_memneq(a, b, size) != 0UL ? 1 : 0; +} ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/compat/memneq/memneq.c 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/compat/memneq/memneq.c 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,170 @@ +/* + * Constant-time equality testing of memory regions. @@ -32157,7 +32160,7 @@ +#include + +/* Make the optimizer believe the variable can be manipulated arbitrarily. */ -+#define COMPILER_OPTIMIZER_HIDE_VAR(var) __asm__ ("" : "=r" (var) : "0" (var)) ++#define COMPILER_OPTIMIZER_HIDE_VAR(var) asm("" : "=r" (var) : "0" (var)) + +#ifndef __HAVE_ARCH_CRYPTO_MEMNEQ + @@ -32263,8 +32266,8 @@ +} + +#endif /* __HAVE_ARCH_CRYPTO_MEMNEQ */ ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/compat/dst_cache/dst_cache.c 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/compat/dst_cache/dst_cache.c 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,175 @@ +/* + * net/core/dst_cache.c - dst entry cache @@ -32441,8 +32444,8 @@ + + free_percpu(dst_cache->cache); +} ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/compat/dst_cache/include/net/dst_cache.h 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/compat/dst_cache/include/net/dst_cache.h 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,97 @@ +#ifndef _WG_NET_DST_CACHE_H +#define _WG_NET_DST_CACHE_H @@ -32541,8 +32544,8 @@ +void dst_cache_destroy(struct dst_cache *dst_cache); + +#endif /* _WG_NET_DST_CACHE_H */ ---- /dev/null 2018-02-18 13:06:28.903837808 +0200 -+++ b/net/wireguard/compat/compat-asm.h 2018-02-18 22:22:31.000000000 +0200 +--- /dev/null 2018-03-04 21:55:12.891724619 +0200 ++++ b/net/wireguard/compat/compat-asm.h 2018-03-04 19:51:33.000000000 +0200 @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0 + * diff --git a/kernel/tools/cpupowertools/files/patches/mageia/net-netfilter-add-back-stackpointer-size-checks.patch b/kernel/tools/cpupowertools/files/patches/mageia/net-netfilter-add-back-stackpointer-size-checks.patch new file mode 100644 index 00000000..56c0f51b --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/mageia/net-netfilter-add-back-stackpointer-size-checks.patch @@ -0,0 +1,84 @@ +From 57ebd808a97d7c5b1e1afb937c2db22beba3c1f8 Mon Sep 17 00:00:00 2001 +From: Florian Westphal +Date: Wed, 7 Feb 2018 13:46:25 +0100 +Subject: [PATCH] netfilter: add back stackpointer size checks + +The rationale for removing the check is only correct for rulesets +generated by ip(6)tables. + +In iptables, a jump can only occur to a user-defined chain, i.e. +because we size the stack based on number of user-defined chains we +cannot exceed stack size. + +However, the underlying binary format has no such restriction, +and the validation step only ensures that the jump target is a +valid rule start point. + +IOW, its possible to build a rule blob that has no user-defined +chains but does contain a jump. + +If this happens, no jump stack gets allocated and crash occurs +because no jumpstack was allocated. + +Fixes: 7814b6ec6d0d6 ("netfilter: xtables: don't save/restore jumpstack offset") +Reported-by: syzbot+e783f671527912cd9403@syzkaller.appspotmail.com +Signed-off-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +--- + net/ipv4/netfilter/arp_tables.c | 4 ++++ + net/ipv4/netfilter/ip_tables.c | 7 ++++++- + net/ipv6/netfilter/ip6_tables.c | 4 ++++ + 3 files changed, 14 insertions(+), 1 deletion(-) + +diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c +index 4ffe302f9b82..e3e420f3ba7b 100644 +--- a/net/ipv4/netfilter/arp_tables.c ++++ b/net/ipv4/netfilter/arp_tables.c +@@ -252,6 +252,10 @@ unsigned int arpt_do_table(struct sk_buff *skb, + } + if (table_base + v + != arpt_next_entry(e)) { ++ if (unlikely(stackidx >= private->stacksize)) { ++ verdict = NF_DROP; ++ break; ++ } + jumpstack[stackidx++] = e; + } + +diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c +index 9a71f3149507..e38395a8dcf2 100644 +--- a/net/ipv4/netfilter/ip_tables.c ++++ b/net/ipv4/netfilter/ip_tables.c +@@ -330,8 +330,13 @@ ipt_do_table(struct sk_buff *skb, + continue; + } + if (table_base + v != ipt_next_entry(e) && +- !(e->ip.flags & IPT_F_GOTO)) ++ !(e->ip.flags & IPT_F_GOTO)) { ++ if (unlikely(stackidx >= private->stacksize)) { ++ verdict = NF_DROP; ++ break; ++ } + jumpstack[stackidx++] = e; ++ } + + e = get_entry(table_base, v); + continue; +diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c +index af4c917e0836..62358b93bbac 100644 +--- a/net/ipv6/netfilter/ip6_tables.c ++++ b/net/ipv6/netfilter/ip6_tables.c +@@ -352,6 +352,10 @@ ip6t_do_table(struct sk_buff *skb, + } + if (table_base + v != ip6t_next_entry(e) && + !(e->ipv6.flags & IP6T_F_GOTO)) { ++ if (unlikely(stackidx >= private->stacksize)) { ++ verdict = NF_DROP; ++ break; ++ } + jumpstack[stackidx++] = e; + } + +-- +2.16.2 + diff --git a/kernel/tools/cpupowertools/files/patches/mageia/patch-4.14.25-rc1.patch b/kernel/tools/cpupowertools/files/patches/mageia/patch-4.14.25-rc1.patch new file mode 100644 index 00000000..3246762b --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/mageia/patch-4.14.25-rc1.patch @@ -0,0 +1,4181 @@ +diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt +index 77f4de59dc9c..d499676890d8 100644 +--- a/Documentation/networking/ip-sysctl.txt ++++ b/Documentation/networking/ip-sysctl.txt +@@ -508,7 +508,7 @@ tcp_rmem - vector of 3 INTEGERs: min, default, max + min: Minimal size of receive buffer used by TCP sockets. + It is guaranteed to each TCP socket, even under moderate memory + pressure. +- Default: 1 page ++ Default: 4K + + default: initial size of receive buffer used by TCP sockets. + This value overrides net.core.rmem_default used by other protocols. +@@ -666,7 +666,7 @@ tcp_window_scaling - BOOLEAN + tcp_wmem - vector of 3 INTEGERs: min, default, max + min: Amount of memory reserved for send buffers for TCP sockets. + Each TCP socket has rights to use it due to fact of its birth. +- Default: 1 page ++ Default: 4K + + default: initial size of send buffer used by TCP sockets. This + value overrides net.core.wmem_default used by other protocols. +diff --git a/arch/arm/boot/dts/logicpd-som-lv.dtsi b/arch/arm/boot/dts/logicpd-som-lv.dtsi +index 4f2c5ec75714..e262fa9ef334 100644 +--- a/arch/arm/boot/dts/logicpd-som-lv.dtsi ++++ b/arch/arm/boot/dts/logicpd-som-lv.dtsi +@@ -97,6 +97,8 @@ + }; + + &i2c1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c1_pins>; + clock-frequency = <2600000>; + + twl: twl@48 { +@@ -215,7 +217,12 @@ + >; + }; + +- ++ i2c1_pins: pinmux_i2c1_pins { ++ pinctrl-single,pins = < ++ OMAP3_CORE1_IOPAD(0x21ba, PIN_INPUT | MUX_MODE0) /* i2c1_scl.i2c1_scl */ ++ OMAP3_CORE1_IOPAD(0x21bc, PIN_INPUT | MUX_MODE0) /* i2c1_sda.i2c1_sda */ ++ >; ++ }; + }; + + &omap3_pmx_wkup { +diff --git a/arch/arm/boot/dts/logicpd-torpedo-som.dtsi b/arch/arm/boot/dts/logicpd-torpedo-som.dtsi +index 6d89736c7b44..cf22b35f0a28 100644 +--- a/arch/arm/boot/dts/logicpd-torpedo-som.dtsi ++++ b/arch/arm/boot/dts/logicpd-torpedo-som.dtsi +@@ -104,6 +104,8 @@ + }; + + &i2c1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c1_pins>; + clock-frequency = <2600000>; + + twl: twl@48 { +@@ -211,6 +213,12 @@ + OMAP3_CORE1_IOPAD(0x21b8, PIN_INPUT | MUX_MODE0) /* hsusb0_data7.hsusb0_data7 */ + >; + }; ++ i2c1_pins: pinmux_i2c1_pins { ++ pinctrl-single,pins = < ++ OMAP3_CORE1_IOPAD(0x21ba, PIN_INPUT | MUX_MODE0) /* i2c1_scl.i2c1_scl */ ++ OMAP3_CORE1_IOPAD(0x21bc, PIN_INPUT | MUX_MODE0) /* i2c1_sda.i2c1_sda */ ++ >; ++ }; + }; + + &uart2 { +diff --git a/arch/arm/boot/dts/rk3288-phycore-som.dtsi b/arch/arm/boot/dts/rk3288-phycore-som.dtsi +index 99cfae875e12..5eae4776ffde 100644 +--- a/arch/arm/boot/dts/rk3288-phycore-som.dtsi ++++ b/arch/arm/boot/dts/rk3288-phycore-som.dtsi +@@ -110,26 +110,6 @@ + }; + }; + +-&cpu0 { +- cpu0-supply = <&vdd_cpu>; +- operating-points = < +- /* KHz uV */ +- 1800000 1400000 +- 1608000 1350000 +- 1512000 1300000 +- 1416000 1200000 +- 1200000 1100000 +- 1008000 1050000 +- 816000 1000000 +- 696000 950000 +- 600000 900000 +- 408000 900000 +- 312000 900000 +- 216000 900000 +- 126000 900000 +- >; +-}; +- + &emmc { + status = "okay"; + bus-width = <8>; +diff --git a/arch/arm/kvm/hyp/Makefile b/arch/arm/kvm/hyp/Makefile +index 5638ce0c9524..63d6b404d88e 100644 +--- a/arch/arm/kvm/hyp/Makefile ++++ b/arch/arm/kvm/hyp/Makefile +@@ -7,6 +7,8 @@ ccflags-y += -fno-stack-protector -DDISABLE_BRANCH_PROFILING + + KVM=../../../../virt/kvm + ++CFLAGS_ARMV7VE :=$(call cc-option, -march=armv7ve) ++ + obj-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/hyp/vgic-v2-sr.o + obj-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/hyp/vgic-v3-sr.o + obj-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/hyp/timer-sr.o +@@ -15,7 +17,10 @@ obj-$(CONFIG_KVM_ARM_HOST) += tlb.o + obj-$(CONFIG_KVM_ARM_HOST) += cp15-sr.o + obj-$(CONFIG_KVM_ARM_HOST) += vfp.o + obj-$(CONFIG_KVM_ARM_HOST) += banked-sr.o ++CFLAGS_banked-sr.o += $(CFLAGS_ARMV7VE) ++ + obj-$(CONFIG_KVM_ARM_HOST) += entry.o + obj-$(CONFIG_KVM_ARM_HOST) += hyp-entry.o + obj-$(CONFIG_KVM_ARM_HOST) += switch.o ++CFLAGS_switch.o += $(CFLAGS_ARMV7VE) + obj-$(CONFIG_KVM_ARM_HOST) += s2-setup.o +diff --git a/arch/arm/kvm/hyp/banked-sr.c b/arch/arm/kvm/hyp/banked-sr.c +index 111bda8cdebd..be4b8b0a40ad 100644 +--- a/arch/arm/kvm/hyp/banked-sr.c ++++ b/arch/arm/kvm/hyp/banked-sr.c +@@ -20,6 +20,10 @@ + + #include + ++/* ++ * gcc before 4.9 doesn't understand -march=armv7ve, so we have to ++ * trick the assembler. ++ */ + __asm__(".arch_extension virt"); + + void __hyp_text __banked_save_state(struct kvm_cpu_context *ctxt) +diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig +index 9b49867154bf..63fa79f9f121 100644 +--- a/arch/arm/mach-mvebu/Kconfig ++++ b/arch/arm/mach-mvebu/Kconfig +@@ -42,7 +42,7 @@ config MACH_ARMADA_375 + depends on ARCH_MULTI_V7 + select ARMADA_370_XP_IRQ + select ARM_ERRATA_720789 +- select ARM_ERRATA_753970 ++ select PL310_ERRATA_753970 + select ARM_GIC + select ARMADA_375_CLK + select HAVE_ARM_SCU +@@ -58,7 +58,7 @@ config MACH_ARMADA_38X + bool "Marvell Armada 380/385 boards" + depends on ARCH_MULTI_V7 + select ARM_ERRATA_720789 +- select ARM_ERRATA_753970 ++ select PL310_ERRATA_753970 + select ARM_GIC + select ARM_GLOBAL_TIMER + select CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK +diff --git a/arch/arm/plat-orion/common.c b/arch/arm/plat-orion/common.c +index aff6994950ba..a2399fd66e97 100644 +--- a/arch/arm/plat-orion/common.c ++++ b/arch/arm/plat-orion/common.c +@@ -472,28 +472,27 @@ void __init orion_ge11_init(struct mv643xx_eth_platform_data *eth_data, + /***************************************************************************** + * Ethernet switch + ****************************************************************************/ +-static __initconst const char *orion_ge00_mvmdio_bus_name = "orion-mii"; +-static __initdata struct mdio_board_info +- orion_ge00_switch_board_info; ++static __initdata struct mdio_board_info orion_ge00_switch_board_info = { ++ .bus_id = "orion-mii", ++ .modalias = "mv88e6085", ++}; + + void __init orion_ge00_switch_init(struct dsa_chip_data *d) + { +- struct mdio_board_info *bd; + unsigned int i; + + if (!IS_BUILTIN(CONFIG_PHYLIB)) + return; + +- for (i = 0; i < ARRAY_SIZE(d->port_names); i++) +- if (!strcmp(d->port_names[i], "cpu")) ++ for (i = 0; i < ARRAY_SIZE(d->port_names); i++) { ++ if (!strcmp(d->port_names[i], "cpu")) { ++ d->netdev[i] = &orion_ge00.dev; + break; ++ } ++ } + +- bd = &orion_ge00_switch_board_info; +- bd->bus_id = orion_ge00_mvmdio_bus_name; +- bd->mdio_addr = d->sw_addr; +- d->netdev[i] = &orion_ge00.dev; +- strcpy(bd->modalias, "mv88e6085"); +- bd->platform_data = d; ++ orion_ge00_switch_board_info.mdio_addr = d->sw_addr; ++ orion_ge00_switch_board_info.platform_data = d; + + mdiobus_register_board_info(&orion_ge00_switch_board_info, 1); + } +diff --git a/arch/parisc/include/asm/cacheflush.h b/arch/parisc/include/asm/cacheflush.h +index 3742508cc534..bd5ce31936f5 100644 +--- a/arch/parisc/include/asm/cacheflush.h ++++ b/arch/parisc/include/asm/cacheflush.h +@@ -26,6 +26,7 @@ void flush_user_icache_range_asm(unsigned long, unsigned long); + void flush_kernel_icache_range_asm(unsigned long, unsigned long); + void flush_user_dcache_range_asm(unsigned long, unsigned long); + void flush_kernel_dcache_range_asm(unsigned long, unsigned long); ++void purge_kernel_dcache_range_asm(unsigned long, unsigned long); + void flush_kernel_dcache_page_asm(void *); + void flush_kernel_icache_page(void *); + +diff --git a/arch/parisc/include/asm/processor.h b/arch/parisc/include/asm/processor.h +index 0e6ab6e4a4e9..2dbe5580a1a4 100644 +--- a/arch/parisc/include/asm/processor.h ++++ b/arch/parisc/include/asm/processor.h +@@ -316,6 +316,8 @@ extern int _parisc_requires_coherency; + #define parisc_requires_coherency() (0) + #endif + ++extern int running_on_qemu; ++ + #endif /* __ASSEMBLY__ */ + + #endif /* __ASM_PARISC_PROCESSOR_H */ +diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c +index 19c0c141bc3f..79089778725b 100644 +--- a/arch/parisc/kernel/cache.c ++++ b/arch/parisc/kernel/cache.c +@@ -465,10 +465,10 @@ EXPORT_SYMBOL(copy_user_page); + int __flush_tlb_range(unsigned long sid, unsigned long start, + unsigned long end) + { +- unsigned long flags, size; ++ unsigned long flags; + +- size = (end - start); +- if (size >= parisc_tlb_flush_threshold) { ++ if ((!IS_ENABLED(CONFIG_SMP) || !arch_irqs_disabled()) && ++ end - start >= parisc_tlb_flush_threshold) { + flush_tlb_all(); + return 1; + } +@@ -539,13 +539,11 @@ void flush_cache_mm(struct mm_struct *mm) + struct vm_area_struct *vma; + pgd_t *pgd; + +- /* Flush the TLB to avoid speculation if coherency is required. */ +- if (parisc_requires_coherency()) +- flush_tlb_all(); +- + /* Flushing the whole cache on each cpu takes forever on + rp3440, etc. So, avoid it if the mm isn't too big. */ +- if (mm_total_size(mm) >= parisc_cache_flush_threshold) { ++ if ((!IS_ENABLED(CONFIG_SMP) || !arch_irqs_disabled()) && ++ mm_total_size(mm) >= parisc_cache_flush_threshold) { ++ flush_tlb_all(); + flush_cache_all(); + return; + } +@@ -553,9 +551,9 @@ void flush_cache_mm(struct mm_struct *mm) + if (mm->context == mfsp(3)) { + for (vma = mm->mmap; vma; vma = vma->vm_next) { + flush_user_dcache_range_asm(vma->vm_start, vma->vm_end); +- if ((vma->vm_flags & VM_EXEC) == 0) +- continue; +- flush_user_icache_range_asm(vma->vm_start, vma->vm_end); ++ if (vma->vm_flags & VM_EXEC) ++ flush_user_icache_range_asm(vma->vm_start, vma->vm_end); ++ flush_tlb_range(vma, vma->vm_start, vma->vm_end); + } + return; + } +@@ -581,14 +579,9 @@ void flush_cache_mm(struct mm_struct *mm) + void flush_cache_range(struct vm_area_struct *vma, + unsigned long start, unsigned long end) + { +- BUG_ON(!vma->vm_mm->context); +- +- /* Flush the TLB to avoid speculation if coherency is required. */ +- if (parisc_requires_coherency()) ++ if ((!IS_ENABLED(CONFIG_SMP) || !arch_irqs_disabled()) && ++ end - start >= parisc_cache_flush_threshold) { + flush_tlb_range(vma, start, end); +- +- if ((end - start) >= parisc_cache_flush_threshold +- || vma->vm_mm->context != mfsp(3)) { + flush_cache_all(); + return; + } +@@ -596,6 +589,7 @@ void flush_cache_range(struct vm_area_struct *vma, + flush_user_dcache_range_asm(start, end); + if (vma->vm_flags & VM_EXEC) + flush_user_icache_range_asm(start, end); ++ flush_tlb_range(vma, start, end); + } + + void +@@ -604,8 +598,7 @@ flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long + BUG_ON(!vma->vm_mm->context); + + if (pfn_valid(pfn)) { +- if (parisc_requires_coherency()) +- flush_tlb_page(vma, vmaddr); ++ flush_tlb_page(vma, vmaddr); + __flush_cache_page(vma, vmaddr, PFN_PHYS(pfn)); + } + } +@@ -613,21 +606,33 @@ flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long + void flush_kernel_vmap_range(void *vaddr, int size) + { + unsigned long start = (unsigned long)vaddr; ++ unsigned long end = start + size; + +- if ((unsigned long)size > parisc_cache_flush_threshold) ++ if ((!IS_ENABLED(CONFIG_SMP) || !arch_irqs_disabled()) && ++ (unsigned long)size >= parisc_cache_flush_threshold) { ++ flush_tlb_kernel_range(start, end); + flush_data_cache(); +- else +- flush_kernel_dcache_range_asm(start, start + size); ++ return; ++ } ++ ++ flush_kernel_dcache_range_asm(start, end); ++ flush_tlb_kernel_range(start, end); + } + EXPORT_SYMBOL(flush_kernel_vmap_range); + + void invalidate_kernel_vmap_range(void *vaddr, int size) + { + unsigned long start = (unsigned long)vaddr; ++ unsigned long end = start + size; + +- if ((unsigned long)size > parisc_cache_flush_threshold) ++ if ((!IS_ENABLED(CONFIG_SMP) || !arch_irqs_disabled()) && ++ (unsigned long)size >= parisc_cache_flush_threshold) { ++ flush_tlb_kernel_range(start, end); + flush_data_cache(); +- else +- flush_kernel_dcache_range_asm(start, start + size); ++ return; ++ } ++ ++ purge_kernel_dcache_range_asm(start, end); ++ flush_tlb_kernel_range(start, end); + } + EXPORT_SYMBOL(invalidate_kernel_vmap_range); +diff --git a/arch/parisc/kernel/pacache.S b/arch/parisc/kernel/pacache.S +index 2d40c4ff3f69..67b0f7532e83 100644 +--- a/arch/parisc/kernel/pacache.S ++++ b/arch/parisc/kernel/pacache.S +@@ -1110,6 +1110,28 @@ ENTRY_CFI(flush_kernel_dcache_range_asm) + .procend + ENDPROC_CFI(flush_kernel_dcache_range_asm) + ++ENTRY_CFI(purge_kernel_dcache_range_asm) ++ .proc ++ .callinfo NO_CALLS ++ .entry ++ ++ ldil L%dcache_stride, %r1 ++ ldw R%dcache_stride(%r1), %r23 ++ ldo -1(%r23), %r21 ++ ANDCM %r26, %r21, %r26 ++ ++1: cmpb,COND(<<),n %r26, %r25,1b ++ pdc,m %r23(%r26) ++ ++ sync ++ syncdma ++ bv %r0(%r2) ++ nop ++ .exit ++ ++ .procend ++ENDPROC_CFI(purge_kernel_dcache_range_asm) ++ + ENTRY_CFI(flush_user_icache_range_asm) + .proc + .callinfo NO_CALLS +diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c +index 4b8fd6dc22da..f7e684560186 100644 +--- a/arch/parisc/kernel/time.c ++++ b/arch/parisc/kernel/time.c +@@ -76,10 +76,10 @@ irqreturn_t __irq_entry timer_interrupt(int irq, void *dev_id) + next_tick = cpuinfo->it_value; + + /* Calculate how many ticks have elapsed. */ ++ now = mfctl(16); + do { + ++ticks_elapsed; + next_tick += cpt; +- now = mfctl(16); + } while (next_tick - now > cpt); + + /* Store (in CR16 cycles) up to when we are accounting right now. */ +@@ -103,16 +103,17 @@ irqreturn_t __irq_entry timer_interrupt(int irq, void *dev_id) + * if one or the other wrapped. If "now" is "bigger" we'll end up + * with a very large unsigned number. + */ +- while (next_tick - mfctl(16) > cpt) ++ now = mfctl(16); ++ while (next_tick - now > cpt) + next_tick += cpt; + + /* Program the IT when to deliver the next interrupt. + * Only bottom 32-bits of next_tick are writable in CR16! + * Timer interrupt will be delivered at least a few hundred cycles +- * after the IT fires, so if we are too close (<= 500 cycles) to the ++ * after the IT fires, so if we are too close (<= 8000 cycles) to the + * next cycle, simply skip it. + */ +- if (next_tick - mfctl(16) <= 500) ++ if (next_tick - now <= 8000) + next_tick += cpt; + mtctl(next_tick, 16); + +@@ -248,7 +249,7 @@ static int __init init_cr16_clocksource(void) + * different sockets, so mark them unstable and lower rating on + * multi-socket SMP systems. + */ +- if (num_online_cpus() > 1) { ++ if (num_online_cpus() > 1 && !running_on_qemu) { + int cpu; + unsigned long cpu0_loc; + cpu0_loc = per_cpu(cpu_data, 0).cpu_loc; +diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c +index a832ad031cee..5185be314661 100644 +--- a/arch/s390/kvm/interrupt.c ++++ b/arch/s390/kvm/interrupt.c +@@ -173,8 +173,15 @@ static int ckc_interrupts_enabled(struct kvm_vcpu *vcpu) + + static int ckc_irq_pending(struct kvm_vcpu *vcpu) + { +- if (vcpu->arch.sie_block->ckc >= kvm_s390_get_tod_clock_fast(vcpu->kvm)) ++ const u64 now = kvm_s390_get_tod_clock_fast(vcpu->kvm); ++ const u64 ckc = vcpu->arch.sie_block->ckc; ++ ++ if (vcpu->arch.sie_block->gcr[0] & 0x0020000000000000ul) { ++ if ((s64)ckc >= (s64)now) ++ return 0; ++ } else if (ckc >= now) { + return 0; ++ } + return ckc_interrupts_enabled(vcpu); + } + +@@ -1004,13 +1011,19 @@ int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu) + + static u64 __calculate_sltime(struct kvm_vcpu *vcpu) + { +- u64 now, cputm, sltime = 0; ++ const u64 now = kvm_s390_get_tod_clock_fast(vcpu->kvm); ++ const u64 ckc = vcpu->arch.sie_block->ckc; ++ u64 cputm, sltime = 0; + + if (ckc_interrupts_enabled(vcpu)) { +- now = kvm_s390_get_tod_clock_fast(vcpu->kvm); +- sltime = tod_to_ns(vcpu->arch.sie_block->ckc - now); +- /* already expired or overflow? */ +- if (!sltime || vcpu->arch.sie_block->ckc <= now) ++ if (vcpu->arch.sie_block->gcr[0] & 0x0020000000000000ul) { ++ if ((s64)now < (s64)ckc) ++ sltime = tod_to_ns((s64)ckc - (s64)now); ++ } else if (now < ckc) { ++ sltime = tod_to_ns(ckc - now); ++ } ++ /* already expired */ ++ if (!sltime) + return 0; + if (cpu_timer_interrupts_enabled(vcpu)) { + cputm = kvm_s390_get_cpu_timer(vcpu); +diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c +index 6e3d80b2048e..f4f12ecd0cec 100644 +--- a/arch/s390/kvm/kvm-s390.c ++++ b/arch/s390/kvm/kvm-s390.c +@@ -169,6 +169,28 @@ int kvm_arch_hardware_enable(void) + static void kvm_gmap_notifier(struct gmap *gmap, unsigned long start, + unsigned long end); + ++static void kvm_clock_sync_scb(struct kvm_s390_sie_block *scb, u64 delta) ++{ ++ u8 delta_idx = 0; ++ ++ /* ++ * The TOD jumps by delta, we have to compensate this by adding ++ * -delta to the epoch. ++ */ ++ delta = -delta; ++ ++ /* sign-extension - we're adding to signed values below */ ++ if ((s64)delta < 0) ++ delta_idx = -1; ++ ++ scb->epoch += delta; ++ if (scb->ecd & ECD_MEF) { ++ scb->epdx += delta_idx; ++ if (scb->epoch < delta) ++ scb->epdx += 1; ++ } ++} ++ + /* + * This callback is executed during stop_machine(). All CPUs are therefore + * temporarily stopped. In order not to change guest behavior, we have to +@@ -184,13 +206,17 @@ static int kvm_clock_sync(struct notifier_block *notifier, unsigned long val, + unsigned long long *delta = v; + + list_for_each_entry(kvm, &vm_list, vm_list) { +- kvm->arch.epoch -= *delta; + kvm_for_each_vcpu(i, vcpu, kvm) { +- vcpu->arch.sie_block->epoch -= *delta; ++ kvm_clock_sync_scb(vcpu->arch.sie_block, *delta); ++ if (i == 0) { ++ kvm->arch.epoch = vcpu->arch.sie_block->epoch; ++ kvm->arch.epdx = vcpu->arch.sie_block->epdx; ++ } + if (vcpu->arch.cputm_enabled) + vcpu->arch.cputm_start += *delta; + if (vcpu->arch.vsie_block) +- vcpu->arch.vsie_block->epoch -= *delta; ++ kvm_clock_sync_scb(vcpu->arch.vsie_block, ++ *delta); + } + } + return NOTIFY_OK; +@@ -888,12 +914,9 @@ static int kvm_s390_set_tod_ext(struct kvm *kvm, struct kvm_device_attr *attr) + if (copy_from_user(>od, (void __user *)attr->addr, sizeof(gtod))) + return -EFAULT; + +- if (test_kvm_facility(kvm, 139)) +- kvm_s390_set_tod_clock_ext(kvm, >od); +- else if (gtod.epoch_idx == 0) +- kvm_s390_set_tod_clock(kvm, gtod.tod); +- else ++ if (!test_kvm_facility(kvm, 139) && gtod.epoch_idx) + return -EINVAL; ++ kvm_s390_set_tod_clock(kvm, >od); + + VM_EVENT(kvm, 3, "SET: TOD extension: 0x%x, TOD base: 0x%llx", + gtod.epoch_idx, gtod.tod); +@@ -918,13 +941,14 @@ static int kvm_s390_set_tod_high(struct kvm *kvm, struct kvm_device_attr *attr) + + static int kvm_s390_set_tod_low(struct kvm *kvm, struct kvm_device_attr *attr) + { +- u64 gtod; ++ struct kvm_s390_vm_tod_clock gtod = { 0 }; + +- if (copy_from_user(>od, (void __user *)attr->addr, sizeof(gtod))) ++ if (copy_from_user(>od.tod, (void __user *)attr->addr, ++ sizeof(gtod.tod))) + return -EFAULT; + +- kvm_s390_set_tod_clock(kvm, gtod); +- VM_EVENT(kvm, 3, "SET: TOD base: 0x%llx", gtod); ++ kvm_s390_set_tod_clock(kvm, >od); ++ VM_EVENT(kvm, 3, "SET: TOD base: 0x%llx", gtod.tod); + return 0; + } + +@@ -2359,6 +2383,7 @@ void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu) + mutex_lock(&vcpu->kvm->lock); + preempt_disable(); + vcpu->arch.sie_block->epoch = vcpu->kvm->arch.epoch; ++ vcpu->arch.sie_block->epdx = vcpu->kvm->arch.epdx; + preempt_enable(); + mutex_unlock(&vcpu->kvm->lock); + if (!kvm_is_ucontrol(vcpu->kvm)) { +@@ -2945,8 +2970,8 @@ static int kvm_s390_handle_requests(struct kvm_vcpu *vcpu) + return 0; + } + +-void kvm_s390_set_tod_clock_ext(struct kvm *kvm, +- const struct kvm_s390_vm_tod_clock *gtod) ++void kvm_s390_set_tod_clock(struct kvm *kvm, ++ const struct kvm_s390_vm_tod_clock *gtod) + { + struct kvm_vcpu *vcpu; + struct kvm_s390_tod_clock_ext htod; +@@ -2958,10 +2983,12 @@ void kvm_s390_set_tod_clock_ext(struct kvm *kvm, + get_tod_clock_ext((char *)&htod); + + kvm->arch.epoch = gtod->tod - htod.tod; +- kvm->arch.epdx = gtod->epoch_idx - htod.epoch_idx; +- +- if (kvm->arch.epoch > gtod->tod) +- kvm->arch.epdx -= 1; ++ kvm->arch.epdx = 0; ++ if (test_kvm_facility(kvm, 139)) { ++ kvm->arch.epdx = gtod->epoch_idx - htod.epoch_idx; ++ if (kvm->arch.epoch > gtod->tod) ++ kvm->arch.epdx -= 1; ++ } + + kvm_s390_vcpu_block_all(kvm); + kvm_for_each_vcpu(i, vcpu, kvm) { +@@ -2974,22 +3001,6 @@ void kvm_s390_set_tod_clock_ext(struct kvm *kvm, + mutex_unlock(&kvm->lock); + } + +-void kvm_s390_set_tod_clock(struct kvm *kvm, u64 tod) +-{ +- struct kvm_vcpu *vcpu; +- int i; +- +- mutex_lock(&kvm->lock); +- preempt_disable(); +- kvm->arch.epoch = tod - get_tod_clock(); +- kvm_s390_vcpu_block_all(kvm); +- kvm_for_each_vcpu(i, vcpu, kvm) +- vcpu->arch.sie_block->epoch = kvm->arch.epoch; +- kvm_s390_vcpu_unblock_all(kvm); +- preempt_enable(); +- mutex_unlock(&kvm->lock); +-} +- + /** + * kvm_arch_fault_in_page - fault-in guest page if necessary + * @vcpu: The corresponding virtual cpu +diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h +index 9f8fdd7b2311..e22d94f494a7 100644 +--- a/arch/s390/kvm/kvm-s390.h ++++ b/arch/s390/kvm/kvm-s390.h +@@ -272,9 +272,8 @@ int kvm_s390_handle_sigp_pei(struct kvm_vcpu *vcpu); + int handle_sthyi(struct kvm_vcpu *vcpu); + + /* implemented in kvm-s390.c */ +-void kvm_s390_set_tod_clock_ext(struct kvm *kvm, +- const struct kvm_s390_vm_tod_clock *gtod); +-void kvm_s390_set_tod_clock(struct kvm *kvm, u64 tod); ++void kvm_s390_set_tod_clock(struct kvm *kvm, ++ const struct kvm_s390_vm_tod_clock *gtod); + long kvm_arch_fault_in_page(struct kvm_vcpu *vcpu, gpa_t gpa, int writable); + int kvm_s390_store_status_unloaded(struct kvm_vcpu *vcpu, unsigned long addr); + int kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr); +diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c +index 7bd3a59232f0..734283a21677 100644 +--- a/arch/s390/kvm/priv.c ++++ b/arch/s390/kvm/priv.c +@@ -84,9 +84,10 @@ int kvm_s390_handle_e3(struct kvm_vcpu *vcpu) + /* Handle SCK (SET CLOCK) interception */ + static int handle_set_clock(struct kvm_vcpu *vcpu) + { ++ struct kvm_s390_vm_tod_clock gtod = { 0 }; + int rc; + u8 ar; +- u64 op2, val; ++ u64 op2; + + if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE) + return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP); +@@ -94,12 +95,12 @@ static int handle_set_clock(struct kvm_vcpu *vcpu) + op2 = kvm_s390_get_base_disp_s(vcpu, &ar); + if (op2 & 7) /* Operand must be on a doubleword boundary */ + return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); +- rc = read_guest(vcpu, op2, ar, &val, sizeof(val)); ++ rc = read_guest(vcpu, op2, ar, >od.tod, sizeof(gtod.tod)); + if (rc) + return kvm_s390_inject_prog_cond(vcpu, rc); + +- VCPU_EVENT(vcpu, 3, "SCK: setting guest TOD to 0x%llx", val); +- kvm_s390_set_tod_clock(vcpu->kvm, val); ++ VCPU_EVENT(vcpu, 3, "SCK: setting guest TOD to 0x%llx", gtod.tod); ++ kvm_s390_set_tod_clock(vcpu->kvm, >od); + + kvm_s390_set_psw_cc(vcpu, 0); + return 0; +diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h +index 8b8f1f14a0bf..5c790e93657d 100644 +--- a/arch/x86/include/asm/pgtable.h ++++ b/arch/x86/include/asm/pgtable.h +@@ -350,14 +350,14 @@ static inline pmd_t pmd_set_flags(pmd_t pmd, pmdval_t set) + { + pmdval_t v = native_pmd_val(pmd); + +- return __pmd(v | set); ++ return native_make_pmd(v | set); + } + + static inline pmd_t pmd_clear_flags(pmd_t pmd, pmdval_t clear) + { + pmdval_t v = native_pmd_val(pmd); + +- return __pmd(v & ~clear); ++ return native_make_pmd(v & ~clear); + } + + static inline pmd_t pmd_mkold(pmd_t pmd) +@@ -409,14 +409,14 @@ static inline pud_t pud_set_flags(pud_t pud, pudval_t set) + { + pudval_t v = native_pud_val(pud); + +- return __pud(v | set); ++ return native_make_pud(v | set); + } + + static inline pud_t pud_clear_flags(pud_t pud, pudval_t clear) + { + pudval_t v = native_pud_val(pud); + +- return __pud(v & ~clear); ++ return native_make_pud(v & ~clear); + } + + static inline pud_t pud_mkold(pud_t pud) +diff --git a/arch/x86/include/asm/pgtable_32.h b/arch/x86/include/asm/pgtable_32.h +index e55466760ff8..b3ec519e3982 100644 +--- a/arch/x86/include/asm/pgtable_32.h ++++ b/arch/x86/include/asm/pgtable_32.h +@@ -32,6 +32,7 @@ extern pmd_t initial_pg_pmd[]; + static inline void pgtable_cache_init(void) { } + static inline void check_pgt_cache(void) { } + void paging_init(void); ++void sync_initial_page_table(void); + + /* + * Define this if things work differently on an i386 and an i486: +diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h +index 81462e9a34f6..1149d2112b2e 100644 +--- a/arch/x86/include/asm/pgtable_64.h ++++ b/arch/x86/include/asm/pgtable_64.h +@@ -28,6 +28,7 @@ extern pgd_t init_top_pgt[]; + #define swapper_pg_dir init_top_pgt + + extern void paging_init(void); ++static inline void sync_initial_page_table(void) { } + + #define pte_ERROR(e) \ + pr_err("%s:%d: bad pte %p(%016lx)\n", \ +diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h +index 3696398a9475..246f15b4e64c 100644 +--- a/arch/x86/include/asm/pgtable_types.h ++++ b/arch/x86/include/asm/pgtable_types.h +@@ -323,6 +323,11 @@ static inline pudval_t native_pud_val(pud_t pud) + #else + #include + ++static inline pud_t native_make_pud(pudval_t val) ++{ ++ return (pud_t) { .p4d.pgd = native_make_pgd(val) }; ++} ++ + static inline pudval_t native_pud_val(pud_t pud) + { + return native_pgd_val(pud.p4d.pgd); +@@ -344,6 +349,11 @@ static inline pmdval_t native_pmd_val(pmd_t pmd) + #else + #include + ++static inline pmd_t native_make_pmd(pmdval_t val) ++{ ++ return (pmd_t) { .pud.p4d.pgd = native_make_pgd(val) }; ++} ++ + static inline pmdval_t native_pmd_val(pmd_t pmd) + { + return native_pgd_val(pmd.pud.p4d.pgd); +diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c +index c54361a22f59..efbcf5283520 100644 +--- a/arch/x86/kernel/setup.c ++++ b/arch/x86/kernel/setup.c +@@ -1238,20 +1238,13 @@ void __init setup_arch(char **cmdline_p) + + kasan_init(); + +-#ifdef CONFIG_X86_32 +- /* sync back kernel address range */ +- clone_pgd_range(initial_page_table + KERNEL_PGD_BOUNDARY, +- swapper_pg_dir + KERNEL_PGD_BOUNDARY, +- KERNEL_PGD_PTRS); +- + /* +- * sync back low identity map too. It is used for example +- * in the 32-bit EFI stub. ++ * Sync back kernel address range. ++ * ++ * FIXME: Can the later sync in setup_cpu_entry_areas() replace ++ * this call? + */ +- clone_pgd_range(initial_page_table, +- swapper_pg_dir + KERNEL_PGD_BOUNDARY, +- min(KERNEL_PGD_PTRS, KERNEL_PGD_BOUNDARY)); +-#endif ++ sync_initial_page_table(); + + tboot_probe(); + +diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c +index 497aa766fab3..ea554f812ee1 100644 +--- a/arch/x86/kernel/setup_percpu.c ++++ b/arch/x86/kernel/setup_percpu.c +@@ -287,24 +287,15 @@ void __init setup_per_cpu_areas(void) + /* Setup cpu initialized, callin, callout masks */ + setup_cpu_local_masks(); + +-#ifdef CONFIG_X86_32 + /* + * Sync back kernel address range again. We already did this in + * setup_arch(), but percpu data also needs to be available in + * the smpboot asm. We can't reliably pick up percpu mappings + * using vmalloc_fault(), because exception dispatch needs + * percpu data. ++ * ++ * FIXME: Can the later sync in setup_cpu_entry_areas() replace ++ * this call? + */ +- clone_pgd_range(initial_page_table + KERNEL_PGD_BOUNDARY, +- swapper_pg_dir + KERNEL_PGD_BOUNDARY, +- KERNEL_PGD_PTRS); +- +- /* +- * sync back low identity map too. It is used for example +- * in the 32-bit EFI stub. +- */ +- clone_pgd_range(initial_page_table, +- swapper_pg_dir + KERNEL_PGD_BOUNDARY, +- min(KERNEL_PGD_PTRS, KERNEL_PGD_BOUNDARY)); +-#endif ++ sync_initial_page_table(); + } +diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c +index ef03efba1c23..8cfdb6484fd0 100644 +--- a/arch/x86/kvm/lapic.c ++++ b/arch/x86/kvm/lapic.c +@@ -1944,14 +1944,13 @@ void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value) + + void kvm_lapic_reset(struct kvm_vcpu *vcpu, bool init_event) + { +- struct kvm_lapic *apic; ++ struct kvm_lapic *apic = vcpu->arch.apic; + int i; + +- apic_debug("%s\n", __func__); ++ if (!apic) ++ return; + +- ASSERT(vcpu); +- apic = vcpu->arch.apic; +- ASSERT(apic != NULL); ++ apic_debug("%s\n", __func__); + + /* Stop the timer in case it's a reset to an active apic */ + hrtimer_cancel(&apic->lapic_timer.timer); +@@ -2107,7 +2106,6 @@ int kvm_create_lapic(struct kvm_vcpu *vcpu) + */ + vcpu->arch.apic_base = MSR_IA32_APICBASE_ENABLE; + static_key_slow_inc(&apic_sw_disabled.key); /* sw disabled at reset */ +- kvm_lapic_reset(vcpu, false); + kvm_iodevice_init(&apic->dev, &apic_mmio_ops); + + return 0; +@@ -2511,7 +2509,6 @@ void kvm_apic_accept_events(struct kvm_vcpu *vcpu) + + pe = xchg(&apic->pending_events, 0); + if (test_bit(KVM_APIC_INIT, &pe)) { +- kvm_lapic_reset(vcpu, true); + kvm_vcpu_reset(vcpu, true); + if (kvm_vcpu_is_bsp(apic->vcpu)) + vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE; +diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c +index ca000fc644bc..2b6f8a4f2731 100644 +--- a/arch/x86/kvm/mmu.c ++++ b/arch/x86/kvm/mmu.c +@@ -150,6 +150,20 @@ module_param(dbg, bool, 0644); + /* make pte_list_desc fit well in cache line */ + #define PTE_LIST_EXT 3 + ++/* ++ * Return values of handle_mmio_page_fault and mmu.page_fault: ++ * RET_PF_RETRY: let CPU fault again on the address. ++ * RET_PF_EMULATE: mmio page fault, emulate the instruction directly. ++ * ++ * For handle_mmio_page_fault only: ++ * RET_PF_INVALID: the spte is invalid, let the real page fault path update it. ++ */ ++enum { ++ RET_PF_RETRY = 0, ++ RET_PF_EMULATE = 1, ++ RET_PF_INVALID = 2, ++}; ++ + struct pte_list_desc { + u64 *sptes[PTE_LIST_EXT]; + struct pte_list_desc *more; +@@ -2794,13 +2808,13 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *sptep, + return ret; + } + +-static bool mmu_set_spte(struct kvm_vcpu *vcpu, u64 *sptep, unsigned pte_access, +- int write_fault, int level, gfn_t gfn, kvm_pfn_t pfn, +- bool speculative, bool host_writable) ++static int mmu_set_spte(struct kvm_vcpu *vcpu, u64 *sptep, unsigned pte_access, ++ int write_fault, int level, gfn_t gfn, kvm_pfn_t pfn, ++ bool speculative, bool host_writable) + { + int was_rmapped = 0; + int rmap_count; +- bool emulate = false; ++ int ret = RET_PF_RETRY; + + pgprintk("%s: spte %llx write_fault %d gfn %llx\n", __func__, + *sptep, write_fault, gfn); +@@ -2830,12 +2844,12 @@ static bool mmu_set_spte(struct kvm_vcpu *vcpu, u64 *sptep, unsigned pte_access, + if (set_spte(vcpu, sptep, pte_access, level, gfn, pfn, speculative, + true, host_writable)) { + if (write_fault) +- emulate = true; ++ ret = RET_PF_EMULATE; + kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu); + } + + if (unlikely(is_mmio_spte(*sptep))) +- emulate = true; ++ ret = RET_PF_EMULATE; + + pgprintk("%s: setting spte %llx\n", __func__, *sptep); + pgprintk("instantiating %s PTE (%s) at %llx (%llx) addr %p\n", +@@ -2855,7 +2869,7 @@ static bool mmu_set_spte(struct kvm_vcpu *vcpu, u64 *sptep, unsigned pte_access, + + kvm_release_pfn_clean(pfn); + +- return emulate; ++ return ret; + } + + static kvm_pfn_t pte_prefetch_gfn_to_pfn(struct kvm_vcpu *vcpu, gfn_t gfn, +@@ -2994,17 +3008,16 @@ static int kvm_handle_bad_page(struct kvm_vcpu *vcpu, gfn_t gfn, kvm_pfn_t pfn) + * Do not cache the mmio info caused by writing the readonly gfn + * into the spte otherwise read access on readonly gfn also can + * caused mmio page fault and treat it as mmio access. +- * Return 1 to tell kvm to emulate it. + */ + if (pfn == KVM_PFN_ERR_RO_FAULT) +- return 1; ++ return RET_PF_EMULATE; + + if (pfn == KVM_PFN_ERR_HWPOISON) { + kvm_send_hwpoison_signal(kvm_vcpu_gfn_to_hva(vcpu, gfn), current); +- return 0; ++ return RET_PF_RETRY; + } + +- return -EFAULT; ++ return RET_PF_EMULATE; + } + + static void transparent_hugepage_adjust(struct kvm_vcpu *vcpu, +@@ -3286,13 +3299,13 @@ static int nonpaging_map(struct kvm_vcpu *vcpu, gva_t v, u32 error_code, + } + + if (fast_page_fault(vcpu, v, level, error_code)) +- return 0; ++ return RET_PF_RETRY; + + mmu_seq = vcpu->kvm->mmu_notifier_seq; + smp_rmb(); + + if (try_async_pf(vcpu, prefault, gfn, v, &pfn, write, &map_writable)) +- return 0; ++ return RET_PF_RETRY; + + if (handle_abnormal_pfn(vcpu, v, gfn, pfn, ACC_ALL, &r)) + return r; +@@ -3312,7 +3325,7 @@ static int nonpaging_map(struct kvm_vcpu *vcpu, gva_t v, u32 error_code, + out_unlock: + spin_unlock(&vcpu->kvm->mmu_lock); + kvm_release_pfn_clean(pfn); +- return 0; ++ return RET_PF_RETRY; + } + + +@@ -3659,54 +3672,38 @@ walk_shadow_page_get_mmio_spte(struct kvm_vcpu *vcpu, u64 addr, u64 *sptep) + return reserved; + } + +-/* +- * Return values of handle_mmio_page_fault: +- * RET_MMIO_PF_EMULATE: it is a real mmio page fault, emulate the instruction +- * directly. +- * RET_MMIO_PF_INVALID: invalid spte is detected then let the real page +- * fault path update the mmio spte. +- * RET_MMIO_PF_RETRY: let CPU fault again on the address. +- * RET_MMIO_PF_BUG: a bug was detected (and a WARN was printed). +- */ +-enum { +- RET_MMIO_PF_EMULATE = 1, +- RET_MMIO_PF_INVALID = 2, +- RET_MMIO_PF_RETRY = 0, +- RET_MMIO_PF_BUG = -1 +-}; +- + static int handle_mmio_page_fault(struct kvm_vcpu *vcpu, u64 addr, bool direct) + { + u64 spte; + bool reserved; + + if (mmio_info_in_cache(vcpu, addr, direct)) +- return RET_MMIO_PF_EMULATE; ++ return RET_PF_EMULATE; + + reserved = walk_shadow_page_get_mmio_spte(vcpu, addr, &spte); + if (WARN_ON(reserved)) +- return RET_MMIO_PF_BUG; ++ return -EINVAL; + + if (is_mmio_spte(spte)) { + gfn_t gfn = get_mmio_spte_gfn(spte); + unsigned access = get_mmio_spte_access(spte); + + if (!check_mmio_spte(vcpu, spte)) +- return RET_MMIO_PF_INVALID; ++ return RET_PF_INVALID; + + if (direct) + addr = 0; + + trace_handle_mmio_page_fault(addr, gfn, access); + vcpu_cache_mmio_info(vcpu, addr, gfn, access); +- return RET_MMIO_PF_EMULATE; ++ return RET_PF_EMULATE; + } + + /* + * If the page table is zapped by other cpus, let CPU fault again on + * the address. + */ +- return RET_MMIO_PF_RETRY; ++ return RET_PF_RETRY; + } + EXPORT_SYMBOL_GPL(handle_mmio_page_fault); + +@@ -3756,7 +3753,7 @@ static int nonpaging_page_fault(struct kvm_vcpu *vcpu, gva_t gva, + pgprintk("%s: gva %lx error %x\n", __func__, gva, error_code); + + if (page_fault_handle_page_track(vcpu, error_code, gfn)) +- return 1; ++ return RET_PF_EMULATE; + + r = mmu_topup_memory_caches(vcpu); + if (r) +@@ -3877,7 +3874,7 @@ static int tdp_page_fault(struct kvm_vcpu *vcpu, gva_t gpa, u32 error_code, + MMU_WARN_ON(!VALID_PAGE(vcpu->arch.mmu.root_hpa)); + + if (page_fault_handle_page_track(vcpu, error_code, gfn)) +- return 1; ++ return RET_PF_EMULATE; + + r = mmu_topup_memory_caches(vcpu); + if (r) +@@ -3894,13 +3891,13 @@ static int tdp_page_fault(struct kvm_vcpu *vcpu, gva_t gpa, u32 error_code, + } + + if (fast_page_fault(vcpu, gpa, level, error_code)) +- return 0; ++ return RET_PF_RETRY; + + mmu_seq = vcpu->kvm->mmu_notifier_seq; + smp_rmb(); + + if (try_async_pf(vcpu, prefault, gfn, gpa, &pfn, write, &map_writable)) +- return 0; ++ return RET_PF_RETRY; + + if (handle_abnormal_pfn(vcpu, 0, gfn, pfn, ACC_ALL, &r)) + return r; +@@ -3920,7 +3917,7 @@ static int tdp_page_fault(struct kvm_vcpu *vcpu, gva_t gpa, u32 error_code, + out_unlock: + spin_unlock(&vcpu->kvm->mmu_lock); + kvm_release_pfn_clean(pfn); +- return 0; ++ return RET_PF_RETRY; + } + + static void nonpaging_init_context(struct kvm_vcpu *vcpu, +@@ -4919,25 +4916,25 @@ int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t cr2, u64 error_code, + vcpu->arch.gpa_val = cr2; + } + ++ r = RET_PF_INVALID; + if (unlikely(error_code & PFERR_RSVD_MASK)) { + r = handle_mmio_page_fault(vcpu, cr2, direct); +- if (r == RET_MMIO_PF_EMULATE) { ++ if (r == RET_PF_EMULATE) { + emulation_type = 0; + goto emulate; + } +- if (r == RET_MMIO_PF_RETRY) +- return 1; +- if (r < 0) +- return r; +- /* Must be RET_MMIO_PF_INVALID. */ + } + +- r = vcpu->arch.mmu.page_fault(vcpu, cr2, lower_32_bits(error_code), +- false); ++ if (r == RET_PF_INVALID) { ++ r = vcpu->arch.mmu.page_fault(vcpu, cr2, lower_32_bits(error_code), ++ false); ++ WARN_ON(r == RET_PF_INVALID); ++ } ++ ++ if (r == RET_PF_RETRY) ++ return 1; + if (r < 0) + return r; +- if (!r) +- return 1; + + /* + * Before emulating the instruction, check if the error code +diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h +index f18d1f8d332b..5abae72266b7 100644 +--- a/arch/x86/kvm/paging_tmpl.h ++++ b/arch/x86/kvm/paging_tmpl.h +@@ -593,7 +593,7 @@ static int FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr, + struct kvm_mmu_page *sp = NULL; + struct kvm_shadow_walk_iterator it; + unsigned direct_access, access = gw->pt_access; +- int top_level, emulate; ++ int top_level, ret; + + direct_access = gw->pte_access; + +@@ -659,15 +659,15 @@ static int FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr, + } + + clear_sp_write_flooding_count(it.sptep); +- emulate = mmu_set_spte(vcpu, it.sptep, gw->pte_access, write_fault, +- it.level, gw->gfn, pfn, prefault, map_writable); ++ ret = mmu_set_spte(vcpu, it.sptep, gw->pte_access, write_fault, ++ it.level, gw->gfn, pfn, prefault, map_writable); + FNAME(pte_prefetch)(vcpu, gw, it.sptep); + +- return emulate; ++ return ret; + + out_gpte_changed: + kvm_release_pfn_clean(pfn); +- return 0; ++ return RET_PF_RETRY; + } + + /* +@@ -762,12 +762,12 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, u32 error_code, + if (!prefault) + inject_page_fault(vcpu, &walker.fault); + +- return 0; ++ return RET_PF_RETRY; + } + + if (page_fault_handle_page_track(vcpu, error_code, walker.gfn)) { + shadow_page_table_clear_flood(vcpu, addr); +- return 1; ++ return RET_PF_EMULATE; + } + + vcpu->arch.write_fault_to_shadow_pgtable = false; +@@ -789,7 +789,7 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, u32 error_code, + + if (try_async_pf(vcpu, prefault, walker.gfn, addr, &pfn, write_fault, + &map_writable)) +- return 0; ++ return RET_PF_RETRY; + + if (handle_abnormal_pfn(vcpu, addr, walker.gfn, pfn, walker.pte_access, &r)) + return r; +@@ -834,7 +834,7 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, u32 error_code, + out_unlock: + spin_unlock(&vcpu->kvm->mmu_lock); + kvm_release_pfn_clean(pfn); +- return 0; ++ return RET_PF_RETRY; + } + + static gpa_t FNAME(get_level1_sp_gpa)(struct kvm_mmu_page *sp) +diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c +index e0bc3ad0f6cd..9fb0daf628cb 100644 +--- a/arch/x86/kvm/svm.c ++++ b/arch/x86/kvm/svm.c +@@ -45,6 +45,7 @@ + #include + #include + #include ++#include + #include + + #include +@@ -5015,7 +5016,7 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu) + * being speculatively taken. + */ + if (svm->spec_ctrl) +- wrmsrl(MSR_IA32_SPEC_CTRL, svm->spec_ctrl); ++ native_wrmsrl(MSR_IA32_SPEC_CTRL, svm->spec_ctrl); + + asm volatile ( + "push %%" _ASM_BP "; \n\t" +@@ -5124,11 +5125,11 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu) + * If the L02 MSR bitmap does not intercept the MSR, then we need to + * save it. + */ +- if (!msr_write_intercepted(vcpu, MSR_IA32_SPEC_CTRL)) +- rdmsrl(MSR_IA32_SPEC_CTRL, svm->spec_ctrl); ++ if (unlikely(!msr_write_intercepted(vcpu, MSR_IA32_SPEC_CTRL))) ++ svm->spec_ctrl = native_read_msr(MSR_IA32_SPEC_CTRL); + + if (svm->spec_ctrl) +- wrmsrl(MSR_IA32_SPEC_CTRL, 0); ++ native_wrmsrl(MSR_IA32_SPEC_CTRL, 0); + + /* Eliminate branch target predictions from guest mode */ + vmexit_fill_RSB(); +diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c +index 5ffde16253cb..315fccb2684b 100644 +--- a/arch/x86/kvm/vmx.c ++++ b/arch/x86/kvm/vmx.c +@@ -51,6 +51,7 @@ + #include + #include + #include ++#include + #include + + #include "trace.h" +@@ -9431,7 +9432,7 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu) + * being speculatively taken. + */ + if (vmx->spec_ctrl) +- wrmsrl(MSR_IA32_SPEC_CTRL, vmx->spec_ctrl); ++ native_wrmsrl(MSR_IA32_SPEC_CTRL, vmx->spec_ctrl); + + vmx->__launched = vmx->loaded_vmcs->launched; + asm( +@@ -9566,11 +9567,11 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu) + * If the L02 MSR bitmap does not intercept the MSR, then we need to + * save it. + */ +- if (!msr_write_intercepted(vcpu, MSR_IA32_SPEC_CTRL)) +- rdmsrl(MSR_IA32_SPEC_CTRL, vmx->spec_ctrl); ++ if (unlikely(!msr_write_intercepted(vcpu, MSR_IA32_SPEC_CTRL))) ++ vmx->spec_ctrl = native_read_msr(MSR_IA32_SPEC_CTRL); + + if (vmx->spec_ctrl) +- wrmsrl(MSR_IA32_SPEC_CTRL, 0); ++ native_wrmsrl(MSR_IA32_SPEC_CTRL, 0); + + /* Eliminate branch target predictions from guest mode */ + vmexit_fill_RSB(); +diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c +index 0dcd7bf45dc1..b9afb4784d12 100644 +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -7482,13 +7482,13 @@ EXPORT_SYMBOL_GPL(kvm_task_switch); + + int kvm_valid_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs) + { +- if ((sregs->efer & EFER_LME) && (sregs->cr0 & X86_CR0_PG_BIT)) { ++ if ((sregs->efer & EFER_LME) && (sregs->cr0 & X86_CR0_PG)) { + /* + * When EFER.LME and CR0.PG are set, the processor is in + * 64-bit mode (though maybe in a 32-bit code segment). + * CR4.PAE and EFER.LMA must be set. + */ +- if (!(sregs->cr4 & X86_CR4_PAE_BIT) ++ if (!(sregs->cr4 & X86_CR4_PAE) + || !(sregs->efer & EFER_LMA)) + return -EINVAL; + } else { +@@ -7821,6 +7821,8 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu) + + void kvm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event) + { ++ kvm_lapic_reset(vcpu, init_event); ++ + vcpu->arch.hflags = 0; + + vcpu->arch.smi_pending = 0; +@@ -8249,10 +8251,8 @@ int __x86_set_memory_region(struct kvm *kvm, int id, gpa_t gpa, u32 size) + return r; + } + +- if (!size) { +- r = vm_munmap(old.userspace_addr, old.npages * PAGE_SIZE); +- WARN_ON(r < 0); +- } ++ if (!size) ++ vm_munmap(old.userspace_addr, old.npages * PAGE_SIZE); + + return 0; + } +diff --git a/arch/x86/mm/cpu_entry_area.c b/arch/x86/mm/cpu_entry_area.c +index b9283cc27622..476d810639a8 100644 +--- a/arch/x86/mm/cpu_entry_area.c ++++ b/arch/x86/mm/cpu_entry_area.c +@@ -163,4 +163,10 @@ void __init setup_cpu_entry_areas(void) + + for_each_possible_cpu(cpu) + setup_cpu_entry_area(cpu); ++ ++ /* ++ * This is the last essential update to swapper_pgdir which needs ++ * to be synchronized to initial_page_table on 32bit. ++ */ ++ sync_initial_page_table(); + } +diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c +index 135c9a7898c7..3141e67ec24c 100644 +--- a/arch/x86/mm/init_32.c ++++ b/arch/x86/mm/init_32.c +@@ -453,6 +453,21 @@ static inline void permanent_kmaps_init(pgd_t *pgd_base) + } + #endif /* CONFIG_HIGHMEM */ + ++void __init sync_initial_page_table(void) ++{ ++ clone_pgd_range(initial_page_table + KERNEL_PGD_BOUNDARY, ++ swapper_pg_dir + KERNEL_PGD_BOUNDARY, ++ KERNEL_PGD_PTRS); ++ ++ /* ++ * sync back low identity map too. It is used for example ++ * in the 32-bit EFI stub. ++ */ ++ clone_pgd_range(initial_page_table, ++ swapper_pg_dir + KERNEL_PGD_BOUNDARY, ++ min(KERNEL_PGD_PTRS, KERNEL_PGD_BOUNDARY)); ++} ++ + void __init native_pagetable_init(void) + { + unsigned long pfn, va; +diff --git a/arch/x86/platform/intel-mid/intel-mid.c b/arch/x86/platform/intel-mid/intel-mid.c +index 86676cec99a1..09dd7f3cf621 100644 +--- a/arch/x86/platform/intel-mid/intel-mid.c ++++ b/arch/x86/platform/intel-mid/intel-mid.c +@@ -79,7 +79,7 @@ static void intel_mid_power_off(void) + + static void intel_mid_reboot(void) + { +- intel_scu_ipc_simple_command(IPCMSG_COLD_BOOT, 0); ++ intel_scu_ipc_simple_command(IPCMSG_COLD_RESET, 0); + } + + static unsigned long __init intel_mid_calibrate_tsc(void) +diff --git a/arch/x86/xen/suspend.c b/arch/x86/xen/suspend.c +index 92bf5ecb6baf..3e3a58ea669e 100644 +--- a/arch/x86/xen/suspend.c ++++ b/arch/x86/xen/suspend.c +@@ -1,12 +1,15 @@ + // SPDX-License-Identifier: GPL-2.0 + #include + #include ++#include + + #include + #include + #include + #include + ++#include ++#include + #include + #include + #include +@@ -15,6 +18,8 @@ + #include "mmu.h" + #include "pmu.h" + ++static DEFINE_PER_CPU(u64, spec_ctrl); ++ + void xen_arch_pre_suspend(void) + { + if (xen_pv_domain()) +@@ -31,6 +36,9 @@ void xen_arch_post_suspend(int cancelled) + + static void xen_vcpu_notify_restore(void *data) + { ++ if (xen_pv_domain() && boot_cpu_has(X86_FEATURE_SPEC_CTRL)) ++ wrmsrl(MSR_IA32_SPEC_CTRL, this_cpu_read(spec_ctrl)); ++ + /* Boot processor notified via generic timekeeping_resume() */ + if (smp_processor_id() == 0) + return; +@@ -40,7 +48,15 @@ static void xen_vcpu_notify_restore(void *data) + + static void xen_vcpu_notify_suspend(void *data) + { ++ u64 tmp; ++ + tick_suspend_local(); ++ ++ if (xen_pv_domain() && boot_cpu_has(X86_FEATURE_SPEC_CTRL)) { ++ rdmsrl(MSR_IA32_SPEC_CTRL, tmp); ++ this_cpu_write(spec_ctrl, tmp); ++ wrmsrl(MSR_IA32_SPEC_CTRL, 0); ++ } + } + + void xen_arch_resume(void) +diff --git a/block/blk-core.c b/block/blk-core.c +index 95b7ea996ac2..c01f4907dbbc 100644 +--- a/block/blk-core.c ++++ b/block/blk-core.c +@@ -2277,7 +2277,7 @@ blk_qc_t submit_bio(struct bio *bio) + unsigned int count; + + if (unlikely(bio_op(bio) == REQ_OP_WRITE_SAME)) +- count = queue_logical_block_size(bio->bi_disk->queue); ++ count = queue_logical_block_size(bio->bi_disk->queue) >> 9; + else + count = bio_sectors(bio); + +diff --git a/block/blk-mq.c b/block/blk-mq.c +index b60798a30ea2..f1fb126a3be5 100644 +--- a/block/blk-mq.c ++++ b/block/blk-mq.c +@@ -638,7 +638,6 @@ static void __blk_mq_requeue_request(struct request *rq) + + trace_block_rq_requeue(q, rq); + wbt_requeue(q->rq_wb, &rq->issue_stat); +- blk_mq_sched_requeue_request(rq); + + if (test_and_clear_bit(REQ_ATOM_STARTED, &rq->atomic_flags)) { + if (q->dma_drain_size && blk_rq_bytes(rq)) +@@ -650,6 +649,9 @@ void blk_mq_requeue_request(struct request *rq, bool kick_requeue_list) + { + __blk_mq_requeue_request(rq); + ++ /* this request will be re-inserted to io scheduler queue */ ++ blk_mq_sched_requeue_request(rq); ++ + BUG_ON(blk_queued_rq(rq)); + blk_mq_add_to_requeue_list(rq, true, kick_requeue_list); + } +diff --git a/block/kyber-iosched.c b/block/kyber-iosched.c +index f58cab82105b..09cd5cf2e459 100644 +--- a/block/kyber-iosched.c ++++ b/block/kyber-iosched.c +@@ -814,6 +814,7 @@ static struct elevator_type kyber_sched = { + .limit_depth = kyber_limit_depth, + .prepare_request = kyber_prepare_request, + .finish_request = kyber_finish_request, ++ .requeue_request = kyber_finish_request, + .completed_request = kyber_completed_request, + .dispatch_request = kyber_dispatch_request, + .has_work = kyber_has_work, +diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c +index 4d0979e02a28..b6d58cc58f5f 100644 +--- a/drivers/acpi/bus.c ++++ b/drivers/acpi/bus.c +@@ -66,10 +66,37 @@ static int set_copy_dsdt(const struct dmi_system_id *id) + return 0; + } + #endif ++static int set_gbl_term_list(const struct dmi_system_id *id) ++{ ++ acpi_gbl_parse_table_as_term_list = 1; ++ return 0; ++} + +-static const struct dmi_system_id dsdt_dmi_table[] __initconst = { ++static const struct dmi_system_id acpi_quirks_dmi_table[] __initconst = { ++ /* ++ * Touchpad on Dell XPS 9570/Precision M5530 doesn't work under I2C ++ * mode. ++ * https://bugzilla.kernel.org/show_bug.cgi?id=198515 ++ */ ++ { ++ .callback = set_gbl_term_list, ++ .ident = "Dell Precision M5530", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "Precision M5530"), ++ }, ++ }, ++ { ++ .callback = set_gbl_term_list, ++ .ident = "Dell XPS 15 9570", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "XPS 15 9570"), ++ }, ++ }, + /* + * Invoke DSDT corruption work-around on all Toshiba Satellite. ++ * DSDT will be copied to memory. + * https://bugzilla.kernel.org/show_bug.cgi?id=14679 + */ + { +@@ -83,7 +110,7 @@ static const struct dmi_system_id dsdt_dmi_table[] __initconst = { + {} + }; + #else +-static const struct dmi_system_id dsdt_dmi_table[] __initconst = { ++static const struct dmi_system_id acpi_quirks_dmi_table[] __initconst = { + {} + }; + #endif +@@ -1001,11 +1028,8 @@ void __init acpi_early_init(void) + + acpi_permanent_mmap = true; + +- /* +- * If the machine falls into the DMI check table, +- * DSDT will be copied to memory +- */ +- dmi_check_system(dsdt_dmi_table); ++ /* Check machine-specific quirks */ ++ dmi_check_system(acpi_quirks_dmi_table); + + status = acpi_reallocate_root_table(); + if (ACPI_FAILURE(status)) { +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index d54c3f6f728c..673698c7b143 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -21,6 +21,7 @@ + * + */ + ++#include + #include + #include + #include +@@ -381,6 +382,21 @@ static const struct usb_device_id blacklist_table[] = { + { } /* Terminating entry */ + }; + ++/* The Bluetooth USB module build into some devices needs to be reset on resume, ++ * this is a problem with the platform (likely shutting off all power) not with ++ * the module itself. So we use a DMI list to match known broken platforms. ++ */ ++static const struct dmi_system_id btusb_needs_reset_resume_table[] = { ++ { ++ /* Lenovo Yoga 920 (QCA Rome device 0cf3:e300) */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), ++ DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo YOGA 920"), ++ }, ++ }, ++ {} ++}; ++ + #define BTUSB_MAX_ISOC_FRAMES 10 + + #define BTUSB_INTR_RUNNING 0 +@@ -3013,6 +3029,9 @@ static int btusb_probe(struct usb_interface *intf, + hdev->send = btusb_send_frame; + hdev->notify = btusb_notify; + ++ if (dmi_check_system(btusb_needs_reset_resume_table)) ++ interface_to_usbdev(intf)->quirks |= USB_QUIRK_RESET_RESUME; ++ + #ifdef CONFIG_PM + err = btusb_config_oob_wake(hdev); + if (err) +@@ -3099,12 +3118,6 @@ static int btusb_probe(struct usb_interface *intf, + if (id->driver_info & BTUSB_QCA_ROME) { + data->setup_on_usb = btusb_setup_qca; + hdev->set_bdaddr = btusb_set_bdaddr_ath3012; +- +- /* QCA Rome devices lose their updated firmware over suspend, +- * but the USB hub doesn't notice any status change. +- * explicitly request a device reset on resume. +- */ +- interface_to_usbdev(intf)->quirks |= USB_QUIRK_RESET_RESUME; + } + + #ifdef CONFIG_BT_HCIBTUSB_RTL +diff --git a/drivers/char/tpm/st33zp24/st33zp24.c b/drivers/char/tpm/st33zp24/st33zp24.c +index 4d1dc8b46877..f95b9c75175b 100644 +--- a/drivers/char/tpm/st33zp24/st33zp24.c ++++ b/drivers/char/tpm/st33zp24/st33zp24.c +@@ -457,7 +457,7 @@ static int st33zp24_recv(struct tpm_chip *chip, unsigned char *buf, + size_t count) + { + int size = 0; +- int expected; ++ u32 expected; + + if (!chip) + return -EBUSY; +@@ -474,7 +474,7 @@ static int st33zp24_recv(struct tpm_chip *chip, unsigned char *buf, + } + + expected = be32_to_cpu(*(__be32 *)(buf + 2)); +- if (expected > count) { ++ if (expected > count || expected < TPM_HEADER_SIZE) { + size = -EIO; + goto out; + } +diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c +index 1d6729be4cd6..3cec403a80b3 100644 +--- a/drivers/char/tpm/tpm-interface.c ++++ b/drivers/char/tpm/tpm-interface.c +@@ -1228,6 +1228,10 @@ int tpm_get_random(u32 chip_num, u8 *out, size_t max) + break; + + recd = be32_to_cpu(tpm_cmd.params.getrandom_out.rng_data_len); ++ if (recd > num_bytes) { ++ total = -EFAULT; ++ break; ++ } + + rlength = be32_to_cpu(tpm_cmd.header.out.length); + if (rlength < offsetof(struct tpm_getrandom_out, rng_data) + +diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c +index e1a41b788f08..44a3d16231f6 100644 +--- a/drivers/char/tpm/tpm2-cmd.c ++++ b/drivers/char/tpm/tpm2-cmd.c +@@ -683,6 +683,10 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip, + if (!rc) { + data_len = be16_to_cpup( + (__be16 *) &buf.data[TPM_HEADER_SIZE + 4]); ++ if (data_len < MIN_KEY_SIZE || data_len > MAX_KEY_SIZE + 1) { ++ rc = -EFAULT; ++ goto out; ++ } + + rlength = be32_to_cpu(((struct tpm2_cmd *)&buf) + ->header.out.length); +diff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c_infineon.c +index 79d6bbb58e39..d5b44cadac56 100644 +--- a/drivers/char/tpm/tpm_i2c_infineon.c ++++ b/drivers/char/tpm/tpm_i2c_infineon.c +@@ -473,7 +473,8 @@ static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count) + static int tpm_tis_i2c_recv(struct tpm_chip *chip, u8 *buf, size_t count) + { + int size = 0; +- int expected, status; ++ int status; ++ u32 expected; + + if (count < TPM_HEADER_SIZE) { + size = -EIO; +@@ -488,7 +489,7 @@ static int tpm_tis_i2c_recv(struct tpm_chip *chip, u8 *buf, size_t count) + } + + expected = be32_to_cpu(*(__be32 *)(buf + 2)); +- if ((size_t) expected > count) { ++ if (((size_t) expected > count) || (expected < TPM_HEADER_SIZE)) { + size = -EIO; + goto out; + } +diff --git a/drivers/char/tpm/tpm_i2c_nuvoton.c b/drivers/char/tpm/tpm_i2c_nuvoton.c +index c6428771841f..caa86b19c76d 100644 +--- a/drivers/char/tpm/tpm_i2c_nuvoton.c ++++ b/drivers/char/tpm/tpm_i2c_nuvoton.c +@@ -281,7 +281,11 @@ static int i2c_nuvoton_recv(struct tpm_chip *chip, u8 *buf, size_t count) + struct device *dev = chip->dev.parent; + struct i2c_client *client = to_i2c_client(dev); + s32 rc; +- int expected, status, burst_count, retries, size = 0; ++ int status; ++ int burst_count; ++ int retries; ++ int size = 0; ++ u32 expected; + + if (count < TPM_HEADER_SIZE) { + i2c_nuvoton_ready(chip); /* return to idle */ +@@ -323,7 +327,7 @@ static int i2c_nuvoton_recv(struct tpm_chip *chip, u8 *buf, size_t count) + * to machine native + */ + expected = be32_to_cpu(*(__be32 *) (buf + 2)); +- if (expected > count) { ++ if (expected > count || expected < size) { + dev_err(dev, "%s() expected > count\n", __func__); + size = -EIO; + continue; +diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c +index 7e55aa9ce680..ebd0e75a3e4d 100644 +--- a/drivers/char/tpm/tpm_tis.c ++++ b/drivers/char/tpm/tpm_tis.c +@@ -223,7 +223,7 @@ static int tpm_tcg_read_bytes(struct tpm_tis_data *data, u32 addr, u16 len, + } + + static int tpm_tcg_write_bytes(struct tpm_tis_data *data, u32 addr, u16 len, +- u8 *value) ++ const u8 *value) + { + struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); + +diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c +index 63bc6c3b949e..083578b2517e 100644 +--- a/drivers/char/tpm/tpm_tis_core.c ++++ b/drivers/char/tpm/tpm_tis_core.c +@@ -202,7 +202,8 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count) + { + struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); + int size = 0; +- int expected, status; ++ int status; ++ u32 expected; + + if (count < TPM_HEADER_SIZE) { + size = -EIO; +@@ -217,7 +218,7 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count) + } + + expected = be32_to_cpu(*(__be32 *) (buf + 2)); +- if (expected > count) { ++ if (expected > count || expected < TPM_HEADER_SIZE) { + size = -EIO; + goto out; + } +@@ -252,7 +253,7 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count) + * tpm.c can skip polling for the data to be available as the interrupt is + * waited for here + */ +-static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len) ++static int tpm_tis_send_data(struct tpm_chip *chip, const u8 *buf, size_t len) + { + struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); + int rc, status, burstcnt; +@@ -343,7 +344,7 @@ static void disable_interrupts(struct tpm_chip *chip) + * tpm.c can skip polling for the data to be available as the interrupt is + * waited for here + */ +-static int tpm_tis_send_main(struct tpm_chip *chip, u8 *buf, size_t len) ++static int tpm_tis_send_main(struct tpm_chip *chip, const u8 *buf, size_t len) + { + struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); + int rc; +diff --git a/drivers/char/tpm/tpm_tis_core.h b/drivers/char/tpm/tpm_tis_core.h +index e2212f021a02..6bbac319ff3b 100644 +--- a/drivers/char/tpm/tpm_tis_core.h ++++ b/drivers/char/tpm/tpm_tis_core.h +@@ -98,7 +98,7 @@ struct tpm_tis_phy_ops { + int (*read_bytes)(struct tpm_tis_data *data, u32 addr, u16 len, + u8 *result); + int (*write_bytes)(struct tpm_tis_data *data, u32 addr, u16 len, +- u8 *value); ++ const u8 *value); + int (*read16)(struct tpm_tis_data *data, u32 addr, u16 *result); + int (*read32)(struct tpm_tis_data *data, u32 addr, u32 *result); + int (*write32)(struct tpm_tis_data *data, u32 addr, u32 src); +@@ -128,7 +128,7 @@ static inline int tpm_tis_read32(struct tpm_tis_data *data, u32 addr, + } + + static inline int tpm_tis_write_bytes(struct tpm_tis_data *data, u32 addr, +- u16 len, u8 *value) ++ u16 len, const u8 *value) + { + return data->phy_ops->write_bytes(data, addr, len, value); + } +diff --git a/drivers/char/tpm/tpm_tis_spi.c b/drivers/char/tpm/tpm_tis_spi.c +index 88fe72ae967f..8ab0bd8445f6 100644 +--- a/drivers/char/tpm/tpm_tis_spi.c ++++ b/drivers/char/tpm/tpm_tis_spi.c +@@ -46,9 +46,7 @@ + struct tpm_tis_spi_phy { + struct tpm_tis_data priv; + struct spi_device *spi_device; +- +- u8 tx_buf[4]; +- u8 rx_buf[4]; ++ u8 *iobuf; + }; + + static inline struct tpm_tis_spi_phy *to_tpm_tis_spi_phy(struct tpm_tis_data *data) +@@ -57,7 +55,7 @@ static inline struct tpm_tis_spi_phy *to_tpm_tis_spi_phy(struct tpm_tis_data *da + } + + static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len, +- u8 *buffer, u8 direction) ++ u8 *in, const u8 *out) + { + struct tpm_tis_spi_phy *phy = to_tpm_tis_spi_phy(data); + int ret = 0; +@@ -71,14 +69,14 @@ static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len, + while (len) { + transfer_len = min_t(u16, len, MAX_SPI_FRAMESIZE); + +- phy->tx_buf[0] = direction | (transfer_len - 1); +- phy->tx_buf[1] = 0xd4; +- phy->tx_buf[2] = addr >> 8; +- phy->tx_buf[3] = addr; ++ phy->iobuf[0] = (in ? 0x80 : 0) | (transfer_len - 1); ++ phy->iobuf[1] = 0xd4; ++ phy->iobuf[2] = addr >> 8; ++ phy->iobuf[3] = addr; + + memset(&spi_xfer, 0, sizeof(spi_xfer)); +- spi_xfer.tx_buf = phy->tx_buf; +- spi_xfer.rx_buf = phy->rx_buf; ++ spi_xfer.tx_buf = phy->iobuf; ++ spi_xfer.rx_buf = phy->iobuf; + spi_xfer.len = 4; + spi_xfer.cs_change = 1; + +@@ -88,9 +86,9 @@ static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len, + if (ret < 0) + goto exit; + +- if ((phy->rx_buf[3] & 0x01) == 0) { ++ if ((phy->iobuf[3] & 0x01) == 0) { + // handle SPI wait states +- phy->tx_buf[0] = 0; ++ phy->iobuf[0] = 0; + + for (i = 0; i < TPM_RETRY; i++) { + spi_xfer.len = 1; +@@ -99,7 +97,7 @@ static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len, + ret = spi_sync_locked(phy->spi_device, &m); + if (ret < 0) + goto exit; +- if (phy->rx_buf[0] & 0x01) ++ if (phy->iobuf[0] & 0x01) + break; + } + +@@ -113,12 +111,12 @@ static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len, + spi_xfer.len = transfer_len; + spi_xfer.delay_usecs = 5; + +- if (direction) { ++ if (in) { + spi_xfer.tx_buf = NULL; +- spi_xfer.rx_buf = buffer; +- } else { +- spi_xfer.tx_buf = buffer; ++ } else if (out) { + spi_xfer.rx_buf = NULL; ++ memcpy(phy->iobuf, out, transfer_len); ++ out += transfer_len; + } + + spi_message_init(&m); +@@ -127,8 +125,12 @@ static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len, + if (ret < 0) + goto exit; + ++ if (in) { ++ memcpy(in, phy->iobuf, transfer_len); ++ in += transfer_len; ++ } ++ + len -= transfer_len; +- buffer += transfer_len; + } + + exit: +@@ -139,13 +141,13 @@ static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len, + static int tpm_tis_spi_read_bytes(struct tpm_tis_data *data, u32 addr, + u16 len, u8 *result) + { +- return tpm_tis_spi_transfer(data, addr, len, result, 0x80); ++ return tpm_tis_spi_transfer(data, addr, len, result, NULL); + } + + static int tpm_tis_spi_write_bytes(struct tpm_tis_data *data, u32 addr, +- u16 len, u8 *value) ++ u16 len, const u8 *value) + { +- return tpm_tis_spi_transfer(data, addr, len, value, 0); ++ return tpm_tis_spi_transfer(data, addr, len, NULL, value); + } + + static int tpm_tis_spi_read16(struct tpm_tis_data *data, u32 addr, u16 *result) +@@ -194,6 +196,10 @@ static int tpm_tis_spi_probe(struct spi_device *dev) + + phy->spi_device = dev; + ++ phy->iobuf = devm_kmalloc(&dev->dev, MAX_SPI_FRAMESIZE, GFP_KERNEL); ++ if (!phy->iobuf) ++ return -ENOMEM; ++ + return tpm_tis_core_init(&dev->dev, &phy->priv, -1, &tpm_spi_phy_ops, + NULL); + } +diff --git a/drivers/cpufreq/s3c24xx-cpufreq.c b/drivers/cpufreq/s3c24xx-cpufreq.c +index 7b596fa38ad2..6bebc1f9f55a 100644 +--- a/drivers/cpufreq/s3c24xx-cpufreq.c ++++ b/drivers/cpufreq/s3c24xx-cpufreq.c +@@ -351,7 +351,13 @@ struct clk *s3c_cpufreq_clk_get(struct device *dev, const char *name) + static int s3c_cpufreq_init(struct cpufreq_policy *policy) + { + policy->clk = clk_arm; +- return cpufreq_generic_init(policy, ftab, cpu_cur.info->latency); ++ ++ policy->cpuinfo.transition_latency = cpu_cur.info->latency; ++ ++ if (ftab) ++ return cpufreq_table_validate_and_show(policy, ftab); ++ ++ return 0; + } + + static int __init s3c_cpufreq_initclks(void) +diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c +index cd9d6ba03579..0dc0d595c47c 100644 +--- a/drivers/edac/sb_edac.c ++++ b/drivers/edac/sb_edac.c +@@ -279,7 +279,7 @@ static const u32 correrrthrsld[] = { + * sbridge structs + */ + +-#define NUM_CHANNELS 4 /* Max channels per MC */ ++#define NUM_CHANNELS 6 /* Max channels per MC */ + #define MAX_DIMMS 3 /* Max DIMMS per channel */ + #define KNL_MAX_CHAS 38 /* KNL max num. of Cache Home Agents */ + #define KNL_MAX_CHANNELS 6 /* KNL max num. of PCI channels */ +diff --git a/drivers/md/md.c b/drivers/md/md.c +index 6bf093cef958..e058c209bbcf 100644 +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -8522,6 +8522,10 @@ static int remove_and_add_spares(struct mddev *mddev, + int removed = 0; + bool remove_some = false; + ++ if (this && test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) ++ /* Mustn't remove devices when resync thread is running */ ++ return 0; ++ + rdev_for_each(rdev, mddev) { + if ((this == NULL || rdev == this) && + rdev->raid_disk >= 0 && +diff --git a/drivers/media/dvb-frontends/m88ds3103.c b/drivers/media/dvb-frontends/m88ds3103.c +index 50bce68ffd66..65d157fe76d1 100644 +--- a/drivers/media/dvb-frontends/m88ds3103.c ++++ b/drivers/media/dvb-frontends/m88ds3103.c +@@ -1262,11 +1262,12 @@ static int m88ds3103_select(struct i2c_mux_core *muxc, u32 chan) + * New users must use I2C client binding directly! + */ + struct dvb_frontend *m88ds3103_attach(const struct m88ds3103_config *cfg, +- struct i2c_adapter *i2c, struct i2c_adapter **tuner_i2c_adapter) ++ struct i2c_adapter *i2c, ++ struct i2c_adapter **tuner_i2c_adapter) + { + struct i2c_client *client; + struct i2c_board_info board_info; +- struct m88ds3103_platform_data pdata; ++ struct m88ds3103_platform_data pdata = {}; + + pdata.clk = cfg->clock; + pdata.i2c_wr_max = cfg->i2c_wr_max; +@@ -1409,6 +1410,8 @@ static int m88ds3103_probe(struct i2c_client *client, + case M88DS3103_CHIP_ID: + break; + default: ++ ret = -ENODEV; ++ dev_err(&client->dev, "Unknown device. Chip_id=%02x\n", dev->chip_id); + goto err_kfree; + } + +diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c +index 35026795be28..fa41d9422d57 100644 +--- a/drivers/mmc/host/dw_mmc-exynos.c ++++ b/drivers/mmc/host/dw_mmc-exynos.c +@@ -487,6 +487,7 @@ static unsigned long exynos_dwmmc_caps[4] = { + + static const struct dw_mci_drv_data exynos_drv_data = { + .caps = exynos_dwmmc_caps, ++ .num_caps = ARRAY_SIZE(exynos_dwmmc_caps), + .init = dw_mci_exynos_priv_init, + .set_ios = dw_mci_exynos_set_ios, + .parse_dt = dw_mci_exynos_parse_dt, +diff --git a/drivers/mmc/host/dw_mmc-k3.c b/drivers/mmc/host/dw_mmc-k3.c +index 64cda84b2302..864e7fcaffaf 100644 +--- a/drivers/mmc/host/dw_mmc-k3.c ++++ b/drivers/mmc/host/dw_mmc-k3.c +@@ -135,6 +135,9 @@ static int dw_mci_hi6220_parse_dt(struct dw_mci *host) + if (priv->ctrl_id < 0) + priv->ctrl_id = 0; + ++ if (priv->ctrl_id >= TIMING_MODE) ++ return -EINVAL; ++ + host->priv = priv; + return 0; + } +@@ -207,6 +210,7 @@ static int dw_mci_hi6220_execute_tuning(struct dw_mci_slot *slot, u32 opcode) + + static const struct dw_mci_drv_data hi6220_data = { + .caps = dw_mci_hi6220_caps, ++ .num_caps = ARRAY_SIZE(dw_mci_hi6220_caps), + .switch_voltage = dw_mci_hi6220_switch_voltage, + .set_ios = dw_mci_hi6220_set_ios, + .parse_dt = dw_mci_hi6220_parse_dt, +diff --git a/drivers/mmc/host/dw_mmc-rockchip.c b/drivers/mmc/host/dw_mmc-rockchip.c +index a3f1c2b30145..339295212935 100644 +--- a/drivers/mmc/host/dw_mmc-rockchip.c ++++ b/drivers/mmc/host/dw_mmc-rockchip.c +@@ -319,6 +319,7 @@ static const struct dw_mci_drv_data rk2928_drv_data = { + + static const struct dw_mci_drv_data rk3288_drv_data = { + .caps = dw_mci_rk3288_dwmmc_caps, ++ .num_caps = ARRAY_SIZE(dw_mci_rk3288_dwmmc_caps), + .set_ios = dw_mci_rk3288_set_ios, + .execute_tuning = dw_mci_rk3288_execute_tuning, + .parse_dt = dw_mci_rk3288_parse_dt, +diff --git a/drivers/mmc/host/dw_mmc-zx.c b/drivers/mmc/host/dw_mmc-zx.c +index d38e94ae2b85..c06b5393312f 100644 +--- a/drivers/mmc/host/dw_mmc-zx.c ++++ b/drivers/mmc/host/dw_mmc-zx.c +@@ -195,6 +195,7 @@ static unsigned long zx_dwmmc_caps[3] = { + + static const struct dw_mci_drv_data zx_drv_data = { + .caps = zx_dwmmc_caps, ++ .num_caps = ARRAY_SIZE(zx_dwmmc_caps), + .execute_tuning = dw_mci_zx_execute_tuning, + .prepare_hs400_tuning = dw_mci_zx_prepare_hs400_tuning, + .parse_dt = dw_mci_zx_parse_dt, +diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c +index 4f2806720c5c..60341a814055 100644 +--- a/drivers/mmc/host/dw_mmc.c ++++ b/drivers/mmc/host/dw_mmc.c +@@ -165,6 +165,8 @@ static int dw_mci_regs_show(struct seq_file *s, void *v) + { + struct dw_mci *host = s->private; + ++ pm_runtime_get_sync(host->dev); ++ + seq_printf(s, "STATUS:\t0x%08x\n", mci_readl(host, STATUS)); + seq_printf(s, "RINTSTS:\t0x%08x\n", mci_readl(host, RINTSTS)); + seq_printf(s, "CMD:\t0x%08x\n", mci_readl(host, CMD)); +@@ -172,6 +174,8 @@ static int dw_mci_regs_show(struct seq_file *s, void *v) + seq_printf(s, "INTMASK:\t0x%08x\n", mci_readl(host, INTMASK)); + seq_printf(s, "CLKENA:\t0x%08x\n", mci_readl(host, CLKENA)); + ++ pm_runtime_put_autosuspend(host->dev); ++ + return 0; + } + +@@ -2758,12 +2762,57 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) + return IRQ_HANDLED; + } + ++static int dw_mci_init_slot_caps(struct dw_mci_slot *slot) ++{ ++ struct dw_mci *host = slot->host; ++ const struct dw_mci_drv_data *drv_data = host->drv_data; ++ struct mmc_host *mmc = slot->mmc; ++ int ctrl_id; ++ ++ if (host->pdata->caps) ++ mmc->caps = host->pdata->caps; ++ ++ /* ++ * Support MMC_CAP_ERASE by default. ++ * It needs to use trim/discard/erase commands. ++ */ ++ mmc->caps |= MMC_CAP_ERASE; ++ ++ if (host->pdata->pm_caps) ++ mmc->pm_caps = host->pdata->pm_caps; ++ ++ if (host->dev->of_node) { ++ ctrl_id = of_alias_get_id(host->dev->of_node, "mshc"); ++ if (ctrl_id < 0) ++ ctrl_id = 0; ++ } else { ++ ctrl_id = to_platform_device(host->dev)->id; ++ } ++ ++ if (drv_data && drv_data->caps) { ++ if (ctrl_id >= drv_data->num_caps) { ++ dev_err(host->dev, "invalid controller id %d\n", ++ ctrl_id); ++ return -EINVAL; ++ } ++ mmc->caps |= drv_data->caps[ctrl_id]; ++ } ++ ++ if (host->pdata->caps2) ++ mmc->caps2 = host->pdata->caps2; ++ ++ /* Process SDIO IRQs through the sdio_irq_work. */ ++ if (mmc->caps & MMC_CAP_SDIO_IRQ) ++ mmc->caps2 |= MMC_CAP2_SDIO_IRQ_NOTHREAD; ++ ++ return 0; ++} ++ + static int dw_mci_init_slot(struct dw_mci *host) + { + struct mmc_host *mmc; + struct dw_mci_slot *slot; +- const struct dw_mci_drv_data *drv_data = host->drv_data; +- int ctrl_id, ret; ++ int ret; + u32 freq[2]; + + mmc = mmc_alloc_host(sizeof(struct dw_mci_slot), host->dev); +@@ -2797,38 +2846,13 @@ static int dw_mci_init_slot(struct dw_mci *host) + if (!mmc->ocr_avail) + mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; + +- if (host->pdata->caps) +- mmc->caps = host->pdata->caps; +- +- /* +- * Support MMC_CAP_ERASE by default. +- * It needs to use trim/discard/erase commands. +- */ +- mmc->caps |= MMC_CAP_ERASE; +- +- if (host->pdata->pm_caps) +- mmc->pm_caps = host->pdata->pm_caps; +- +- if (host->dev->of_node) { +- ctrl_id = of_alias_get_id(host->dev->of_node, "mshc"); +- if (ctrl_id < 0) +- ctrl_id = 0; +- } else { +- ctrl_id = to_platform_device(host->dev)->id; +- } +- if (drv_data && drv_data->caps) +- mmc->caps |= drv_data->caps[ctrl_id]; +- +- if (host->pdata->caps2) +- mmc->caps2 = host->pdata->caps2; +- + ret = mmc_of_parse(mmc); + if (ret) + goto err_host_allocated; + +- /* Process SDIO IRQs through the sdio_irq_work. */ +- if (mmc->caps & MMC_CAP_SDIO_IRQ) +- mmc->caps2 |= MMC_CAP2_SDIO_IRQ_NOTHREAD; ++ ret = dw_mci_init_slot_caps(slot); ++ if (ret) ++ goto err_host_allocated; + + /* Useful defaults if platform data is unset. */ + if (host->use_dma == TRANS_MODE_IDMAC) { +diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h +index 34474ad731aa..044c87ce6725 100644 +--- a/drivers/mmc/host/dw_mmc.h ++++ b/drivers/mmc/host/dw_mmc.h +@@ -542,6 +542,7 @@ struct dw_mci_slot { + /** + * dw_mci driver data - dw-mshc implementation specific driver data. + * @caps: mmc subsystem specified capabilities of the controller(s). ++ * @num_caps: number of capabilities specified by @caps. + * @init: early implementation specific initialization. + * @set_ios: handle bus specific extensions. + * @parse_dt: parse implementation specific device tree properties. +@@ -553,6 +554,7 @@ struct dw_mci_slot { + */ + struct dw_mci_drv_data { + unsigned long *caps; ++ u32 num_caps; + int (*init)(struct dw_mci *host); + void (*set_ios)(struct dw_mci *host, struct mmc_ios *ios); + int (*parse_dt)(struct dw_mci *host); +diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c +index 67d787fa3306..070f5da06fd2 100644 +--- a/drivers/mmc/host/sdhci-pci-core.c ++++ b/drivers/mmc/host/sdhci-pci-core.c +@@ -594,9 +594,36 @@ static void byt_read_dsm(struct sdhci_pci_slot *slot) + slot->chip->rpm_retune = intel_host->d3_retune; + } + +-static int byt_emmc_probe_slot(struct sdhci_pci_slot *slot) ++static int intel_execute_tuning(struct mmc_host *mmc, u32 opcode) ++{ ++ int err = sdhci_execute_tuning(mmc, opcode); ++ struct sdhci_host *host = mmc_priv(mmc); ++ ++ if (err) ++ return err; ++ ++ /* ++ * Tuning can leave the IP in an active state (Buffer Read Enable bit ++ * set) which prevents the entry to low power states (i.e. S0i3). Data ++ * reset will clear it. ++ */ ++ sdhci_reset(host, SDHCI_RESET_DATA); ++ ++ return 0; ++} ++ ++static void byt_probe_slot(struct sdhci_pci_slot *slot) + { ++ struct mmc_host_ops *ops = &slot->host->mmc_host_ops; ++ + byt_read_dsm(slot); ++ ++ ops->execute_tuning = intel_execute_tuning; ++} ++ ++static int byt_emmc_probe_slot(struct sdhci_pci_slot *slot) ++{ ++ byt_probe_slot(slot); + slot->host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE | + MMC_CAP_HW_RESET | MMC_CAP_1_8V_DDR | + MMC_CAP_CMD_DURING_TFR | +@@ -651,7 +678,7 @@ static int ni_byt_sdio_probe_slot(struct sdhci_pci_slot *slot) + { + int err; + +- byt_read_dsm(slot); ++ byt_probe_slot(slot); + + err = ni_set_max_freq(slot); + if (err) +@@ -664,7 +691,7 @@ static int ni_byt_sdio_probe_slot(struct sdhci_pci_slot *slot) + + static int byt_sdio_probe_slot(struct sdhci_pci_slot *slot) + { +- byt_read_dsm(slot); ++ byt_probe_slot(slot); + slot->host->mmc->caps |= MMC_CAP_POWER_OFF_CARD | MMC_CAP_NONREMOVABLE | + MMC_CAP_WAIT_WHILE_BUSY; + return 0; +@@ -672,7 +699,7 @@ static int byt_sdio_probe_slot(struct sdhci_pci_slot *slot) + + static int byt_sd_probe_slot(struct sdhci_pci_slot *slot) + { +- byt_read_dsm(slot); ++ byt_probe_slot(slot); + slot->host->mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY | + MMC_CAP_AGGRESSIVE_PM | MMC_CAP_CD_WAKE; + slot->cd_idx = 0; +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +index 608693d11bd7..75c4455e2271 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +@@ -595,7 +595,7 @@ static void xgbe_isr_task(unsigned long data) + + reissue_mask = 1 << 0; + if (!pdata->per_channel_irq) +- reissue_mask |= 0xffff < 4; ++ reissue_mask |= 0xffff << 4; + + XP_IOWRITE(pdata, XP_INT_REISSUE_EN, reissue_mask); + } +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-pci.c b/drivers/net/ethernet/amd/xgbe/xgbe-pci.c +index 3e5833cf1fab..eb23f9ba1a9a 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-pci.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-pci.c +@@ -426,6 +426,8 @@ static int xgbe_pci_resume(struct pci_dev *pdev) + struct net_device *netdev = pdata->netdev; + int ret = 0; + ++ XP_IOWRITE(pdata, XP_INT_EN, 0x1fffff); ++ + pdata->lpm_ctrl &= ~MDIO_CTRL1_LPOWER; + XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, pdata->lpm_ctrl); + +diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +index 879a9c4cef59..29f600fd6977 100644 +--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c ++++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +@@ -1877,6 +1877,14 @@ static void ixgbe_dma_sync_frag(struct ixgbe_ring *rx_ring, + ixgbe_rx_pg_size(rx_ring), + DMA_FROM_DEVICE, + IXGBE_RX_DMA_ATTR); ++ } else if (ring_uses_build_skb(rx_ring)) { ++ unsigned long offset = (unsigned long)(skb->data) & ~PAGE_MASK; ++ ++ dma_sync_single_range_for_cpu(rx_ring->dev, ++ IXGBE_CB(skb)->dma, ++ offset, ++ skb_headlen(skb), ++ DMA_FROM_DEVICE); + } else { + struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[0]; + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +index 3cdb932cae76..a863572882b2 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +@@ -1918,13 +1918,16 @@ static void mlx5e_build_rq_param(struct mlx5e_priv *priv, + param->wq.linear = 1; + } + +-static void mlx5e_build_drop_rq_param(struct mlx5e_rq_param *param) ++static void mlx5e_build_drop_rq_param(struct mlx5_core_dev *mdev, ++ struct mlx5e_rq_param *param) + { + void *rqc = param->rqc; + void *wq = MLX5_ADDR_OF(rqc, rqc, wq); + + MLX5_SET(wq, wq, wq_type, MLX5_WQ_TYPE_LINKED_LIST); + MLX5_SET(wq, wq, log_wq_stride, ilog2(sizeof(struct mlx5e_rx_wqe))); ++ ++ param->wq.buf_numa_node = dev_to_node(&mdev->pdev->dev); + } + + static void mlx5e_build_sq_param_common(struct mlx5e_priv *priv, +@@ -2778,6 +2781,9 @@ static int mlx5e_alloc_drop_cq(struct mlx5_core_dev *mdev, + struct mlx5e_cq *cq, + struct mlx5e_cq_param *param) + { ++ param->wq.buf_numa_node = dev_to_node(&mdev->pdev->dev); ++ param->wq.db_numa_node = dev_to_node(&mdev->pdev->dev); ++ + return mlx5e_alloc_cq_common(mdev, param, cq); + } + +@@ -2789,7 +2795,7 @@ static int mlx5e_open_drop_rq(struct mlx5_core_dev *mdev, + struct mlx5e_cq *cq = &drop_rq->cq; + int err; + +- mlx5e_build_drop_rq_param(&rq_param); ++ mlx5e_build_drop_rq_param(mdev, &rq_param); + + err = mlx5e_alloc_drop_cq(mdev, cq, &cq_param); + if (err) +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c +index 91b1b0938931..3476f594c195 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c +@@ -36,6 +36,7 @@ + #include + #include + #include ++#include + #include "en.h" + #include "en_tc.h" + #include "eswitch.h" +@@ -546,20 +547,33 @@ bool mlx5e_post_rx_mpwqes(struct mlx5e_rq *rq) + return true; + } + ++static void mlx5e_lro_update_tcp_hdr(struct mlx5_cqe64 *cqe, struct tcphdr *tcp) ++{ ++ u8 l4_hdr_type = get_cqe_l4_hdr_type(cqe); ++ u8 tcp_ack = (l4_hdr_type == CQE_L4_HDR_TYPE_TCP_ACK_NO_DATA) || ++ (l4_hdr_type == CQE_L4_HDR_TYPE_TCP_ACK_AND_DATA); ++ ++ tcp->check = 0; ++ tcp->psh = get_cqe_lro_tcppsh(cqe); ++ ++ if (tcp_ack) { ++ tcp->ack = 1; ++ tcp->ack_seq = cqe->lro_ack_seq_num; ++ tcp->window = cqe->lro_tcp_win; ++ } ++} ++ + static void mlx5e_lro_update_hdr(struct sk_buff *skb, struct mlx5_cqe64 *cqe, + u32 cqe_bcnt) + { + struct ethhdr *eth = (struct ethhdr *)(skb->data); + struct tcphdr *tcp; + int network_depth = 0; ++ __wsum check; + __be16 proto; + u16 tot_len; + void *ip_p; + +- u8 l4_hdr_type = get_cqe_l4_hdr_type(cqe); +- u8 tcp_ack = (l4_hdr_type == CQE_L4_HDR_TYPE_TCP_ACK_NO_DATA) || +- (l4_hdr_type == CQE_L4_HDR_TYPE_TCP_ACK_AND_DATA); +- + skb->mac_len = ETH_HLEN; + proto = __vlan_get_protocol(skb, eth->h_proto, &network_depth); + +@@ -577,23 +591,30 @@ static void mlx5e_lro_update_hdr(struct sk_buff *skb, struct mlx5_cqe64 *cqe, + ipv4->check = 0; + ipv4->check = ip_fast_csum((unsigned char *)ipv4, + ipv4->ihl); ++ ++ mlx5e_lro_update_tcp_hdr(cqe, tcp); ++ check = csum_partial(tcp, tcp->doff * 4, ++ csum_unfold((__force __sum16)cqe->check_sum)); ++ /* Almost done, don't forget the pseudo header */ ++ tcp->check = csum_tcpudp_magic(ipv4->saddr, ipv4->daddr, ++ tot_len - sizeof(struct iphdr), ++ IPPROTO_TCP, check); + } else { ++ u16 payload_len = tot_len - sizeof(struct ipv6hdr); + struct ipv6hdr *ipv6 = ip_p; + + tcp = ip_p + sizeof(struct ipv6hdr); + skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6; + + ipv6->hop_limit = cqe->lro_min_ttl; +- ipv6->payload_len = cpu_to_be16(tot_len - +- sizeof(struct ipv6hdr)); +- } +- +- tcp->psh = get_cqe_lro_tcppsh(cqe); +- +- if (tcp_ack) { +- tcp->ack = 1; +- tcp->ack_seq = cqe->lro_ack_seq_num; +- tcp->window = cqe->lro_tcp_win; ++ ipv6->payload_len = cpu_to_be16(payload_len); ++ ++ mlx5e_lro_update_tcp_hdr(cqe, tcp); ++ check = csum_partial(tcp, tcp->doff * 4, ++ csum_unfold((__force __sum16)cqe->check_sum)); ++ /* Almost done, don't forget the pseudo header */ ++ tcp->check = csum_ipv6_magic(&ipv6->saddr, &ipv6->daddr, payload_len, ++ IPPROTO_TCP, check); + } + } + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c b/drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c +index 5a4608281f38..707976482c09 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c +@@ -216,7 +216,8 @@ mlx5e_test_loopback_validate(struct sk_buff *skb, + if (iph->protocol != IPPROTO_UDP) + goto out; + +- udph = udp_hdr(skb); ++ /* Don't assume skb_transport_header() was set */ ++ udph = (struct udphdr *)((u8 *)iph + 4 * iph->ihl); + if (udph->dest != htons(9)) + goto out; + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c +index 1d6925d4369a..eea7f931cad3 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c +@@ -155,7 +155,7 @@ static inline u16 mlx5e_calc_min_inline(enum mlx5_inline_modes mode, + default: + hlen = mlx5e_skb_l2_header_offset(skb); + } +- return min_t(u16, hlen, skb->len); ++ return min_t(u16, hlen, skb_headlen(skb)); + } + + static inline void mlx5e_tx_skb_pull_inline(unsigned char **skb_data, +diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +index 7bef80676464..516e63244606 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +@@ -729,26 +729,29 @@ static struct mlxsw_sp_fib *mlxsw_sp_vr_fib(const struct mlxsw_sp_vr *vr, + static struct mlxsw_sp_vr *mlxsw_sp_vr_create(struct mlxsw_sp *mlxsw_sp, + u32 tb_id) + { ++ struct mlxsw_sp_fib *fib4; ++ struct mlxsw_sp_fib *fib6; + struct mlxsw_sp_vr *vr; + int err; + + vr = mlxsw_sp_vr_find_unused(mlxsw_sp); + if (!vr) + return ERR_PTR(-EBUSY); +- vr->fib4 = mlxsw_sp_fib_create(vr, MLXSW_SP_L3_PROTO_IPV4); +- if (IS_ERR(vr->fib4)) +- return ERR_CAST(vr->fib4); +- vr->fib6 = mlxsw_sp_fib_create(vr, MLXSW_SP_L3_PROTO_IPV6); +- if (IS_ERR(vr->fib6)) { +- err = PTR_ERR(vr->fib6); ++ fib4 = mlxsw_sp_fib_create(vr, MLXSW_SP_L3_PROTO_IPV4); ++ if (IS_ERR(fib4)) ++ return ERR_CAST(fib4); ++ fib6 = mlxsw_sp_fib_create(vr, MLXSW_SP_L3_PROTO_IPV6); ++ if (IS_ERR(fib6)) { ++ err = PTR_ERR(fib6); + goto err_fib6_create; + } ++ vr->fib4 = fib4; ++ vr->fib6 = fib6; + vr->tb_id = tb_id; + return vr; + + err_fib6_create: +- mlxsw_sp_fib_destroy(vr->fib4); +- vr->fib4 = NULL; ++ mlxsw_sp_fib_destroy(fib4); + return ERR_PTR(err); + } + +@@ -3029,6 +3032,9 @@ mlxsw_sp_fib4_entry_offload_unset(struct mlxsw_sp_fib_entry *fib_entry) + struct mlxsw_sp_nexthop_group *nh_grp = fib_entry->nh_group; + int i; + ++ if (!list_is_singular(&nh_grp->fib_list)) ++ return; ++ + for (i = 0; i < nh_grp->count; i++) { + struct mlxsw_sp_nexthop *nh = &nh_grp->nexthops[i]; + +diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +index f5863e5bec81..42a6afcaae03 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +@@ -1098,6 +1098,7 @@ static int __mlxsw_sp_port_fdb_uc_op(struct mlxsw_sp *mlxsw_sp, u8 local_port, + bool dynamic) + { + char *sfd_pl; ++ u8 num_rec; + int err; + + sfd_pl = kmalloc(MLXSW_REG_SFD_LEN, GFP_KERNEL); +@@ -1107,9 +1108,16 @@ static int __mlxsw_sp_port_fdb_uc_op(struct mlxsw_sp *mlxsw_sp, u8 local_port, + mlxsw_reg_sfd_pack(sfd_pl, mlxsw_sp_sfd_op(adding), 0); + mlxsw_reg_sfd_uc_pack(sfd_pl, 0, mlxsw_sp_sfd_rec_policy(dynamic), + mac, fid, action, local_port); ++ num_rec = mlxsw_reg_sfd_num_rec_get(sfd_pl); + err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfd), sfd_pl); +- kfree(sfd_pl); ++ if (err) ++ goto out; ++ ++ if (num_rec != mlxsw_reg_sfd_num_rec_get(sfd_pl)) ++ err = -EBUSY; + ++out: ++ kfree(sfd_pl); + return err; + } + +@@ -1134,6 +1142,7 @@ static int mlxsw_sp_port_fdb_uc_lag_op(struct mlxsw_sp *mlxsw_sp, u16 lag_id, + bool adding, bool dynamic) + { + char *sfd_pl; ++ u8 num_rec; + int err; + + sfd_pl = kmalloc(MLXSW_REG_SFD_LEN, GFP_KERNEL); +@@ -1144,9 +1153,16 @@ static int mlxsw_sp_port_fdb_uc_lag_op(struct mlxsw_sp *mlxsw_sp, u16 lag_id, + mlxsw_reg_sfd_uc_lag_pack(sfd_pl, 0, mlxsw_sp_sfd_rec_policy(dynamic), + mac, fid, MLXSW_REG_SFD_REC_ACTION_NOP, + lag_vid, lag_id); ++ num_rec = mlxsw_reg_sfd_num_rec_get(sfd_pl); + err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfd), sfd_pl); +- kfree(sfd_pl); ++ if (err) ++ goto out; ++ ++ if (num_rec != mlxsw_reg_sfd_num_rec_get(sfd_pl)) ++ err = -EBUSY; + ++out: ++ kfree(sfd_pl); + return err; + } + +@@ -1191,6 +1207,7 @@ static int mlxsw_sp_port_mdb_op(struct mlxsw_sp *mlxsw_sp, const char *addr, + u16 fid, u16 mid, bool adding) + { + char *sfd_pl; ++ u8 num_rec; + int err; + + sfd_pl = kmalloc(MLXSW_REG_SFD_LEN, GFP_KERNEL); +@@ -1200,7 +1217,15 @@ static int mlxsw_sp_port_mdb_op(struct mlxsw_sp *mlxsw_sp, const char *addr, + mlxsw_reg_sfd_pack(sfd_pl, mlxsw_sp_sfd_op(adding), 0); + mlxsw_reg_sfd_mc_pack(sfd_pl, 0, addr, fid, + MLXSW_REG_SFD_REC_ACTION_NOP, mid); ++ num_rec = mlxsw_reg_sfd_num_rec_get(sfd_pl); + err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfd), sfd_pl); ++ if (err) ++ goto out; ++ ++ if (num_rec != mlxsw_reg_sfd_num_rec_get(sfd_pl)) ++ err = -EBUSY; ++ ++out: + kfree(sfd_pl); + return err; + } +diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c +index db8a4bcfc6c7..14b646b3b084 100644 +--- a/drivers/net/ethernet/ti/cpsw.c ++++ b/drivers/net/ethernet/ti/cpsw.c +@@ -1618,6 +1618,7 @@ static netdev_tx_t cpsw_ndo_start_xmit(struct sk_buff *skb, + q_idx = q_idx % cpsw->tx_ch_num; + + txch = cpsw->txv[q_idx].ch; ++ txq = netdev_get_tx_queue(ndev, q_idx); + ret = cpsw_tx_packet_submit(priv, skb, txch); + if (unlikely(ret != 0)) { + cpsw_err(priv, tx_err, "desc submit failed\n"); +@@ -1628,15 +1629,26 @@ static netdev_tx_t cpsw_ndo_start_xmit(struct sk_buff *skb, + * tell the kernel to stop sending us tx frames. + */ + if (unlikely(!cpdma_check_free_tx_desc(txch))) { +- txq = netdev_get_tx_queue(ndev, q_idx); + netif_tx_stop_queue(txq); ++ ++ /* Barrier, so that stop_queue visible to other cpus */ ++ smp_mb__after_atomic(); ++ ++ if (cpdma_check_free_tx_desc(txch)) ++ netif_tx_wake_queue(txq); + } + + return NETDEV_TX_OK; + fail: + ndev->stats.tx_dropped++; +- txq = netdev_get_tx_queue(ndev, skb_get_queue_mapping(skb)); + netif_tx_stop_queue(txq); ++ ++ /* Barrier, so that stop_queue visible to other cpus */ ++ smp_mb__after_atomic(); ++ ++ if (cpdma_check_free_tx_desc(txch)) ++ netif_tx_wake_queue(txq); ++ + return NETDEV_TX_BUSY; + } + +diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c +index 2b1e67bc1e73..3d860de5e342 100644 +--- a/drivers/net/phy/phy.c ++++ b/drivers/net/phy/phy.c +@@ -842,7 +842,7 @@ void phy_start(struct phy_device *phydev) + break; + case PHY_HALTED: + /* make sure interrupts are re-enabled for the PHY */ +- if (phydev->irq != PHY_POLL) { ++ if (phy_interrupt_is_valid(phydev)) { + err = phy_enable_interrupts(phydev); + if (err < 0) + break; +diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c +index 8c6b8918ec31..38cd2e8fae23 100644 +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -3158,6 +3158,15 @@ ppp_connect_channel(struct channel *pch, int unit) + goto outl; + + ppp_lock(ppp); ++ spin_lock_bh(&pch->downl); ++ if (!pch->chan) { ++ /* Don't connect unregistered channels */ ++ spin_unlock_bh(&pch->downl); ++ ppp_unlock(ppp); ++ ret = -ENOTCONN; ++ goto outl; ++ } ++ spin_unlock_bh(&pch->downl); + if (pch->file.hdrlen > ppp->file.hdrlen) + ppp->file.hdrlen = pch->file.hdrlen; + hdrlen = pch->file.hdrlen + 2; /* for protocol bytes */ +diff --git a/drivers/net/tun.c b/drivers/net/tun.c +index fa51b7b0e9ea..bc38d54e37b9 100644 +--- a/drivers/net/tun.c ++++ b/drivers/net/tun.c +@@ -1315,6 +1315,7 @@ static struct sk_buff *tun_build_skb(struct tun_struct *tun, + else + *skb_xdp = 0; + ++ preempt_disable(); + rcu_read_lock(); + xdp_prog = rcu_dereference(tun->xdp_prog); + if (xdp_prog && !*skb_xdp) { +@@ -1333,9 +1334,11 @@ static struct sk_buff *tun_build_skb(struct tun_struct *tun, + get_page(alloc_frag->page); + alloc_frag->offset += buflen; + err = xdp_do_redirect(tun->dev, &xdp, xdp_prog); ++ xdp_do_flush_map(); + if (err) + goto err_redirect; + rcu_read_unlock(); ++ preempt_enable(); + return NULL; + case XDP_TX: + xdp_xmit = true; +@@ -1357,6 +1360,7 @@ static struct sk_buff *tun_build_skb(struct tun_struct *tun, + skb = build_skb(buf, buflen); + if (!skb) { + rcu_read_unlock(); ++ preempt_enable(); + return ERR_PTR(-ENOMEM); + } + +@@ -1369,10 +1373,12 @@ static struct sk_buff *tun_build_skb(struct tun_struct *tun, + skb->dev = tun->dev; + generic_xdp_tx(skb, xdp_prog); + rcu_read_unlock(); ++ preempt_enable(); + return NULL; + } + + rcu_read_unlock(); ++ preempt_enable(); + + return skb; + +@@ -1380,6 +1386,7 @@ static struct sk_buff *tun_build_skb(struct tun_struct *tun, + put_page(alloc_frag->page); + err_xdp: + rcu_read_unlock(); ++ preempt_enable(); + this_cpu_inc(tun->pcpu_stats->rx_dropped); + return NULL; + } +diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c +index 7927e28f5336..6a785595b9b8 100644 +--- a/drivers/net/virtio_net.c ++++ b/drivers/net/virtio_net.c +@@ -1995,8 +1995,9 @@ static int virtnet_xdp_set(struct net_device *dev, struct bpf_prog *prog, + } + + /* Make sure NAPI is not using any XDP TX queues for RX. */ +- for (i = 0; i < vi->max_queue_pairs; i++) +- napi_disable(&vi->rq[i].napi); ++ if (netif_running(dev)) ++ for (i = 0; i < vi->max_queue_pairs; i++) ++ napi_disable(&vi->rq[i].napi); + + netif_set_real_num_rx_queues(dev, curr_qp + xdp_qp); + err = _virtnet_set_queues(vi, curr_qp + xdp_qp); +@@ -2015,7 +2016,8 @@ static int virtnet_xdp_set(struct net_device *dev, struct bpf_prog *prog, + } + if (old_prog) + bpf_prog_put(old_prog); +- virtnet_napi_enable(vi->rq[i].vq, &vi->rq[i].napi); ++ if (netif_running(dev)) ++ virtnet_napi_enable(vi->rq[i].vq, &vi->rq[i].napi); + } + + return 0; +diff --git a/drivers/net/wan/hdlc_ppp.c b/drivers/net/wan/hdlc_ppp.c +index 0d2e00ece804..f3c1d5245978 100644 +--- a/drivers/net/wan/hdlc_ppp.c ++++ b/drivers/net/wan/hdlc_ppp.c +@@ -574,7 +574,10 @@ static void ppp_timer(unsigned long arg) + ppp_cp_event(proto->dev, proto->pid, TO_GOOD, 0, 0, + 0, NULL); + proto->restart_counter--; +- } else ++ } else if (netif_carrier_ok(proto->dev)) ++ ppp_cp_event(proto->dev, proto->pid, TO_GOOD, 0, 0, ++ 0, NULL); ++ else + ppp_cp_event(proto->dev, proto->pid, TO_BAD, 0, 0, + 0, NULL); + break; +diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c +index 33d4431c2b4b..93a082e0bdd4 100644 +--- a/drivers/nvme/host/rdma.c ++++ b/drivers/nvme/host/rdma.c +@@ -88,7 +88,6 @@ enum nvme_rdma_queue_flags { + + struct nvme_rdma_queue { + struct nvme_rdma_qe *rsp_ring; +- atomic_t sig_count; + int queue_size; + size_t cmnd_capsule_len; + struct nvme_rdma_ctrl *ctrl; +@@ -521,7 +520,6 @@ static int nvme_rdma_alloc_queue(struct nvme_rdma_ctrl *ctrl, + queue->cmnd_capsule_len = sizeof(struct nvme_command); + + queue->queue_size = queue_size; +- atomic_set(&queue->sig_count, 0); + + queue->cm_id = rdma_create_id(&init_net, nvme_rdma_cm_handler, queue, + RDMA_PS_TCP, IB_QPT_RC); +@@ -1232,21 +1230,9 @@ static void nvme_rdma_send_done(struct ib_cq *cq, struct ib_wc *wc) + nvme_end_request(rq, req->status, req->result); + } + +-/* +- * We want to signal completion at least every queue depth/2. This returns the +- * largest power of two that is not above half of (queue size + 1) to optimize +- * (avoid divisions). +- */ +-static inline bool nvme_rdma_queue_sig_limit(struct nvme_rdma_queue *queue) +-{ +- int limit = 1 << ilog2((queue->queue_size + 1) / 2); +- +- return (atomic_inc_return(&queue->sig_count) & (limit - 1)) == 0; +-} +- + static int nvme_rdma_post_send(struct nvme_rdma_queue *queue, + struct nvme_rdma_qe *qe, struct ib_sge *sge, u32 num_sge, +- struct ib_send_wr *first, bool flush) ++ struct ib_send_wr *first) + { + struct ib_send_wr wr, *bad_wr; + int ret; +@@ -1255,31 +1241,12 @@ static int nvme_rdma_post_send(struct nvme_rdma_queue *queue, + sge->length = sizeof(struct nvme_command), + sge->lkey = queue->device->pd->local_dma_lkey; + +- qe->cqe.done = nvme_rdma_send_done; +- + wr.next = NULL; + wr.wr_cqe = &qe->cqe; + wr.sg_list = sge; + wr.num_sge = num_sge; + wr.opcode = IB_WR_SEND; +- wr.send_flags = 0; +- +- /* +- * Unsignalled send completions are another giant desaster in the +- * IB Verbs spec: If we don't regularly post signalled sends +- * the send queue will fill up and only a QP reset will rescue us. +- * Would have been way to obvious to handle this in hardware or +- * at least the RDMA stack.. +- * +- * Always signal the flushes. The magic request used for the flush +- * sequencer is not allocated in our driver's tagset and it's +- * triggered to be freed by blk_cleanup_queue(). So we need to +- * always mark it as signaled to ensure that the "wr_cqe", which is +- * embedded in request's payload, is not freed when __ib_process_cq() +- * calls wr_cqe->done(). +- */ +- if (nvme_rdma_queue_sig_limit(queue) || flush) +- wr.send_flags |= IB_SEND_SIGNALED; ++ wr.send_flags = IB_SEND_SIGNALED; + + if (first) + first->next = ≀ +@@ -1329,6 +1296,12 @@ static struct blk_mq_tags *nvme_rdma_tagset(struct nvme_rdma_queue *queue) + return queue->ctrl->tag_set.tags[queue_idx - 1]; + } + ++static void nvme_rdma_async_done(struct ib_cq *cq, struct ib_wc *wc) ++{ ++ if (unlikely(wc->status != IB_WC_SUCCESS)) ++ nvme_rdma_wr_error(cq, wc, "ASYNC"); ++} ++ + static void nvme_rdma_submit_async_event(struct nvme_ctrl *arg, int aer_idx) + { + struct nvme_rdma_ctrl *ctrl = to_rdma_ctrl(arg); +@@ -1350,10 +1323,12 @@ static void nvme_rdma_submit_async_event(struct nvme_ctrl *arg, int aer_idx) + cmd->common.flags |= NVME_CMD_SGL_METABUF; + nvme_rdma_set_sg_null(cmd); + ++ sqe->cqe.done = nvme_rdma_async_done; ++ + ib_dma_sync_single_for_device(dev, sqe->dma, sizeof(*cmd), + DMA_TO_DEVICE); + +- ret = nvme_rdma_post_send(queue, sqe, &sge, 1, NULL, false); ++ ret = nvme_rdma_post_send(queue, sqe, &sge, 1, NULL); + WARN_ON_ONCE(ret); + } + +@@ -1639,7 +1614,6 @@ static blk_status_t nvme_rdma_queue_rq(struct blk_mq_hw_ctx *hctx, + struct nvme_rdma_request *req = blk_mq_rq_to_pdu(rq); + struct nvme_rdma_qe *sqe = &req->sqe; + struct nvme_command *c = sqe->data; +- bool flush = false; + struct ib_device *dev; + blk_status_t ret; + int err; +@@ -1668,13 +1642,13 @@ static blk_status_t nvme_rdma_queue_rq(struct blk_mq_hw_ctx *hctx, + goto err; + } + ++ sqe->cqe.done = nvme_rdma_send_done; ++ + ib_dma_sync_single_for_device(dev, sqe->dma, + sizeof(struct nvme_command), DMA_TO_DEVICE); + +- if (req_op(rq) == REQ_OP_FLUSH) +- flush = true; + err = nvme_rdma_post_send(queue, sqe, req->sge, req->num_sge, +- req->mr->need_inval ? &req->reg_wr.wr : NULL, flush); ++ req->mr->need_inval ? &req->reg_wr.wr : NULL); + if (unlikely(err)) { + nvme_rdma_unmap_data(queue, rq); + goto err; +diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c +index cae54f8320be..633e55c57b13 100644 +--- a/drivers/pci/pcie/aspm.c ++++ b/drivers/pci/pcie/aspm.c +@@ -803,10 +803,14 @@ static struct pcie_link_state *alloc_pcie_link_state(struct pci_dev *pdev) + + /* + * Root Ports and PCI/PCI-X to PCIe Bridges are roots of PCIe +- * hierarchies. ++ * hierarchies. Note that some PCIe host implementations omit ++ * the root ports entirely, in which case a downstream port on ++ * a switch may become the root of the link state chain for all ++ * its subordinate endpoints. + */ + if (pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT || +- pci_pcie_type(pdev) == PCI_EXP_TYPE_PCIE_BRIDGE) { ++ pci_pcie_type(pdev) == PCI_EXP_TYPE_PCIE_BRIDGE || ++ !pdev->bus->parent->self) { + link->root = link; + } else { + struct pcie_link_state *parent; +diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h +index 92dd4aef21a3..6b1e83539a9d 100644 +--- a/drivers/s390/net/qeth_core.h ++++ b/drivers/s390/net/qeth_core.h +@@ -580,6 +580,11 @@ struct qeth_cmd_buffer { + void (*callback) (struct qeth_channel *, struct qeth_cmd_buffer *); + }; + ++static inline struct qeth_ipa_cmd *__ipa_cmd(struct qeth_cmd_buffer *iob) ++{ ++ return (struct qeth_ipa_cmd *)(iob->data + IPA_PDU_HEADER_SIZE); ++} ++ + /** + * definition of a qeth channel, used for read and write + */ +@@ -834,7 +839,7 @@ struct qeth_trap_id { + */ + static inline int qeth_get_elements_for_range(addr_t start, addr_t end) + { +- return PFN_UP(end - 1) - PFN_DOWN(start); ++ return PFN_UP(end) - PFN_DOWN(start); + } + + static inline int qeth_get_micros(void) +diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c +index 7c7a244b6684..145b57762d8f 100644 +--- a/drivers/s390/net/qeth_core_main.c ++++ b/drivers/s390/net/qeth_core_main.c +@@ -2073,7 +2073,7 @@ int qeth_send_control_data(struct qeth_card *card, int len, + unsigned long flags; + struct qeth_reply *reply = NULL; + unsigned long timeout, event_timeout; +- struct qeth_ipa_cmd *cmd; ++ struct qeth_ipa_cmd *cmd = NULL; + + QETH_CARD_TEXT(card, 2, "sendctl"); + +@@ -2087,23 +2087,27 @@ int qeth_send_control_data(struct qeth_card *card, int len, + } + reply->callback = reply_cb; + reply->param = reply_param; +- if (card->state == CARD_STATE_DOWN) +- reply->seqno = QETH_IDX_COMMAND_SEQNO; +- else +- reply->seqno = card->seqno.ipa++; ++ + init_waitqueue_head(&reply->wait_q); +- spin_lock_irqsave(&card->lock, flags); +- list_add_tail(&reply->list, &card->cmd_waiter_list); +- spin_unlock_irqrestore(&card->lock, flags); + QETH_DBF_HEX(CTRL, 2, iob->data, QETH_DBF_CTRL_LEN); + + while (atomic_cmpxchg(&card->write.irq_pending, 0, 1)) ; +- qeth_prepare_control_data(card, len, iob); + +- if (IS_IPA(iob->data)) ++ if (IS_IPA(iob->data)) { ++ cmd = __ipa_cmd(iob); ++ cmd->hdr.seqno = card->seqno.ipa++; ++ reply->seqno = cmd->hdr.seqno; + event_timeout = QETH_IPA_TIMEOUT; +- else ++ } else { ++ reply->seqno = QETH_IDX_COMMAND_SEQNO; + event_timeout = QETH_TIMEOUT; ++ } ++ qeth_prepare_control_data(card, len, iob); ++ ++ spin_lock_irqsave(&card->lock, flags); ++ list_add_tail(&reply->list, &card->cmd_waiter_list); ++ spin_unlock_irqrestore(&card->lock, flags); ++ + timeout = jiffies + event_timeout; + + QETH_CARD_TEXT(card, 6, "noirqpnd"); +@@ -2128,9 +2132,8 @@ int qeth_send_control_data(struct qeth_card *card, int len, + + /* we have only one long running ipassist, since we can ensure + process context of this command we can sleep */ +- cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE); +- if ((cmd->hdr.command == IPA_CMD_SETIP) && +- (cmd->hdr.prot_version == QETH_PROT_IPV4)) { ++ if (cmd && cmd->hdr.command == IPA_CMD_SETIP && ++ cmd->hdr.prot_version == QETH_PROT_IPV4) { + if (!wait_event_timeout(reply->wait_q, + atomic_read(&reply->received), event_timeout)) + goto time_err; +@@ -2894,7 +2897,7 @@ static void qeth_fill_ipacmd_header(struct qeth_card *card, + memset(cmd, 0, sizeof(struct qeth_ipa_cmd)); + cmd->hdr.command = command; + cmd->hdr.initiator = IPA_CMD_INITIATOR_HOST; +- cmd->hdr.seqno = card->seqno.ipa; ++ /* cmd->hdr.seqno is set by qeth_send_control_data() */ + cmd->hdr.adapter_type = qeth_get_ipa_adp_type(card->info.link_type); + cmd->hdr.rel_adapter_no = (__u8) card->info.portno; + if (card->options.layer2) +@@ -3859,10 +3862,12 @@ EXPORT_SYMBOL_GPL(qeth_get_elements_for_frags); + int qeth_get_elements_no(struct qeth_card *card, + struct sk_buff *skb, int extra_elems, int data_offset) + { +- int elements = qeth_get_elements_for_range( +- (addr_t)skb->data + data_offset, +- (addr_t)skb->data + skb_headlen(skb)) + +- qeth_get_elements_for_frags(skb); ++ addr_t end = (addr_t)skb->data + skb_headlen(skb); ++ int elements = qeth_get_elements_for_frags(skb); ++ addr_t start = (addr_t)skb->data + data_offset; ++ ++ if (start != end) ++ elements += qeth_get_elements_for_range(start, end); + + if ((elements + extra_elems) > QETH_MAX_BUFFER_ELEMENTS(card)) { + QETH_DBF_MESSAGE(2, "Invalid size of IP packet " +diff --git a/drivers/s390/net/qeth_l3.h b/drivers/s390/net/qeth_l3.h +index e5833837b799..8727b9517de8 100644 +--- a/drivers/s390/net/qeth_l3.h ++++ b/drivers/s390/net/qeth_l3.h +@@ -40,8 +40,40 @@ struct qeth_ipaddr { + unsigned int pfxlen; + } a6; + } u; +- + }; ++ ++static inline bool qeth_l3_addr_match_ip(struct qeth_ipaddr *a1, ++ struct qeth_ipaddr *a2) ++{ ++ if (a1->proto != a2->proto) ++ return false; ++ if (a1->proto == QETH_PROT_IPV6) ++ return ipv6_addr_equal(&a1->u.a6.addr, &a2->u.a6.addr); ++ return a1->u.a4.addr == a2->u.a4.addr; ++} ++ ++static inline bool qeth_l3_addr_match_all(struct qeth_ipaddr *a1, ++ struct qeth_ipaddr *a2) ++{ ++ /* Assumes that the pair was obtained via qeth_l3_addr_find_by_ip(), ++ * so 'proto' and 'addr' match for sure. ++ * ++ * For ucast: ++ * - 'mac' is always 0. ++ * - 'mask'/'pfxlen' for RXIP/VIPA is always 0. For NORMAL, matching ++ * values are required to avoid mixups in takeover eligibility. ++ * ++ * For mcast, ++ * - 'mac' is mapped from the IP, and thus always matches. ++ * - 'mask'/'pfxlen' is always 0. ++ */ ++ if (a1->type != a2->type) ++ return false; ++ if (a1->proto == QETH_PROT_IPV6) ++ return a1->u.a6.pfxlen == a2->u.a6.pfxlen; ++ return a1->u.a4.mask == a2->u.a4.mask; ++} ++ + static inline u64 qeth_l3_ipaddr_hash(struct qeth_ipaddr *addr) + { + u64 ret = 0; +diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c +index 36dee176f8e2..96576e729222 100644 +--- a/drivers/s390/net/qeth_l3_main.c ++++ b/drivers/s390/net/qeth_l3_main.c +@@ -149,6 +149,24 @@ int qeth_l3_string_to_ipaddr(const char *buf, enum qeth_prot_versions proto, + return -EINVAL; + } + ++static struct qeth_ipaddr *qeth_l3_find_addr_by_ip(struct qeth_card *card, ++ struct qeth_ipaddr *query) ++{ ++ u64 key = qeth_l3_ipaddr_hash(query); ++ struct qeth_ipaddr *addr; ++ ++ if (query->is_multicast) { ++ hash_for_each_possible(card->ip_mc_htable, addr, hnode, key) ++ if (qeth_l3_addr_match_ip(addr, query)) ++ return addr; ++ } else { ++ hash_for_each_possible(card->ip_htable, addr, hnode, key) ++ if (qeth_l3_addr_match_ip(addr, query)) ++ return addr; ++ } ++ return NULL; ++} ++ + static void qeth_l3_convert_addr_to_bits(u8 *addr, u8 *bits, int len) + { + int i, j; +@@ -202,34 +220,6 @@ static bool qeth_l3_is_addr_covered_by_ipato(struct qeth_card *card, + return rc; + } + +-inline int +-qeth_l3_ipaddrs_is_equal(struct qeth_ipaddr *addr1, struct qeth_ipaddr *addr2) +-{ +- return addr1->proto == addr2->proto && +- !memcmp(&addr1->u, &addr2->u, sizeof(addr1->u)) && +- !memcmp(&addr1->mac, &addr2->mac, sizeof(addr1->mac)); +-} +- +-static struct qeth_ipaddr * +-qeth_l3_ip_from_hash(struct qeth_card *card, struct qeth_ipaddr *tmp_addr) +-{ +- struct qeth_ipaddr *addr; +- +- if (tmp_addr->is_multicast) { +- hash_for_each_possible(card->ip_mc_htable, addr, +- hnode, qeth_l3_ipaddr_hash(tmp_addr)) +- if (qeth_l3_ipaddrs_is_equal(tmp_addr, addr)) +- return addr; +- } else { +- hash_for_each_possible(card->ip_htable, addr, +- hnode, qeth_l3_ipaddr_hash(tmp_addr)) +- if (qeth_l3_ipaddrs_is_equal(tmp_addr, addr)) +- return addr; +- } +- +- return NULL; +-} +- + int qeth_l3_delete_ip(struct qeth_card *card, struct qeth_ipaddr *tmp_addr) + { + int rc = 0; +@@ -244,23 +234,18 @@ int qeth_l3_delete_ip(struct qeth_card *card, struct qeth_ipaddr *tmp_addr) + QETH_CARD_HEX(card, 4, ((char *)&tmp_addr->u.a6.addr) + 8, 8); + } + +- addr = qeth_l3_ip_from_hash(card, tmp_addr); +- if (!addr) ++ addr = qeth_l3_find_addr_by_ip(card, tmp_addr); ++ if (!addr || !qeth_l3_addr_match_all(addr, tmp_addr)) + return -ENOENT; + + addr->ref_counter--; +- if (addr->ref_counter > 0 && (addr->type == QETH_IP_TYPE_NORMAL || +- addr->type == QETH_IP_TYPE_RXIP)) ++ if (addr->type == QETH_IP_TYPE_NORMAL && addr->ref_counter > 0) + return rc; + if (addr->in_progress) + return -EINPROGRESS; + +- if (!qeth_card_hw_is_reachable(card)) { +- addr->disp_flag = QETH_DISP_ADDR_DELETE; +- return 0; +- } +- +- rc = qeth_l3_deregister_addr_entry(card, addr); ++ if (qeth_card_hw_is_reachable(card)) ++ rc = qeth_l3_deregister_addr_entry(card, addr); + + hash_del(&addr->hnode); + kfree(addr); +@@ -272,6 +257,7 @@ int qeth_l3_add_ip(struct qeth_card *card, struct qeth_ipaddr *tmp_addr) + { + int rc = 0; + struct qeth_ipaddr *addr; ++ char buf[40]; + + QETH_CARD_TEXT(card, 4, "addip"); + +@@ -282,8 +268,20 @@ int qeth_l3_add_ip(struct qeth_card *card, struct qeth_ipaddr *tmp_addr) + QETH_CARD_HEX(card, 4, ((char *)&tmp_addr->u.a6.addr) + 8, 8); + } + +- addr = qeth_l3_ip_from_hash(card, tmp_addr); +- if (!addr) { ++ addr = qeth_l3_find_addr_by_ip(card, tmp_addr); ++ if (addr) { ++ if (tmp_addr->type != QETH_IP_TYPE_NORMAL) ++ return -EADDRINUSE; ++ if (qeth_l3_addr_match_all(addr, tmp_addr)) { ++ addr->ref_counter++; ++ return 0; ++ } ++ qeth_l3_ipaddr_to_string(tmp_addr->proto, (u8 *)&tmp_addr->u, ++ buf); ++ dev_warn(&card->gdev->dev, ++ "Registering IP address %s failed\n", buf); ++ return -EADDRINUSE; ++ } else { + addr = qeth_l3_get_addr_buffer(tmp_addr->proto); + if (!addr) + return -ENOMEM; +@@ -323,19 +321,15 @@ int qeth_l3_add_ip(struct qeth_card *card, struct qeth_ipaddr *tmp_addr) + (rc == IPA_RC_LAN_OFFLINE)) { + addr->disp_flag = QETH_DISP_ADDR_DO_NOTHING; + if (addr->ref_counter < 1) { +- qeth_l3_delete_ip(card, addr); ++ qeth_l3_deregister_addr_entry(card, addr); ++ hash_del(&addr->hnode); + kfree(addr); + } + } else { + hash_del(&addr->hnode); + kfree(addr); + } +- } else { +- if (addr->type == QETH_IP_TYPE_NORMAL || +- addr->type == QETH_IP_TYPE_RXIP) +- addr->ref_counter++; + } +- + return rc; + } + +@@ -403,11 +397,7 @@ static void qeth_l3_recover_ip(struct qeth_card *card) + spin_lock_bh(&card->ip_lock); + + hash_for_each_safe(card->ip_htable, i, tmp, addr, hnode) { +- if (addr->disp_flag == QETH_DISP_ADDR_DELETE) { +- qeth_l3_deregister_addr_entry(card, addr); +- hash_del(&addr->hnode); +- kfree(addr); +- } else if (addr->disp_flag == QETH_DISP_ADDR_ADD) { ++ if (addr->disp_flag == QETH_DISP_ADDR_ADD) { + if (addr->proto == QETH_PROT_IPV4) { + addr->in_progress = 1; + spin_unlock_bh(&card->ip_lock); +@@ -723,12 +713,7 @@ int qeth_l3_add_vipa(struct qeth_card *card, enum qeth_prot_versions proto, + return -ENOMEM; + + spin_lock_bh(&card->ip_lock); +- +- if (qeth_l3_ip_from_hash(card, ipaddr)) +- rc = -EEXIST; +- else +- qeth_l3_add_ip(card, ipaddr); +- ++ rc = qeth_l3_add_ip(card, ipaddr); + spin_unlock_bh(&card->ip_lock); + + kfree(ipaddr); +@@ -791,12 +776,7 @@ int qeth_l3_add_rxip(struct qeth_card *card, enum qeth_prot_versions proto, + return -ENOMEM; + + spin_lock_bh(&card->ip_lock); +- +- if (qeth_l3_ip_from_hash(card, ipaddr)) +- rc = -EEXIST; +- else +- qeth_l3_add_ip(card, ipaddr); +- ++ rc = qeth_l3_add_ip(card, ipaddr); + spin_unlock_bh(&card->ip_lock); + + kfree(ipaddr); +@@ -1404,8 +1384,9 @@ qeth_l3_add_mc_to_hash(struct qeth_card *card, struct in_device *in4_dev) + memcpy(tmp->mac, buf, sizeof(tmp->mac)); + tmp->is_multicast = 1; + +- ipm = qeth_l3_ip_from_hash(card, tmp); ++ ipm = qeth_l3_find_addr_by_ip(card, tmp); + if (ipm) { ++ /* for mcast, by-IP match means full match */ + ipm->disp_flag = QETH_DISP_ADDR_DO_NOTHING; + } else { + ipm = qeth_l3_get_addr_buffer(QETH_PROT_IPV4); +@@ -1488,8 +1469,9 @@ qeth_l3_add_mc6_to_hash(struct qeth_card *card, struct inet6_dev *in6_dev) + sizeof(struct in6_addr)); + tmp->is_multicast = 1; + +- ipm = qeth_l3_ip_from_hash(card, tmp); ++ ipm = qeth_l3_find_addr_by_ip(card, tmp); + if (ipm) { ++ /* for mcast, by-IP match means full match */ + ipm->disp_flag = QETH_DISP_ADDR_DO_NOTHING; + continue; + } +@@ -2633,11 +2615,12 @@ static void qeth_tso_fill_header(struct qeth_card *card, + static int qeth_l3_get_elements_no_tso(struct qeth_card *card, + struct sk_buff *skb, int extra_elems) + { +- addr_t tcpdptr = (addr_t)tcp_hdr(skb) + tcp_hdrlen(skb); +- int elements = qeth_get_elements_for_range( +- tcpdptr, +- (addr_t)skb->data + skb_headlen(skb)) + +- qeth_get_elements_for_frags(skb); ++ addr_t start = (addr_t)tcp_hdr(skb) + tcp_hdrlen(skb); ++ addr_t end = (addr_t)skb->data + skb_headlen(skb); ++ int elements = qeth_get_elements_for_frags(skb); ++ ++ if (start != end) ++ elements += qeth_get_elements_for_range(start, end); + + if ((elements + extra_elems) > QETH_MAX_BUFFER_ELEMENTS(card)) { + QETH_DBF_MESSAGE(2, +diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c +index 92155cce926d..fb4e6a7ee521 100644 +--- a/drivers/vfio/vfio_iommu_type1.c ++++ b/drivers/vfio/vfio_iommu_type1.c +@@ -338,11 +338,12 @@ static int vaddr_get_pfn(struct mm_struct *mm, unsigned long vaddr, + { + struct page *page[1]; + struct vm_area_struct *vma; ++ struct vm_area_struct *vmas[1]; + int ret; + + if (mm == current->mm) { +- ret = get_user_pages_fast(vaddr, 1, !!(prot & IOMMU_WRITE), +- page); ++ ret = get_user_pages_longterm(vaddr, 1, !!(prot & IOMMU_WRITE), ++ page, vmas); + } else { + unsigned int flags = 0; + +@@ -351,7 +352,18 @@ static int vaddr_get_pfn(struct mm_struct *mm, unsigned long vaddr, + + down_read(&mm->mmap_sem); + ret = get_user_pages_remote(NULL, mm, vaddr, 1, flags, page, +- NULL, NULL); ++ vmas, NULL); ++ /* ++ * The lifetime of a vaddr_get_pfn() page pin is ++ * userspace-controlled. In the fs-dax case this could ++ * lead to indefinite stalls in filesystem operations. ++ * Disallow attempts to pin fs-dax pages via this ++ * interface. ++ */ ++ if (ret > 0 && vma_is_fsdax(vmas[0])) { ++ ret = -EOPNOTSUPP; ++ put_page(page[0]); ++ } + up_read(&mm->mmap_sem); + } + +diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c +index 883881b16c86..4447e0fe9b55 100644 +--- a/fs/btrfs/sysfs.c ++++ b/fs/btrfs/sysfs.c +@@ -422,7 +422,7 @@ static ssize_t btrfs_nodesize_show(struct kobject *kobj, + { + struct btrfs_fs_info *fs_info = to_fs_info(kobj); + +- return snprintf(buf, PAGE_SIZE, "%u\n", fs_info->super_copy->nodesize); ++ return snprintf(buf, PAGE_SIZE, "%u\n", fs_info->nodesize); + } + + BTRFS_ATTR(nodesize, btrfs_nodesize_show); +@@ -432,8 +432,7 @@ static ssize_t btrfs_sectorsize_show(struct kobject *kobj, + { + struct btrfs_fs_info *fs_info = to_fs_info(kobj); + +- return snprintf(buf, PAGE_SIZE, "%u\n", +- fs_info->super_copy->sectorsize); ++ return snprintf(buf, PAGE_SIZE, "%u\n", fs_info->sectorsize); + } + + BTRFS_ATTR(sectorsize, btrfs_sectorsize_show); +@@ -443,8 +442,7 @@ static ssize_t btrfs_clone_alignment_show(struct kobject *kobj, + { + struct btrfs_fs_info *fs_info = to_fs_info(kobj); + +- return snprintf(buf, PAGE_SIZE, "%u\n", +- fs_info->super_copy->sectorsize); ++ return snprintf(buf, PAGE_SIZE, "%u\n", fs_info->sectorsize); + } + + BTRFS_ATTR(clone_alignment, btrfs_clone_alignment_show); +diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c +index f615d59b0489..46bda13e5727 100644 +--- a/fs/btrfs/transaction.c ++++ b/fs/btrfs/transaction.c +@@ -1722,19 +1722,23 @@ static void update_super_roots(struct btrfs_fs_info *fs_info) + + super = fs_info->super_copy; + ++ /* update latest btrfs_super_block::chunk_root refs */ + root_item = &fs_info->chunk_root->root_item; +- super->chunk_root = root_item->bytenr; +- super->chunk_root_generation = root_item->generation; +- super->chunk_root_level = root_item->level; ++ btrfs_set_super_chunk_root(super, root_item->bytenr); ++ btrfs_set_super_chunk_root_generation(super, root_item->generation); ++ btrfs_set_super_chunk_root_level(super, root_item->level); + ++ /* update latest btrfs_super_block::root refs */ + root_item = &fs_info->tree_root->root_item; +- super->root = root_item->bytenr; +- super->generation = root_item->generation; +- super->root_level = root_item->level; ++ btrfs_set_super_root(super, root_item->bytenr); ++ btrfs_set_super_generation(super, root_item->generation); ++ btrfs_set_super_root_level(super, root_item->level); ++ + if (btrfs_test_opt(fs_info, SPACE_CACHE)) +- super->cache_generation = root_item->generation; ++ btrfs_set_super_cache_generation(super, root_item->generation); + if (test_bit(BTRFS_FS_UPDATE_UUID_TREE_GEN, &fs_info->flags)) +- super->uuid_tree_generation = root_item->generation; ++ btrfs_set_super_uuid_tree_generation(super, ++ root_item->generation); + } + + int btrfs_transaction_in_commit(struct btrfs_fs_info *info) +diff --git a/fs/direct-io.c b/fs/direct-io.c +index b53e66d9abd7..625a84aa6484 100644 +--- a/fs/direct-io.c ++++ b/fs/direct-io.c +@@ -1252,8 +1252,7 @@ do_blockdev_direct_IO(struct kiocb *iocb, struct inode *inode, + */ + if (dio->is_async && iov_iter_rw(iter) == WRITE) { + retval = 0; +- if ((iocb->ki_filp->f_flags & O_DSYNC) || +- IS_SYNC(iocb->ki_filp->f_mapping->host)) ++ if (iocb->ki_flags & IOCB_DSYNC) + retval = dio_set_defer_completion(dio); + else if (!dio->inode->i_sb->s_dio_done_wq) { + /* +diff --git a/include/linux/fs.h b/include/linux/fs.h +index 440281f8564d..d54f41a63dbf 100644 +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -3185,7 +3185,7 @@ static inline bool vma_is_fsdax(struct vm_area_struct *vma) + if (!vma_is_dax(vma)) + return false; + inode = file_inode(vma->vm_file); +- if (inode->i_mode == S_IFCHR) ++ if (S_ISCHR(inode->i_mode)) + return false; /* device-dax */ + return true; + } +diff --git a/include/linux/nospec.h b/include/linux/nospec.h +index fbc98e2c8228..132e3f5a2e0d 100644 +--- a/include/linux/nospec.h ++++ b/include/linux/nospec.h +@@ -72,7 +72,6 @@ static inline unsigned long array_index_mask_nospec(unsigned long index, + BUILD_BUG_ON(sizeof(_i) > sizeof(long)); \ + BUILD_BUG_ON(sizeof(_s) > sizeof(long)); \ + \ +- _i &= _mask; \ +- _i; \ ++ (typeof(_i)) (_i & _mask); \ + }) + #endif /* _LINUX_NOSPEC_H */ +diff --git a/include/net/udplite.h b/include/net/udplite.h +index 81bdbf97319b..9185e45b997f 100644 +--- a/include/net/udplite.h ++++ b/include/net/udplite.h +@@ -64,6 +64,7 @@ static inline int udplite_checksum_init(struct sk_buff *skb, struct udphdr *uh) + UDP_SKB_CB(skb)->cscov = cscov; + if (skb->ip_summed == CHECKSUM_COMPLETE) + skb->ip_summed = CHECKSUM_NONE; ++ skb->csum_valid = 0; + } + + return 0; +diff --git a/kernel/time/timer.c b/kernel/time/timer.c +index db5e6daadd94..9fe525f410bf 100644 +--- a/kernel/time/timer.c ++++ b/kernel/time/timer.c +@@ -1834,6 +1834,12 @@ int timers_dead_cpu(unsigned int cpu) + raw_spin_lock_irq(&new_base->lock); + raw_spin_lock_nested(&old_base->lock, SINGLE_DEPTH_NESTING); + ++ /* ++ * The current CPUs base clock might be stale. Update it ++ * before moving the timers over. ++ */ ++ forward_timer_base(new_base); ++ + BUG_ON(old_base->running_timer); + + for (i = 0; i < WHEEL_SIZE; i++) +diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c +index 5d5d413a6cf8..a097a8613a02 100644 +--- a/net/bridge/br_sysfs_if.c ++++ b/net/bridge/br_sysfs_if.c +@@ -235,6 +235,9 @@ static ssize_t brport_show(struct kobject *kobj, + struct brport_attribute *brport_attr = to_brport_attr(attr); + struct net_bridge_port *p = to_brport(kobj); + ++ if (!brport_attr->show) ++ return -EINVAL; ++ + return brport_attr->show(p, buf); + } + +diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c +index 233a30040c91..9b8a53568b0f 100644 +--- a/net/bridge/br_vlan.c ++++ b/net/bridge/br_vlan.c +@@ -157,6 +157,8 @@ static struct net_bridge_vlan *br_vlan_get_master(struct net_bridge *br, u16 vid + masterv = br_vlan_find(vg, vid); + if (WARN_ON(!masterv)) + return NULL; ++ refcount_set(&masterv->refcnt, 1); ++ return masterv; + } + refcount_inc(&masterv->refcnt); + +diff --git a/net/core/dev.c b/net/core/dev.c +index d33bbed640b1..c75ef9d8105a 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -2343,8 +2343,11 @@ EXPORT_SYMBOL(netdev_set_num_tc); + */ + int netif_set_real_num_tx_queues(struct net_device *dev, unsigned int txq) + { ++ bool disabling; + int rc; + ++ disabling = txq < dev->real_num_tx_queues; ++ + if (txq < 1 || txq > dev->num_tx_queues) + return -EINVAL; + +@@ -2360,15 +2363,19 @@ int netif_set_real_num_tx_queues(struct net_device *dev, unsigned int txq) + if (dev->num_tc) + netif_setup_tc(dev, txq); + +- if (txq < dev->real_num_tx_queues) { ++ dev->real_num_tx_queues = txq; ++ ++ if (disabling) { ++ synchronize_net(); + qdisc_reset_all_tx_gt(dev, txq); + #ifdef CONFIG_XPS + netif_reset_xps_queues_gt(dev, txq); + #endif + } ++ } else { ++ dev->real_num_tx_queues = txq; + } + +- dev->real_num_tx_queues = txq; + return 0; + } + EXPORT_SYMBOL(netif_set_real_num_tx_queues); +diff --git a/net/core/gen_estimator.c b/net/core/gen_estimator.c +index 00ecec4891f3..7f980bd7426e 100644 +--- a/net/core/gen_estimator.c ++++ b/net/core/gen_estimator.c +@@ -66,6 +66,7 @@ struct net_rate_estimator { + static void est_fetch_counters(struct net_rate_estimator *e, + struct gnet_stats_basic_packed *b) + { ++ memset(b, 0, sizeof(*b)); + if (e->stats_lock) + spin_lock(e->stats_lock); + +diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c +index aff3751df950..1ee6c0d8dde4 100644 +--- a/net/ipv4/fib_semantics.c ++++ b/net/ipv4/fib_semantics.c +@@ -654,6 +654,11 @@ int fib_nh_match(struct fib_config *cfg, struct fib_info *fi, + fi->fib_nh, cfg, extack)) + return 1; + } ++#ifdef CONFIG_IP_ROUTE_CLASSID ++ if (cfg->fc_flow && ++ cfg->fc_flow != fi->fib_nh->nh_tclassid) ++ return 1; ++#endif + if ((!cfg->fc_oif || cfg->fc_oif == fi->fib_nh->nh_oif) && + (!cfg->fc_gw || cfg->fc_gw == fi->fib_nh->nh_gw)) + return 0; +diff --git a/net/ipv4/route.c b/net/ipv4/route.c +index 0ba88efca7ad..9ff06c5051ae 100644 +--- a/net/ipv4/route.c ++++ b/net/ipv4/route.c +@@ -128,10 +128,13 @@ static int ip_rt_redirect_silence __read_mostly = ((HZ / 50) << (9 + 1)); + static int ip_rt_error_cost __read_mostly = HZ; + static int ip_rt_error_burst __read_mostly = 5 * HZ; + static int ip_rt_mtu_expires __read_mostly = 10 * 60 * HZ; +-static int ip_rt_min_pmtu __read_mostly = 512 + 20 + 20; ++static u32 ip_rt_min_pmtu __read_mostly = 512 + 20 + 20; + static int ip_rt_min_advmss __read_mostly = 256; + + static int ip_rt_gc_timeout __read_mostly = RT_GC_TIMEOUT; ++ ++static int ip_min_valid_pmtu __read_mostly = IPV4_MIN_MTU; ++ + /* + * Interface to generic destination cache. + */ +@@ -1829,6 +1832,8 @@ int fib_multipath_hash(const struct fib_info *fi, const struct flowi4 *fl4, + return skb_get_hash_raw(skb) >> 1; + memset(&hash_keys, 0, sizeof(hash_keys)); + skb_flow_dissect_flow_keys(skb, &keys, flag); ++ ++ hash_keys.control.addr_type = FLOW_DISSECTOR_KEY_IPV4_ADDRS; + hash_keys.addrs.v4addrs.src = keys.addrs.v4addrs.src; + hash_keys.addrs.v4addrs.dst = keys.addrs.v4addrs.dst; + hash_keys.ports.src = keys.ports.src; +@@ -2934,7 +2939,8 @@ static struct ctl_table ipv4_route_table[] = { + .data = &ip_rt_min_pmtu, + .maxlen = sizeof(int), + .mode = 0644, +- .proc_handler = proc_dointvec, ++ .proc_handler = proc_dointvec_minmax, ++ .extra1 = &ip_min_valid_pmtu, + }, + { + .procname = "min_adv_mss", +diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c +index d9d215e27b8a..14474acea0bb 100644 +--- a/net/ipv4/tcp_input.c ++++ b/net/ipv4/tcp_input.c +@@ -2013,11 +2013,6 @@ void tcp_enter_loss(struct sock *sk) + /* F-RTO RFC5682 sec 3.1 step 1: retransmit SND.UNA if no previous + * loss recovery is underway except recurring timeout(s) on + * the same SND.UNA (sec 3.2). Disable F-RTO on path MTU probing +- * +- * In theory F-RTO can be used repeatedly during loss recovery. +- * In practice this interacts badly with broken middle-boxes that +- * falsely raise the receive window, which results in repeated +- * timeouts and stop-and-go behavior. + */ + tp->frto = sysctl_tcp_frto && + (new_recovery || icsk->icsk_retransmits) && +@@ -2699,18 +2694,14 @@ static void tcp_process_loss(struct sock *sk, int flag, bool is_dupack, + tcp_try_undo_loss(sk, false)) + return; + +- /* The ACK (s)acks some never-retransmitted data meaning not all +- * the data packets before the timeout were lost. Therefore we +- * undo the congestion window and state. This is essentially +- * the operation in F-RTO (RFC5682 section 3.1 step 3.b). Since +- * a retransmitted skb is permantly marked, we can apply such an +- * operation even if F-RTO was not used. +- */ +- if ((flag & FLAG_ORIG_SACK_ACKED) && +- tcp_try_undo_loss(sk, tp->undo_marker)) +- return; +- + if (tp->frto) { /* F-RTO RFC5682 sec 3.1 (sack enhanced version). */ ++ /* Step 3.b. A timeout is spurious if not all data are ++ * lost, i.e., never-retransmitted data are (s)acked. ++ */ ++ if ((flag & FLAG_ORIG_SACK_ACKED) && ++ tcp_try_undo_loss(sk, true)) ++ return; ++ + if (after(tp->snd_nxt, tp->high_seq)) { + if (flag & FLAG_DATA_SACKED || is_dupack) + tp->frto = 0; /* Step 3.a. loss was real */ +@@ -4020,6 +4011,7 @@ void tcp_reset(struct sock *sk) + /* This barrier is coupled with smp_rmb() in tcp_poll() */ + smp_wmb(); + ++ tcp_write_queue_purge(sk); + tcp_done(sk); + + if (!sock_flag(sk, SOCK_DEAD)) +diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c +index cd3d60bb7cc8..83d11cd2eb65 100644 +--- a/net/ipv4/tcp_output.c ++++ b/net/ipv4/tcp_output.c +@@ -1681,7 +1681,7 @@ u32 tcp_tso_autosize(const struct sock *sk, unsigned int mss_now, + */ + segs = max_t(u32, bytes / mss_now, min_tso_segs); + +- return min_t(u32, segs, sk->sk_gso_max_segs); ++ return segs; + } + EXPORT_SYMBOL(tcp_tso_autosize); + +@@ -1693,8 +1693,10 @@ static u32 tcp_tso_segs(struct sock *sk, unsigned int mss_now) + const struct tcp_congestion_ops *ca_ops = inet_csk(sk)->icsk_ca_ops; + u32 tso_segs = ca_ops->tso_segs_goal ? ca_ops->tso_segs_goal(sk) : 0; + +- return tso_segs ? : +- tcp_tso_autosize(sk, mss_now, sysctl_tcp_min_tso_segs); ++ if (!tso_segs) ++ tso_segs = tcp_tso_autosize(sk, mss_now, ++ sysctl_tcp_min_tso_segs); ++ return min_t(u32, tso_segs, sk->sk_gso_max_segs); + } + + /* Returns the portion of skb which can be sent right away */ +@@ -1973,6 +1975,24 @@ static inline void tcp_mtu_check_reprobe(struct sock *sk) + } + } + ++static bool tcp_can_coalesce_send_queue_head(struct sock *sk, int len) ++{ ++ struct sk_buff *skb, *next; ++ ++ skb = tcp_send_head(sk); ++ tcp_for_write_queue_from_safe(skb, next, sk) { ++ if (len <= skb->len) ++ break; ++ ++ if (unlikely(TCP_SKB_CB(skb)->eor)) ++ return false; ++ ++ len -= skb->len; ++ } ++ ++ return true; ++} ++ + /* Create a new MTU probe if we are ready. + * MTU probe is regularly attempting to increase the path MTU by + * deliberately sending larger packets. This discovers routing +@@ -2045,6 +2065,9 @@ static int tcp_mtu_probe(struct sock *sk) + return 0; + } + ++ if (!tcp_can_coalesce_send_queue_head(sk, probe_size)) ++ return -1; ++ + /* We're allowed to probe. Build it now. */ + nskb = sk_stream_alloc_skb(sk, probe_size, GFP_ATOMIC, false); + if (!nskb) +@@ -2080,6 +2103,10 @@ static int tcp_mtu_probe(struct sock *sk) + /* We've eaten all the data from this skb. + * Throw it away. */ + TCP_SKB_CB(nskb)->tcp_flags |= TCP_SKB_CB(skb)->tcp_flags; ++ /* If this is the last SKB we copy and eor is set ++ * we need to propagate it to the new skb. ++ */ ++ TCP_SKB_CB(nskb)->eor = TCP_SKB_CB(skb)->eor; + tcp_unlink_write_queue(skb, sk); + sk_wmem_free_skb(sk, skb); + } else { +diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c +index ebfbccae62fd..c79fa6f6b758 100644 +--- a/net/ipv4/udp.c ++++ b/net/ipv4/udp.c +@@ -2032,6 +2032,11 @@ static inline int udp4_csum_init(struct sk_buff *skb, struct udphdr *uh, + err = udplite_checksum_init(skb, uh); + if (err) + return err; ++ ++ if (UDP_SKB_CB(skb)->partial_cov) { ++ skb->csum = inet_compute_pseudo(skb, proto); ++ return 0; ++ } + } + + /* Note, we are only interested in != 0 or == 0, thus the +diff --git a/net/ipv6/ip6_checksum.c b/net/ipv6/ip6_checksum.c +index ec43d18b5ff9..547515e8450a 100644 +--- a/net/ipv6/ip6_checksum.c ++++ b/net/ipv6/ip6_checksum.c +@@ -73,6 +73,11 @@ int udp6_csum_init(struct sk_buff *skb, struct udphdr *uh, int proto) + err = udplite_checksum_init(skb, uh); + if (err) + return err; ++ ++ if (UDP_SKB_CB(skb)->partial_cov) { ++ skb->csum = ip6_compute_pseudo(skb, proto); ++ return 0; ++ } + } + + /* To support RFC 6936 (allow zero checksum in UDP/IPV6 for tunnels) +diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c +index e79854cc5790..cac815cc8600 100644 +--- a/net/ipv6/sit.c ++++ b/net/ipv6/sit.c +@@ -176,7 +176,7 @@ static void ipip6_tunnel_clone_6rd(struct net_device *dev, struct sit_net *sitn) + #ifdef CONFIG_IPV6_SIT_6RD + struct ip_tunnel *t = netdev_priv(dev); + +- if (t->dev == sitn->fb_tunnel_dev) { ++ if (dev == sitn->fb_tunnel_dev) { + ipv6_addr_set(&t->ip6rd.prefix, htonl(0x20020000), 0, 0, 0); + t->ip6rd.relay_prefix = 0; + t->ip6rd.prefixlen = 16; +diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c +index 533fd0503ba0..9219bc134109 100644 +--- a/net/netlink/af_netlink.c ++++ b/net/netlink/af_netlink.c +@@ -2276,7 +2276,7 @@ int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb, + if (cb->start) { + ret = cb->start(cb); + if (ret) +- goto error_unlock; ++ goto error_put; + } + + nlk->cb_running = true; +@@ -2296,6 +2296,8 @@ int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb, + */ + return -EINTR; + ++error_put: ++ module_put(control->module); + error_unlock: + sock_put(sk); + mutex_unlock(nlk->cb_mutex); +diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c +index d444daf1ac04..6f02499ef007 100644 +--- a/net/netlink/genetlink.c ++++ b/net/netlink/genetlink.c +@@ -1081,6 +1081,7 @@ static int genlmsg_mcast(struct sk_buff *skb, u32 portid, unsigned long group, + { + struct sk_buff *tmp; + struct net *net, *prev = NULL; ++ bool delivered = false; + int err; + + for_each_net_rcu(net) { +@@ -1092,14 +1093,21 @@ static int genlmsg_mcast(struct sk_buff *skb, u32 portid, unsigned long group, + } + err = nlmsg_multicast(prev->genl_sock, tmp, + portid, group, flags); +- if (err) ++ if (!err) ++ delivered = true; ++ else if (err != -ESRCH) + goto error; + } + + prev = net; + } + +- return nlmsg_multicast(prev->genl_sock, skb, portid, group, flags); ++ err = nlmsg_multicast(prev->genl_sock, skb, portid, group, flags); ++ if (!err) ++ delivered = true; ++ else if (err != -ESRCH) ++ goto error; ++ return delivered ? 0 : -ESRCH; + error: + kfree_skb(skb); + return err; +diff --git a/net/rxrpc/output.c b/net/rxrpc/output.c +index 71e6f713fbe7..5b67cb5d47f0 100644 +--- a/net/rxrpc/output.c ++++ b/net/rxrpc/output.c +@@ -395,7 +395,7 @@ int rxrpc_send_data_packet(struct rxrpc_call *call, struct sk_buff *skb, + (char *)&opt, sizeof(opt)); + if (ret == 0) { + ret = kernel_sendmsg(conn->params.local->socket, &msg, +- iov, 1, iov[0].iov_len); ++ iov, 2, len); + + opt = IPV6_PMTUDISC_DO; + kernel_setsockopt(conn->params.local->socket, +diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c +index 934c239cf98d..c2fab4bcb8be 100644 +--- a/net/sched/cls_api.c ++++ b/net/sched/cls_api.c +@@ -871,13 +871,18 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb) + if (tca[TCA_CHAIN] && + nla_get_u32(tca[TCA_CHAIN]) != chain->index) + continue; +- if (!tcf_chain_dump(chain, skb, cb, index_start, &index)) ++ if (!tcf_chain_dump(chain, skb, cb, index_start, &index)) { ++ err = -EMSGSIZE; + break; ++ } + } + + cb->args[0] = index; + + out: ++ /* If we did no progress, the error (EMSGSIZE) is real */ ++ if (skb->len == 0 && err) ++ return err; + return skb->len; + } + +diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c +index b58eccb21f03..ba37d8f57e68 100644 +--- a/net/sched/cls_u32.c ++++ b/net/sched/cls_u32.c +@@ -398,10 +398,12 @@ static int u32_init(struct tcf_proto *tp) + static int u32_destroy_key(struct tcf_proto *tp, struct tc_u_knode *n, + bool free_pf) + { ++ struct tc_u_hnode *ht = rtnl_dereference(n->ht_down); ++ + tcf_exts_destroy(&n->exts); + tcf_exts_put_net(&n->exts); +- if (n->ht_down) +- n->ht_down->refcnt--; ++ if (ht && --ht->refcnt == 0) ++ kfree(ht); + #ifdef CONFIG_CLS_U32_PERF + if (free_pf) + free_percpu(n->pf); +@@ -649,16 +651,15 @@ static void u32_destroy(struct tcf_proto *tp) + + hlist_del(&tp_c->hnode); + +- for (ht = rtnl_dereference(tp_c->hlist); +- ht; +- ht = rtnl_dereference(ht->next)) { +- ht->refcnt--; +- u32_clear_hnode(tp, ht); +- } +- + while ((ht = rtnl_dereference(tp_c->hlist)) != NULL) { ++ u32_clear_hnode(tp, ht); + RCU_INIT_POINTER(tp_c->hlist, ht->next); +- kfree_rcu(ht, rcu); ++ ++ /* u32_destroy_key() will later free ht for us, if it's ++ * still referenced by some knode ++ */ ++ if (--ht->refcnt == 0) ++ kfree_rcu(ht, rcu); + } + + kfree(tp_c); +@@ -927,7 +928,8 @@ static int u32_change(struct net *net, struct sk_buff *in_skb, + if (TC_U32_KEY(n->handle) == 0) + return -EINVAL; + +- if (n->flags != flags) ++ if ((n->flags ^ flags) & ++ ~(TCA_CLS_FLAGS_IN_HW | TCA_CLS_FLAGS_NOT_IN_HW)) + return -EINVAL; + + new = u32_init_knode(tp, n); +diff --git a/net/sctp/input.c b/net/sctp/input.c +index 141c9c466ec1..0247cc432e02 100644 +--- a/net/sctp/input.c ++++ b/net/sctp/input.c +@@ -897,15 +897,12 @@ int sctp_hash_transport(struct sctp_transport *t) + rhl_for_each_entry_rcu(transport, tmp, list, node) + if (transport->asoc->ep == t->asoc->ep) { + rcu_read_unlock(); +- err = -EEXIST; +- goto out; ++ return -EEXIST; + } + rcu_read_unlock(); + + err = rhltable_insert_key(&sctp_transport_hashtable, &arg, + &t->node, sctp_hash_params); +- +-out: + if (err) + pr_err_once("insert transport fail, errno %d\n", err); + +diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c +index 3b18085e3b10..f27a9718554c 100644 +--- a/net/sctp/ipv6.c ++++ b/net/sctp/ipv6.c +@@ -326,8 +326,10 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr, + final_p = fl6_update_dst(fl6, rcu_dereference(np->opt), &final); + bdst = ip6_dst_lookup_flow(sk, fl6, final_p); + +- if (!IS_ERR(bdst) && +- ipv6_chk_addr(dev_net(bdst->dev), ++ if (IS_ERR(bdst)) ++ continue; ++ ++ if (ipv6_chk_addr(dev_net(bdst->dev), + &laddr->a.v6.sin6_addr, bdst->dev, 1)) { + if (!IS_ERR_OR_NULL(dst)) + dst_release(dst); +@@ -336,8 +338,10 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr, + } + + bmatchlen = sctp_v6_addr_match_len(daddr, &laddr->a); +- if (matchlen > bmatchlen) ++ if (matchlen > bmatchlen) { ++ dst_release(bdst); + continue; ++ } + + if (!IS_ERR_OR_NULL(dst)) + dst_release(dst); +diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c +index fcd80feb293f..df22a9c352ad 100644 +--- a/net/sctp/protocol.c ++++ b/net/sctp/protocol.c +@@ -514,22 +514,20 @@ static void sctp_v4_get_dst(struct sctp_transport *t, union sctp_addr *saddr, + if (IS_ERR(rt)) + continue; + +- if (!dst) +- dst = &rt->dst; +- + /* Ensure the src address belongs to the output + * interface. + */ + odev = __ip_dev_find(sock_net(sk), laddr->a.v4.sin_addr.s_addr, + false); + if (!odev || odev->ifindex != fl4->flowi4_oif) { +- if (&rt->dst != dst) ++ if (!dst) ++ dst = &rt->dst; ++ else + dst_release(&rt->dst); + continue; + } + +- if (dst != &rt->dst) +- dst_release(dst); ++ dst_release(dst); + dst = &rt->dst; + break; + } +diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c +index 514465b03829..e4a400f88168 100644 +--- a/net/sctp/sm_make_chunk.c ++++ b/net/sctp/sm_make_chunk.c +@@ -1378,9 +1378,14 @@ static struct sctp_chunk *_sctp_make_chunk(const struct sctp_association *asoc, + struct sctp_chunk *retval; + struct sk_buff *skb; + struct sock *sk; ++ int chunklen; ++ ++ chunklen = SCTP_PAD4(sizeof(*chunk_hdr) + paylen); ++ if (chunklen > SCTP_MAX_CHUNK_LEN) ++ goto nodata; + + /* No need to allocate LL here, as this is only a chunk. */ +- skb = alloc_skb(SCTP_PAD4(sizeof(*chunk_hdr) + paylen), gfp); ++ skb = alloc_skb(chunklen, gfp); + if (!skb) + goto nodata; + +diff --git a/sound/core/control.c b/sound/core/control.c +index 56b3e2d49c82..af7e6165e21e 100644 +--- a/sound/core/control.c ++++ b/sound/core/control.c +@@ -888,7 +888,7 @@ static int snd_ctl_elem_read(struct snd_card *card, + + index_offset = snd_ctl_get_ioff(kctl, &control->id); + vd = &kctl->vd[index_offset]; +- if (!(vd->access & SNDRV_CTL_ELEM_ACCESS_READ) && kctl->get == NULL) ++ if (!(vd->access & SNDRV_CTL_ELEM_ACCESS_READ) || kctl->get == NULL) + return -EPERM; + + snd_ctl_build_ioff(&control->id, kctl, index_offset); +diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c +index c71dcacea807..96143df19b21 100644 +--- a/sound/pci/hda/hda_intel.c ++++ b/sound/pci/hda/hda_intel.c +@@ -181,7 +181,7 @@ static const struct kernel_param_ops param_ops_xint = { + }; + #define param_check_xint param_check_int + +-static int power_save = CONFIG_SND_HDA_POWER_SAVE_DEFAULT; ++static int power_save = -1; + module_param(power_save, xint, 0644); + MODULE_PARM_DESC(power_save, "Automatic power-saving timeout " + "(in second, 0 = disable)."); +@@ -2186,6 +2186,24 @@ static int azx_probe(struct pci_dev *pci, + return err; + } + ++#ifdef CONFIG_PM ++/* On some boards setting power_save to a non 0 value leads to clicking / ++ * popping sounds when ever we enter/leave powersaving mode. Ideally we would ++ * figure out how to avoid these sounds, but that is not always feasible. ++ * So we keep a list of devices where we disable powersaving as its known ++ * to causes problems on these devices. ++ */ ++static struct snd_pci_quirk power_save_blacklist[] = { ++ /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */ ++ SND_PCI_QUIRK(0x1849, 0x0c0c, "Asrock B85M-ITX", 0), ++ /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */ ++ SND_PCI_QUIRK(0x1043, 0x8733, "Asus Prime X370-Pro", 0), ++ /* https://bugzilla.kernel.org/show_bug.cgi?id=198611 */ ++ SND_PCI_QUIRK(0x17aa, 0x2227, "Lenovo X1 Carbon 3rd Gen", 0), ++ {} ++}; ++#endif /* CONFIG_PM */ ++ + /* number of codec slots for each chipset: 0 = default slots (i.e. 4) */ + static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] = { + [AZX_DRIVER_NVIDIA] = 8, +@@ -2198,6 +2216,7 @@ static int azx_probe_continue(struct azx *chip) + struct hdac_bus *bus = azx_bus(chip); + struct pci_dev *pci = chip->pci; + int dev = chip->dev_index; ++ int val; + int err; + + hda->probe_continued = 1; +@@ -2278,7 +2297,22 @@ static int azx_probe_continue(struct azx *chip) + + chip->running = 1; + azx_add_card_list(chip); +- snd_hda_set_power_save(&chip->bus, power_save * 1000); ++ ++ val = power_save; ++#ifdef CONFIG_PM ++ if (val == -1) { ++ const struct snd_pci_quirk *q; ++ ++ val = CONFIG_SND_HDA_POWER_SAVE_DEFAULT; ++ q = snd_pci_quirk_lookup(chip->pci, power_save_blacklist); ++ if (q && val) { ++ dev_info(chip->card->dev, "device %04x:%04x is on the power_save blacklist, forcing power_save to 0\n", ++ q->subvendor, q->subdevice); ++ val = 0; ++ } ++ } ++#endif /* CONFIG_PM */ ++ snd_hda_set_power_save(&chip->bus, val * 1000); + if (azx_has_pm_runtime(chip) || hda->use_vga_switcheroo) + pm_runtime_put_autosuspend(&pci->dev); + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index b7acffdf16a4..454476b47b79 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -4852,13 +4852,14 @@ static void alc_fixup_tpt470_dock(struct hda_codec *codec, + + if (action == HDA_FIXUP_ACT_PRE_PROBE) { + spec->parse_flags = HDA_PINCFG_NO_HP_FIXUP; ++ snd_hda_apply_pincfgs(codec, pincfgs); ++ } else if (action == HDA_FIXUP_ACT_INIT) { + /* Enable DOCK device */ + snd_hda_codec_write(codec, 0x17, 0, + AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, 0); + /* Enable DOCK device */ + snd_hda_codec_write(codec, 0x19, 0, + AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, 0); +- snd_hda_apply_pincfgs(codec, pincfgs); + } + } + +diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h +index 8a59d4782a0f..69bf5cf1e91e 100644 +--- a/sound/usb/quirks-table.h ++++ b/sound/usb/quirks-table.h +@@ -3277,4 +3277,51 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"), + } + }, + ++{ ++ /* ++ * Bower's & Wilkins PX headphones only support the 48 kHz sample rate ++ * even though it advertises more. The capture interface doesn't work ++ * even on windows. ++ */ ++ USB_DEVICE(0x19b5, 0x0021), ++ .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { ++ .ifnum = QUIRK_ANY_INTERFACE, ++ .type = QUIRK_COMPOSITE, ++ .data = (const struct snd_usb_audio_quirk[]) { ++ { ++ .ifnum = 0, ++ .type = QUIRK_AUDIO_STANDARD_MIXER, ++ }, ++ /* Capture */ ++ { ++ .ifnum = 1, ++ .type = QUIRK_IGNORE_INTERFACE, ++ }, ++ /* Playback */ ++ { ++ .ifnum = 2, ++ .type = QUIRK_AUDIO_FIXED_ENDPOINT, ++ .data = &(const struct audioformat) { ++ .formats = SNDRV_PCM_FMTBIT_S16_LE, ++ .channels = 2, ++ .iface = 2, ++ .altsetting = 1, ++ .altset_idx = 1, ++ .attributes = UAC_EP_CS_ATTR_FILL_MAX | ++ UAC_EP_CS_ATTR_SAMPLE_RATE, ++ .endpoint = 0x03, ++ .ep_attr = USB_ENDPOINT_XFER_ISOC, ++ .rates = SNDRV_PCM_RATE_48000, ++ .rate_min = 48000, ++ .rate_max = 48000, ++ .nr_rates = 1, ++ .rate_table = (unsigned int[]) { ++ 48000 ++ } ++ } ++ }, ++ } ++ } ++}, ++ + #undef USB_DEVICE_VENDOR_SPEC +diff --git a/sound/x86/intel_hdmi_audio.c b/sound/x86/intel_hdmi_audio.c +index a0951505c7f5..697872d8308e 100644 +--- a/sound/x86/intel_hdmi_audio.c ++++ b/sound/x86/intel_hdmi_audio.c +@@ -1827,6 +1827,8 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev) + ctx->port = port; + ctx->pipe = -1; + ++ spin_lock_init(&ctx->had_spinlock); ++ mutex_init(&ctx->mutex); + INIT_WORK(&ctx->hdmi_audio_wq, had_audio_wq); + + ret = snd_pcm_new(card, INTEL_HAD, port, MAX_PB_STREAMS, +diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c +index 8401774f5aeb..d81af263f50b 100644 +--- a/virt/kvm/kvm_main.c ++++ b/virt/kvm/kvm_main.c +@@ -975,8 +975,7 @@ int __kvm_set_memory_region(struct kvm *kvm, + /* Check for overlaps */ + r = -EEXIST; + kvm_for_each_memslot(slot, __kvm_memslots(kvm, as_id)) { +- if ((slot->id >= KVM_USER_MEM_SLOTS) || +- (slot->id == id)) ++ if (slot->id == id) + continue; + if (!((base_gfn + npages <= slot->base_gfn) || + (base_gfn >= slot->base_gfn + slot->npages))) diff --git a/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0001-x86-asm-offsets-Move-TSS_sp0-and-TSS_sp1-to-asm-offs.patch b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0001-x86-asm-offsets-Move-TSS_sp0-and-TSS_sp1-to-asm-offs.patch index 4a7877fe..b4edc558 100644 --- a/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0001-x86-asm-offsets-Move-TSS_sp0-and-TSS_sp1-to-asm-offs.patch +++ b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0001-x86-asm-offsets-Move-TSS_sp0-and-TSS_sp1-to-asm-offs.patch @@ -1,7 +1,7 @@ From 3b7711fd3adb7d6b812a33da4a4639ddce6522b6 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Fri, 19 Jan 2018 13:46:20 +0100 -Subject: [PATCH 01/31] x86/asm-offsets: Move TSS_sp0 and TSS_sp1 to +Subject: [PATCH 01/34] x86/asm-offsets: Move TSS_sp0 and TSS_sp1 to asm-offsets.c These offsets will be used in 32 bit assembly code as well, @@ -40,5 +40,5 @@ index bf51e51d808d..d2eba73a5f8a 100644 #ifdef CONFIG_CC_STACKPROTECTOR -- -2.13.6 +2.16.2 diff --git a/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0002-x86-entry-32-Rename-TSS_sysenter_sp0-to-TSS_entry_st.patch b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0002-x86-entry-32-Rename-TSS_sysenter_sp0-to-TSS_entry_st.patch index d228b31f..1d9b8f47 100644 --- a/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0002-x86-entry-32-Rename-TSS_sysenter_sp0-to-TSS_entry_st.patch +++ b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0002-x86-entry-32-Rename-TSS_sysenter_sp0-to-TSS_entry_st.patch @@ -1,7 +1,7 @@ From 52806123bdb0b558a5b4fbfa132bae32e53b008a Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Mon, 15 Jan 2018 18:20:15 +0100 -Subject: [PATCH 02/31] x86/entry/32: Rename TSS_sysenter_sp0 to +Subject: [PATCH 02/34] x86/entry/32: Rename TSS_sysenter_sp0 to TSS_entry_stack The stack address doesn't need to be stored in tss.sp0 if @@ -44,5 +44,5 @@ index fa1261eefa16..f452bfdc485a 100644 #ifdef CONFIG_CC_STACKPROTECTOR -- -2.13.6 +2.16.2 diff --git a/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0003-x86-entry-32-Load-task-stack-from-x86_tss.sp1-in-SYS.patch b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0003-x86-entry-32-Load-task-stack-from-x86_tss.sp1-in-SYS.patch index cf3e210d..6a891571 100644 --- a/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0003-x86-entry-32-Load-task-stack-from-x86_tss.sp1-in-SYS.patch +++ b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0003-x86-entry-32-Load-task-stack-from-x86_tss.sp1-in-SYS.patch @@ -1,7 +1,7 @@ From b696a2c46d9b9937b816b11ff2ec72aa0b65f204 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Fri, 19 Jan 2018 13:33:37 +0100 -Subject: [PATCH 03/31] x86/entry/32: Load task stack from x86_tss.sp1 in +Subject: [PATCH 03/34] x86/entry/32: Load task stack from x86_tss.sp1 in SYSENTER handler We want x86_tss.sp0 point to the entry stack later to use @@ -45,5 +45,5 @@ index 5224c6099184..097d36a64889 100644 /* * Restore %gs if needed (which is common) -- -2.13.6 +2.16.2 diff --git a/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0004-x86-entry-32-Put-ESPFIX-code-into-a-macro.patch b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0004-x86-entry-32-Put-ESPFIX-code-into-a-macro.patch index 488ab4fc..7a6d04ed 100644 --- a/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0004-x86-entry-32-Put-ESPFIX-code-into-a-macro.patch +++ b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0004-x86-entry-32-Put-ESPFIX-code-into-a-macro.patch @@ -1,7 +1,7 @@ From 7c97243c7694dc1c0e0ad73bc17bdc2c553225ac Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Wed, 31 Jan 2018 10:50:02 +0100 -Subject: [PATCH 04/31] x86/entry/32: Put ESPFIX code into a macro +Subject: [PATCH 04/34] x86/entry/32: Put ESPFIX code into a macro This makes it easier to split up the shared iret code path. @@ -133,5 +133,5 @@ index e65977615616..0289bde37a08 100644 .macro FIXUP_ESPFIX_STACK -- -2.13.6 +2.16.2 diff --git a/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0005-x86-entry-32-Unshare-NMI-return-path.patch b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0005-x86-entry-32-Unshare-NMI-return-path.patch index c3171963..33a1f95e 100644 --- a/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0005-x86-entry-32-Unshare-NMI-return-path.patch +++ b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0005-x86-entry-32-Unshare-NMI-return-path.patch @@ -1,7 +1,7 @@ From c66ec22d03296d1311197aaef753c1c320eed225 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Wed, 31 Jan 2018 10:58:38 +0100 -Subject: [PATCH 05/31] x86/entry/32: Unshare NMI return path +Subject: [PATCH 05/34] x86/entry/32: Unshare NMI return path NMI will no longer use most of the shared return path, because NMI needs special handling when the CR3 switches for @@ -39,5 +39,5 @@ index 0289bde37a08..00ae759a7c44 100644 #ifdef CONFIG_X86_ESPFIX32 .Lnmi_espfix_stack: -- -2.13.6 +2.16.2 diff --git a/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0006-x86-entry-32-Split-off-return-to-kernel-path.patch b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0006-x86-entry-32-Split-off-return-to-kernel-path.patch index 523e0f90..e47ab3d3 100644 --- a/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0006-x86-entry-32-Split-off-return-to-kernel-path.patch +++ b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0006-x86-entry-32-Split-off-return-to-kernel-path.patch @@ -1,7 +1,7 @@ From 916e5e906873de859d8a87c1ffb0323e167d1a44 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Wed, 31 Jan 2018 11:07:32 +0100 -Subject: [PATCH 06/31] x86/entry/32: Split off return-to-kernel path +Subject: [PATCH 06/34] x86/entry/32: Split off return-to-kernel path Use a separate return path when we know we are returning to the kernel. This allows us to put the PTI cr3-switch and the @@ -51,5 +51,5 @@ index 00ae759a7c44..9bd77183965f 100644 ENTRY(iret_exc ) pushl $0 # no error code -- -2.13.6 +2.16.2 diff --git a/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0007-x86-entry-32-Restore-segments-before-int-registers.patch b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0007-x86-entry-32-Restore-segments-before-int-registers.patch index 52c548e7..2fd4c846 100644 --- a/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0007-x86-entry-32-Restore-segments-before-int-registers.patch +++ b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0007-x86-entry-32-Restore-segments-before-int-registers.patch @@ -1,7 +1,7 @@ From c19ad15b16ec8908794459f28b44eca889a925f7 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Wed, 31 Jan 2018 11:29:59 +0100 -Subject: [PATCH 07/31] x86/entry/32: Restore segments before int registers +Subject: [PATCH 07/34] x86/entry/32: Restore segments before int registers Restoring the segments can cause exceptions that need to be handled. With PTI enabled, we still need to be on kernel cr3 @@ -27,18 +27,18 @@ diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S index 9bd77183965f..b39c5e210b43 100644 --- a/arch/x86/entry/entry_32.S +++ b/arch/x86/entry/entry_32.S -@@ -92,11 +92,6 @@ +@@ -91,11 +91,6 @@ + /* unfortunately push/pop can't be no-op */ .macro PUSH_GS pushl $0 - .endm +-.endm -.macro POP_GS pop=0 - addl $(4 + \pop), %esp -.endm -.macro POP_GS_EX --.endm + .endm /* all the rest are no-op */ - .macro PTGS_TO_GS @@ -116,20 +111,6 @@ pushl %gs .endm @@ -107,5 +107,5 @@ index 9bd77183965f..b39c5e210b43 100644 .macro CHECK_AND_APPLY_ESPFIX -- -2.13.6 +2.16.2 diff --git a/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0008-x86-entry-32-Enter-the-kernel-via-trampoline-stack.patch b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0008-x86-entry-32-Enter-the-kernel-via-trampoline-stack.patch index eb3f5103..0fddc074 100644 --- a/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0008-x86-entry-32-Enter-the-kernel-via-trampoline-stack.patch +++ b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0008-x86-entry-32-Enter-the-kernel-via-trampoline-stack.patch @@ -1,7 +1,7 @@ -From d9dc2b83bdfc2a9265302cc90b32739ac579f8cc Mon Sep 17 00:00:00 2001 +From 288a2a6b31018ab9172598a39477404582ae29fa Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Tue, 16 Jan 2018 10:55:52 +0100 -Subject: [PATCH 08/31] x86/entry/32: Enter the kernel via trampoline stack +Subject: [PATCH 08/34] x86/entry/32: Enter the kernel via trampoline stack Use the entry-stack as a trampoline to enter the kernel. The entry-stack is already in the cpu_entry_area and will be @@ -9,16 +9,16 @@ mapped to userspace when PTI is enabled. Signed-off-by: Joerg Roedel --- - arch/x86/entry/entry_32.S | 135 +++++++++++++++++++++++++++++++-------- + arch/x86/entry/entry_32.S | 136 +++++++++++++++++++++++++++++++-------- arch/x86/include/asm/switch_to.h | 6 +- arch/x86/kernel/asm-offsets.c | 1 + arch/x86/kernel/cpu/common.c | 5 +- arch/x86/kernel/process.c | 2 - arch/x86/kernel/process_32.c | 10 +-- - 6 files changed, 120 insertions(+), 39 deletions(-) + 6 files changed, 121 insertions(+), 39 deletions(-) diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S -index b39c5e210b43..e714b53b1eaa 100644 +index b39c5e210b43..1737da2e4517 100644 --- a/arch/x86/entry/entry_32.S +++ b/arch/x86/entry/entry_32.S @@ -135,25 +135,36 @@ @@ -65,7 +65,7 @@ index b39c5e210b43..e714b53b1eaa 100644 .endm /* -@@ -261,6 +272,71 @@ +@@ -261,6 +272,72 @@ .Lend_\@: #endif /* CONFIG_X86_ESPFIX32 */ .endm @@ -128,8 +128,9 @@ index b39c5e210b43..e714b53b1eaa 100644 + * We are now on the task-stack and can safely copy over the + * stack-frame + */ ++ shrl $2, %ecx + cld -+ rep movsb ++ rep movsl + +.Lend_\@: +.endm @@ -137,7 +138,7 @@ index b39c5e210b43..e714b53b1eaa 100644 /* * %eax: prev task * %edx: next task -@@ -454,6 +530,7 @@ ENTRY(xen_sysenter_target) +@@ -454,6 +531,7 @@ ENTRY(xen_sysenter_target) */ ENTRY(entry_SYSENTER_32) movl TSS_entry_stack(%esp), %esp @@ -145,7 +146,7 @@ index b39c5e210b43..e714b53b1eaa 100644 .Lsysenter_past_esp: pushl $__USER_DS /* pt_regs->ss */ pushl %ebp /* pt_regs->sp (stashed in bp) */ -@@ -462,7 +539,7 @@ ENTRY(entry_SYSENTER_32) +@@ -462,7 +540,7 @@ ENTRY(entry_SYSENTER_32) pushl $__USER_CS /* pt_regs->cs */ pushl $0 /* pt_regs->ip = 0 (placeholder) */ pushl %eax /* pt_regs->orig_ax */ @@ -154,7 +155,7 @@ index b39c5e210b43..e714b53b1eaa 100644 /* * SYSENTER doesn't filter flags, so we need to clear NT, AC -@@ -573,7 +650,8 @@ ENDPROC(entry_SYSENTER_32) +@@ -573,7 +651,8 @@ ENDPROC(entry_SYSENTER_32) ENTRY(entry_INT80_32) ASM_CLAC pushl %eax /* pt_regs->orig_ax */ @@ -164,7 +165,7 @@ index b39c5e210b43..e714b53b1eaa 100644 /* * User mode is traced as though IRQs are on, and the interrupt gate -@@ -665,7 +743,8 @@ END(irq_entries_start) +@@ -665,7 +744,8 @@ END(irq_entries_start) common_interrupt: ASM_CLAC addl $-0x80, (%esp) /* Adjust vector into the [-256, -1] range */ @@ -174,7 +175,7 @@ index b39c5e210b43..e714b53b1eaa 100644 ENCODE_FRAME_POINTER TRACE_IRQS_OFF movl %esp, %eax -@@ -673,16 +752,16 @@ common_interrupt: +@@ -673,16 +753,16 @@ common_interrupt: jmp ret_from_intr ENDPROC(common_interrupt) @@ -201,7 +202,7 @@ index b39c5e210b43..e714b53b1eaa 100644 ENDPROC(name) #define BUILD_INTERRUPT(name, nr) \ -@@ -908,16 +987,20 @@ common_exception: +@@ -908,16 +988,20 @@ common_exception: pushl %es pushl %ds pushl %eax @@ -224,7 +225,7 @@ index b39c5e210b43..e714b53b1eaa 100644 UNWIND_ESPFIX_STACK GS_TO_REG %ecx movl PT_GS(%esp), %edi # get the function address -@@ -925,9 +1008,6 @@ common_exception: +@@ -925,9 +1009,6 @@ common_exception: movl $-1, PT_ORIG_EAX(%esp) # no syscall to restart REG_TO_PTGS %ecx SET_KERNEL_GS %ecx @@ -234,7 +235,7 @@ index b39c5e210b43..e714b53b1eaa 100644 TRACE_IRQS_OFF movl %esp, %eax # pt_regs pointer CALL_NOSPEC %edi -@@ -946,6 +1026,7 @@ ENTRY(debug) +@@ -946,6 +1027,7 @@ ENTRY(debug) */ ASM_CLAC pushl $-1 # mark this as an int @@ -242,7 +243,7 @@ index b39c5e210b43..e714b53b1eaa 100644 SAVE_ALL ENCODE_FRAME_POINTER xorl %edx, %edx # error code 0 -@@ -981,6 +1062,7 @@ END(debug) +@@ -981,6 +1063,7 @@ END(debug) */ ENTRY(nmi) ASM_CLAC @@ -250,7 +251,7 @@ index b39c5e210b43..e714b53b1eaa 100644 #ifdef CONFIG_X86_ESPFIX32 pushl %eax movl %ss, %eax -@@ -1048,7 +1130,8 @@ END(nmi) +@@ -1048,7 +1131,8 @@ END(nmi) ENTRY(int3) ASM_CLAC pushl $-1 # mark this as an int @@ -351,5 +352,5 @@ index 097d36a64889..3f3a8c620c63 100644 /* -- -2.13.6 +2.16.2 diff --git a/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0009-x86-entry-32-Leave-the-kernel-via-trampoline-stack.patch b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0009-x86-entry-32-Leave-the-kernel-via-trampoline-stack.patch index 9abb0d63..d49e9396 100644 --- a/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0009-x86-entry-32-Leave-the-kernel-via-trampoline-stack.patch +++ b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0009-x86-entry-32-Leave-the-kernel-via-trampoline-stack.patch @@ -1,29 +1,30 @@ -From 4a06e416cfe4d173f8ed65799e112f77ecb12be8 Mon Sep 17 00:00:00 2001 +From af8c0db250e710c6ecd19a83bd8b57da44662041 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Tue, 16 Jan 2018 11:28:30 +0100 -Subject: [PATCH 09/31] x86/entry/32: Leave the kernel via trampoline stack +Subject: [PATCH 09/34] x86/entry/32: Leave the kernel via trampoline stack Switch back to the trampoline stack before returning to userspace. Signed-off-by: Joerg Roedel --- - arch/x86/entry/entry_32.S | 55 +++++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 55 insertions(+) + arch/x86/entry/entry_32.S | 79 +++++++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 77 insertions(+), 2 deletions(-) diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S -index e714b53b1eaa..ba3d8c2886ed 100644 +index 1737da2e4517..1b5656d7040e 100644 --- a/arch/x86/entry/entry_32.S +++ b/arch/x86/entry/entry_32.S -@@ -338,6 +338,59 @@ +@@ -338,6 +338,60 @@ + .Lend_\@: .endm - /* ++/* + * Switch back from the kernel stack to the entry stack. + * + * The %esp register must point to pt_regs on the task stack. It will + * first calculate the size of the stack-frame to copy, depending on -+ * whether we return to VM86 mode or not. With that it uses 'rep movsb' ++ * whether we return to VM86 mode or not. With that it uses 'rep movsl' + * to copy the contents of the stack over to the entry stack. + * + * We must be very careful here, as we can't trust the contents of the @@ -55,11 +56,12 @@ index e714b53b1eaa..ba3d8c2886ed 100644 + movl %esp, %esi + + /* Save future stack pointer in %ebx */ -+ movl %edi, %ebx ++ movl %edi, %ebx + + /* Copy over the stack-frame */ ++ shrl $2, %ecx + cld -+ rep movsb ++ rep movsl + + /* + * Switch to entry-stack - needs to happen after everything is @@ -71,19 +73,58 @@ index e714b53b1eaa..ba3d8c2886ed 100644 +.Lend_\@: +.endm + -+/* + /* * %eax: prev task * %edx: next task - */ -@@ -578,6 +631,7 @@ ENTRY(entry_SYSENTER_32) +@@ -579,25 +633,45 @@ ENTRY(entry_SYSENTER_32) /* Opportunistic SYSEXIT */ TRACE_IRQS_ON /* User mode traces as IRQs on. */ -+ SWITCH_TO_ENTRY_STACK /* Switch to per-cpu entry stack */ ++ ++ /* ++ * Setup entry stack - we keep the pointer in %eax and do the ++ * switch after almost all user-state is restored. ++ */ ++ ++ /* Load entry stack pointer and allocate frame for eflags/eax */ ++ movl PER_CPU_VAR(cpu_tss_rw + TSS_sp0), %eax ++ subl $(2*4), %eax ++ ++ /* Copy eflags and eax to entry stack */ ++ movl PT_EFLAGS(%esp), %edi ++ movl PT_EAX(%esp), %esi ++ movl %edi, (%eax) ++ movl %esi, 4(%eax) ++ ++ /* Restore user registers and segments */ movl PT_EIP(%esp), %edx /* pt_regs->ip */ movl PT_OLDESP(%esp), %ecx /* pt_regs->sp */ 1: mov PT_FS(%esp), %fs -@@ -665,6 +719,7 @@ ENTRY(entry_INT80_32) + PTGS_TO_GS ++ + popl %ebx /* pt_regs->bx */ + addl $2*4, %esp /* skip pt_regs->cx and pt_regs->dx */ + popl %esi /* pt_regs->si */ + popl %edi /* pt_regs->di */ + popl %ebp /* pt_regs->bp */ +- popl %eax /* pt_regs->ax */ ++ ++ /* Switch to entry stack */ ++ movl %eax, %esp + + /* + * Restore all flags except IF. (We restore IF separately because + * STI gives a one-instruction window in which we won't be interrupted, + * whereas POPF does not.) + */ +- addl $PT_EFLAGS-PT_DS, %esp /* point esp at pt_regs->flags */ + btr $X86_EFLAGS_IF_BIT, (%esp) + popfl ++ popl %eax + + /* + * Return back to the vDSO, which will pop ecx and edx. +@@ -666,6 +740,7 @@ ENTRY(entry_INT80_32) restore_all: TRACE_IRQS_IRET @@ -92,5 +133,5 @@ index e714b53b1eaa..ba3d8c2886ed 100644 CHECK_AND_APPLY_ESPFIX .Lrestore_nocheck: -- -2.13.6 +2.16.2 diff --git a/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0010-x86-entry-32-Introduce-SAVE_ALL_NMI-and-RESTORE_ALL_.patch b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0010-x86-entry-32-Introduce-SAVE_ALL_NMI-and-RESTORE_ALL_.patch index 9d5b730e..b45bb7b1 100644 --- a/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0010-x86-entry-32-Introduce-SAVE_ALL_NMI-and-RESTORE_ALL_.patch +++ b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0010-x86-entry-32-Introduce-SAVE_ALL_NMI-and-RESTORE_ALL_.patch @@ -1,7 +1,7 @@ -From 26b38ec7dd2591f092eb359a5a59752d799ab60d Mon Sep 17 00:00:00 2001 +From 49a15ace3cbe2fba45548538ede04c1599b33fb9 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Wed, 31 Jan 2018 16:35:42 +0100 -Subject: [PATCH 10/31] x86/entry/32: Introduce SAVE_ALL_NMI and +Subject: [PATCH 10/34] x86/entry/32: Introduce SAVE_ALL_NMI and RESTORE_ALL_NMI These macros will be used in the NMI handler code and @@ -14,7 +14,7 @@ Signed-off-by: Joerg Roedel 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S -index ba3d8c2886ed..be1d814bd056 100644 +index 1b5656d7040e..bb0bd896c74b 100644 --- a/arch/x86/entry/entry_32.S +++ b/arch/x86/entry/entry_32.S @@ -167,6 +167,9 @@ @@ -46,7 +46,7 @@ index ba3d8c2886ed..be1d814bd056 100644 .macro CHECK_AND_APPLY_ESPFIX #ifdef CONFIG_X86_ESPFIX32 #define GDT_ESPFIX_SS PER_CPU_VAR(gdt_page) + (GDT_ENTRY_ESPFIX_SS * 8) -@@ -1127,7 +1142,7 @@ ENTRY(nmi) +@@ -1148,7 +1163,7 @@ ENTRY(nmi) #endif pushl %eax # pt_regs->orig_ax @@ -55,7 +55,7 @@ index ba3d8c2886ed..be1d814bd056 100644 ENCODE_FRAME_POINTER xorl %edx, %edx # zero error code movl %esp, %eax # pt_regs pointer -@@ -1155,7 +1170,7 @@ ENTRY(nmi) +@@ -1176,7 +1191,7 @@ ENTRY(nmi) .Lnmi_return: CHECK_AND_APPLY_ESPFIX @@ -64,7 +64,7 @@ index ba3d8c2886ed..be1d814bd056 100644 jmp .Lirq_return #ifdef CONFIG_X86_ESPFIX32 -@@ -1171,12 +1186,12 @@ ENTRY(nmi) +@@ -1192,12 +1207,12 @@ ENTRY(nmi) pushl 16(%esp) .endr pushl %eax @@ -80,5 +80,5 @@ index ba3d8c2886ed..be1d814bd056 100644 jmp .Lirq_return #endif -- -2.13.6 +2.16.2 diff --git a/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0011-x86-entry-32-Handle-Entry-from-Kernel-Mode-on-Entry-.patch b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0011-x86-entry-32-Handle-Entry-from-Kernel-Mode-on-Entry-.patch new file mode 100644 index 00000000..c96d7a6e --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0011-x86-entry-32-Handle-Entry-from-Kernel-Mode-on-Entry-.patch @@ -0,0 +1,198 @@ +From bbad1145165d4ed4452913df109ee3429a10dd90 Mon Sep 17 00:00:00 2001 +From: Joerg Roedel +Date: Wed, 31 Jan 2018 20:48:02 +0100 +Subject: [PATCH 11/34] x86/entry/32: Handle Entry from Kernel-Mode on + Entry-Stack + +It can happen that we enter the kernel from kernel-mode and +on the entry-stack. The most common way this happens is when +we get an exception while loading the user-space segment +registers on the kernel-to-userspace exit path. + +The segment loading needs to be done after the entry-stack +switch, because the stack-switch needs kernel %fs for +per_cpu access. + +When this happens, we need to make sure that we leave the +kernel with the entry-stack again, so that the interrupted +code-path runs on the right stack when switching to the +user-cr3. + +We do this by detecting this condition on kernel-entry by +checking CS.RPL and %esp, and if it happens, we copy over +the complete content of the entry stack to the task-stack. +This needs to be done because once we enter the exception +handlers we might be scheduled out or even migrated to a +different CPU, so that we can't rely on the entry-stack +contents. We also leave a marker in the stack-frame to +detect this condition on the exit path. + +On the exit path the copy is reversed, we copy all of the +remaining task-stack back to the entry-stack and switch +to it. + +Signed-off-by: Joerg Roedel +--- + arch/x86/entry/entry_32.S | 110 +++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 109 insertions(+), 1 deletion(-) + +diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S +index bb0bd896c74b..3a84945fa3b6 100644 +--- a/arch/x86/entry/entry_32.S ++++ b/arch/x86/entry/entry_32.S +@@ -299,6 +299,9 @@ + * copied there. So allocate the stack-frame on the task-stack and + * switch to it before we do any copying. + */ ++ ++#define CS_FROM_ENTRY_STACK (1 << 31) ++ + .macro SWITCH_TO_KERNEL_STACK + + ALTERNATIVE "", "jmp .Lend_\@", X86_FEATURE_XENPV +@@ -320,6 +323,10 @@ + /* Load top of task-stack into %edi */ + movl TSS_entry_stack(%edi), %edi + ++ /* Special case - entry from kernel mode via entry stack */ ++ testl $SEGMENT_RPL_MASK, PT_CS(%esp) ++ jz .Lentry_from_kernel_\@ ++ + /* Bytes to copy */ + movl $PTREGS_SIZE, %ecx + +@@ -333,8 +340,8 @@ + */ + addl $(4 * 4), %ecx + +-.Lcopy_pt_regs_\@: + #endif ++.Lcopy_pt_regs_\@: + + /* Allocate frame on task-stack */ + subl %ecx, %edi +@@ -350,6 +357,56 @@ + cld + rep movsl + ++ jmp .Lend_\@ ++ ++.Lentry_from_kernel_\@: ++ ++ /* ++ * This handles the case when we enter the kernel from ++ * kernel-mode and %esp points to the entry-stack. When this ++ * happens we need to switch to the task-stack to run C code, ++ * but switch back to the entry-stack again when we approach ++ * iret and return to the interrupted code-path. This usually ++ * happens when we hit an exception while restoring user-space ++ * segment registers on the way back to user-space. ++ * ++ * When we switch to the task-stack here, we can't trust the ++ * contents of the entry-stack anymore, as the exception handler ++ * might be scheduled out or moved to another CPU. Therefore we ++ * copy the complete entry-stack to the task-stack and set a ++ * marker in the iret-frame (bit 31 of the CS dword) to detect ++ * what we've done on the iret path. ++ * ++ * On the iret path we copy everything back and switch to the ++ * entry-stack, so that the interrupted kernel code-path ++ * continues on the same stack it was interrupted with. ++ * ++ * Be aware that an NMI can happen anytime in this code. ++ * ++ * %esi: Entry-Stack pointer (same as %esp) ++ * %edi: Top of the task stack ++ */ ++ ++ /* Calculate number of bytes on the entry stack in %ecx */ ++ movl %esi, %ecx ++ ++ /* %ecx to the top of entry-stack */ ++ andl $(MASK_entry_stack), %ecx ++ addl $(SIZEOF_entry_stack), %ecx ++ ++ /* Number of bytes on the entry stack to %ecx */ ++ sub %esi, %ecx ++ ++ /* Mark stackframe as coming from entry stack */ ++ orl $CS_FROM_ENTRY_STACK, PT_CS(%esp) ++ ++ /* ++ * %esi and %edi are unchanged, %ecx contains the number of ++ * bytes to copy. The code at .Lcopy_pt_regs_\@ will allocate ++ * the stack-frame on task-stack and copy everything over ++ */ ++ jmp .Lcopy_pt_regs_\@ ++ + .Lend_\@: + .endm + +@@ -407,6 +464,56 @@ + .Lend_\@: + .endm + ++/* ++ * This macro handles the case when we return to kernel-mode on the iret ++ * path and have to switch back to the entry stack. ++ * ++ * See the comments below the .Lentry_from_kernel_\@ label in the ++ * SWITCH_TO_KERNEL_STACK macro for more details. ++ */ ++.macro PARANOID_EXIT_TO_KERNEL_MODE ++ ++ /* ++ * Test if we entered the kernel with the entry-stack. Most ++ * likely we did not, because this code only runs on the ++ * return-to-kernel path. ++ */ ++ testl $CS_FROM_ENTRY_STACK, PT_CS(%esp) ++ jz .Lend_\@ ++ ++ /* Unlikely slow-path */ ++ ++ /* Clear marker from stack-frame */ ++ andl $(~CS_FROM_ENTRY_STACK), PT_CS(%esp) ++ ++ /* Copy the remaining task-stack contents to entry-stack */ ++ movl %esp, %esi ++ movl PER_CPU_VAR(cpu_tss_rw + TSS_sp0), %edi ++ ++ /* Bytes on the task-stack to ecx */ ++ movl PER_CPU_VAR(cpu_current_top_of_stack), %ecx ++ subl %esi, %ecx ++ ++ /* Allocate stack-frame on entry-stack */ ++ subl %ecx, %edi ++ ++ /* ++ * Save future stack-pointer, we must not switch until the ++ * copy is done, otherwise the NMI handler could destroy the ++ * contents of the task-stack we are about to copy. ++ */ ++ movl %edi, %ebx ++ ++ /* Do the copy */ ++ shrl $2, %ecx ++ cld ++ rep movsl ++ ++ /* Safe to switch to entry-stack now */ ++ movl %ebx, %esp ++ ++.Lend_\@: ++.endm + /* + * %eax: prev task + * %edx: next task +@@ -765,6 +872,7 @@ restore_all: + + restore_all_kernel: + TRACE_IRQS_IRET ++ PARANOID_EXIT_TO_KERNEL_MODE + RESTORE_REGS 4 + jmp .Lirq_return + +-- +2.16.2 + diff --git a/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0012-x86-entry-32-Simplify-debug-entry-point.patch b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0012-x86-entry-32-Simplify-debug-entry-point.patch new file mode 100644 index 00000000..803fb485 --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0012-x86-entry-32-Simplify-debug-entry-point.patch @@ -0,0 +1,69 @@ +From 8743506d5153928d0a0fb4106470a6581d03796d Mon Sep 17 00:00:00 2001 +From: Joerg Roedel +Date: Thu, 1 Mar 2018 14:48:16 +0100 +Subject: [PATCH 12/34] x86/entry/32: Simplify debug entry point + +The common exception entry code now handles the +entry-from-sysenter stack situation and makes sure to leave +with the same stack as it entered the kernel. + +So there is no need anymore for the special handling in the +debug entry code. + +Signed-off-by: Joerg Roedel +--- + arch/x86/entry/entry_32.S | 35 +++-------------------------------- + 1 file changed, 3 insertions(+), 32 deletions(-) + +diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S +index 3a84945fa3b6..b1a5f34eeb27 100644 +--- a/arch/x86/entry/entry_32.S ++++ b/arch/x86/entry/entry_32.S +@@ -1215,41 +1215,12 @@ END(common_exception) + + ENTRY(debug) + /* +- * #DB can happen at the first instruction of +- * entry_SYSENTER_32 or in Xen's SYSENTER prologue. If this +- * happens, then we will be running on a very small stack. We +- * need to detect this condition and switch to the thread +- * stack before calling any C code at all. +- * +- * If you edit this code, keep in mind that NMIs can happen in here. ++ * Entry from sysenter is now handled in common_exception + */ + ASM_CLAC + pushl $-1 # mark this as an int +- +- SAVE_ALL +- ENCODE_FRAME_POINTER +- xorl %edx, %edx # error code 0 +- movl %esp, %eax # pt_regs pointer +- +- /* Are we currently on the SYSENTER stack? */ +- movl PER_CPU_VAR(cpu_entry_area), %ecx +- addl $CPU_ENTRY_AREA_entry_stack + SIZEOF_entry_stack, %ecx +- subl %eax, %ecx /* ecx = (end of entry_stack) - esp */ +- cmpl $SIZEOF_entry_stack, %ecx +- jb .Ldebug_from_sysenter_stack +- +- TRACE_IRQS_OFF +- call do_debug +- jmp ret_from_exception +- +-.Ldebug_from_sysenter_stack: +- /* We're on the SYSENTER stack. Switch off. */ +- movl %esp, %ebx +- movl PER_CPU_VAR(cpu_current_top_of_stack), %esp +- TRACE_IRQS_OFF +- call do_debug +- movl %ebx, %esp +- jmp ret_from_exception ++ pushl $do_debug ++ jmp common_exception + END(debug) + + /* +-- +2.16.2 + diff --git a/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0013-x86-entry-32-Add-PTI-cr3-switches-to-NMI-handler-cod.patch b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0013-x86-entry-32-Add-PTI-cr3-switches-to-NMI-handler-cod.patch new file mode 100644 index 00000000..3ecd0997 --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0013-x86-entry-32-Add-PTI-cr3-switches-to-NMI-handler-cod.patch @@ -0,0 +1,127 @@ +From 41bc2c77864b5464134c3ec722225a9ae4701968 Mon Sep 17 00:00:00 2001 +From: Joerg Roedel +Date: Wed, 31 Jan 2018 16:58:57 +0100 +Subject: [PATCH 13/34] x86/entry/32: Add PTI cr3 switches to NMI handler code + +The NMI handler is special, as it needs to leave with the +same cr3 as it was entered with. We need to do this because +we could enter the NMI handler from kernel code with +user-cr3 already loaded. + +Signed-off-by: Joerg Roedel +--- + arch/x86/entry/entry_32.S | 52 +++++++++++++++++++++++++++++++++++++++++------ + 1 file changed, 46 insertions(+), 6 deletions(-) + +diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S +index b1a5f34eeb27..35379e5f60c6 100644 +--- a/arch/x86/entry/entry_32.S ++++ b/arch/x86/entry/entry_32.S +@@ -77,6 +77,8 @@ + #endif + .endm + ++#define PTI_SWITCH_MASK (1 << PAGE_SHIFT) ++ + /* + * User gs save/restore + * +@@ -167,8 +169,30 @@ + + .endm + +-.macro SAVE_ALL_NMI ++.macro SAVE_ALL_NMI cr3_reg:req + SAVE_ALL ++ ++ /* ++ * Now switch the CR3 when PTI is enabled. ++ * ++ * We can enter with either user or kernel cr3, the code will ++ * store the old cr3 in \cr3_reg and switches to the kernel cr3 ++ * if necessary. ++ */ ++ ALTERNATIVE "jmp .Lend_\@", "", X86_FEATURE_PTI ++ ++ movl %cr3, \cr3_reg ++ testl $PTI_SWITCH_MASK, \cr3_reg ++ jz .Lend_\@ /* Already on kernel cr3 */ ++ ++ /* On user cr3 - write new kernel cr3 */ ++ andl $(~PTI_SWITCH_MASK), \cr3_reg ++ movl \cr3_reg, %cr3 ++ ++ /* Restore user cr3 value */ ++ orl $PTI_SWITCH_MASK, \cr3_reg ++ ++.Lend_\@: + .endm + /* + * This is a sneaky trick to help the unwinder find pt_regs on the stack. The +@@ -227,13 +251,29 @@ + RESTORE_SKIP_SEGMENTS \pop + .endm + +-.macro RESTORE_ALL_NMI pop=0 ++.macro RESTORE_ALL_NMI cr3_reg:req pop=0 + /* + * Restore segments - might cause exceptions when loading + * user-space segments + */ + RESTORE_SEGMENTS + ++ /* ++ * Now switch the CR3 when PTI is enabled. ++ * ++ * We enter with kernel cr3 and switch the cr3 to the value ++ * stored on \cr3_reg, which is either a user or a kernel cr3. ++ */ ++ ALTERNATIVE "jmp .Lswitched_\@", "", X86_FEATURE_PTI ++ ++ testl $PTI_SWITCH_MASK, \cr3_reg ++ jz .Lswitched_\@ ++ ++ /* User cr3 in \cr3_reg - write it to hardware cr3 */ ++ movl \cr3_reg, %cr3 ++ ++.Lswitched_\@: ++ + /* Restore integer registers and unwind stack to iret frame */ + RESTORE_INT_REGS + RESTORE_SKIP_SEGMENTS \pop +@@ -1242,7 +1282,7 @@ ENTRY(nmi) + #endif + + pushl %eax # pt_regs->orig_ax +- SAVE_ALL_NMI ++ SAVE_ALL_NMI cr3_reg=%edi + ENCODE_FRAME_POINTER + xorl %edx, %edx # zero error code + movl %esp, %eax # pt_regs pointer +@@ -1270,7 +1310,7 @@ ENTRY(nmi) + + .Lnmi_return: + CHECK_AND_APPLY_ESPFIX +- RESTORE_ALL_NMI pop=4 ++ RESTORE_ALL_NMI cr3_reg=%edi pop=4 + jmp .Lirq_return + + #ifdef CONFIG_X86_ESPFIX32 +@@ -1286,12 +1326,12 @@ ENTRY(nmi) + pushl 16(%esp) + .endr + pushl %eax +- SAVE_ALL_NMI ++ SAVE_ALL_NMI cr3_reg=%edi + ENCODE_FRAME_POINTER + FIXUP_ESPFIX_STACK # %eax == %esp + xorl %edx, %edx # zero error code + call do_nmi +- RESTORE_ALL_NMI ++ RESTORE_ALL_NMI cr3_reg=%edi + lss 12+4(%esp), %esp # back to espfix stack + jmp .Lirq_return + #endif +-- +2.16.2 + diff --git a/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0014-x86-entry-32-Add-PTI-cr3-switch-to-non-NMI-entry-exi.patch b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0014-x86-entry-32-Add-PTI-cr3-switch-to-non-NMI-entry-exi.patch new file mode 100644 index 00000000..7f9db488 --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0014-x86-entry-32-Add-PTI-cr3-switch-to-non-NMI-entry-exi.patch @@ -0,0 +1,187 @@ +From d40791fdb56c15767c7c65a1a2e0c8736f3db0af Mon Sep 17 00:00:00 2001 +From: Joerg Roedel +Date: Wed, 31 Jan 2018 17:22:10 +0100 +Subject: [PATCH 14/34] x86/entry/32: Add PTI cr3 switch to non-NMI entry/exit + points + +Add unconditional cr3 switches between user and kernel cr3 +to all non-NMI entry and exit points. + +Signed-off-by: Joerg Roedel +--- + arch/x86/entry/entry_32.S | 91 +++++++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 88 insertions(+), 3 deletions(-) + +diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S +index 35379e5f60c6..8f78abcf1f9c 100644 +--- a/arch/x86/entry/entry_32.S ++++ b/arch/x86/entry/entry_32.S +@@ -328,6 +328,30 @@ + #endif /* CONFIG_X86_ESPFIX32 */ + .endm + ++/* Unconditionally switch to user cr3 */ ++.macro SWITCH_TO_USER_CR3 scratch_reg:req ++ ALTERNATIVE "jmp .Lend_\@", "", X86_FEATURE_PTI ++ ++ movl %cr3, \scratch_reg ++ orl $PTI_SWITCH_MASK, \scratch_reg ++ movl \scratch_reg, %cr3 ++.Lend_\@: ++.endm ++ ++/* Unconditionally switch to kernel cr3 */ ++.macro SWITCH_TO_KERNEL_CR3 scratch_reg:req ++ ALTERNATIVE "jmp .Lend_\@", "", X86_FEATURE_PTI ++ movl %cr3, \scratch_reg ++ /* Test if we are already on kernel CR3 */ ++ testl $PTI_SWITCH_MASK, \scratch_reg ++ jz .Lend_\@ ++ andl $(~PTI_SWITCH_MASK), \scratch_reg ++ movl \scratch_reg, %cr3 ++ /* Return original CR3 in \scratch_reg */ ++ orl $PTI_SWITCH_MASK, \scratch_reg ++.Lend_\@: ++.endm ++ + + /* + * Called with pt_regs fully populated and kernel segments loaded, +@@ -341,11 +365,19 @@ + */ + + #define CS_FROM_ENTRY_STACK (1 << 31) ++#define CS_FROM_USER_CR3 (1 << 30) + + .macro SWITCH_TO_KERNEL_STACK + + ALTERNATIVE "", "jmp .Lend_\@", X86_FEATURE_XENPV + ++ SWITCH_TO_KERNEL_CR3 scratch_reg=%eax ++ ++ /* ++ * %eax now contains the entry cr3 and we carry it forward in ++ * that register for the time this macro runs ++ */ ++ + /* Are we on the entry stack? Bail out if not! */ + movl PER_CPU_VAR(cpu_entry_area), %edi + addl $CPU_ENTRY_AREA_entry_stack, %edi +@@ -408,7 +440,8 @@ + * but switch back to the entry-stack again when we approach + * iret and return to the interrupted code-path. This usually + * happens when we hit an exception while restoring user-space +- * segment registers on the way back to user-space. ++ * segment registers on the way back to user-space or when the ++ * sysenter handler runs with eflags.tf set. + * + * When we switch to the task-stack here, we can't trust the + * contents of the entry-stack anymore, as the exception handler +@@ -425,6 +458,7 @@ + * + * %esi: Entry-Stack pointer (same as %esp) + * %edi: Top of the task stack ++ * %eax: CR3 on kernel entry + */ + + /* Calculate number of bytes on the entry stack in %ecx */ +@@ -440,6 +474,14 @@ + /* Mark stackframe as coming from entry stack */ + orl $CS_FROM_ENTRY_STACK, PT_CS(%esp) + ++ /* ++ * Test the cr3 used to enter the kernel and add a marker ++ * so that we can switch back to it before iret. ++ */ ++ testl $PTI_SWITCH_MASK, %eax ++ jz .Lcopy_pt_regs_\@ ++ orl $CS_FROM_USER_CR3, PT_CS(%esp) ++ + /* + * %esi and %edi are unchanged, %ecx contains the number of + * bytes to copy. The code at .Lcopy_pt_regs_\@ will allocate +@@ -506,7 +548,7 @@ + + /* + * This macro handles the case when we return to kernel-mode on the iret +- * path and have to switch back to the entry stack. ++ * path and have to switch back to the entry stack and/or user-cr3 + * + * See the comments below the .Lentry_from_kernel_\@ label in the + * SWITCH_TO_KERNEL_STACK macro for more details. +@@ -552,6 +594,18 @@ + /* Safe to switch to entry-stack now */ + movl %ebx, %esp + ++ /* ++ * We came from entry-stack and need to check if we also need to ++ * switch back to user cr3. ++ */ ++ testl $CS_FROM_USER_CR3, PT_CS(%esp) ++ jz .Lend_\@ ++ ++ /* Clear marker from stack-frame */ ++ andl $(~CS_FROM_USER_CR3), PT_CS(%esp) ++ ++ SWITCH_TO_USER_CR3 scratch_reg=%eax ++ + .Lend_\@: + .endm + /* +@@ -746,6 +800,18 @@ ENTRY(xen_sysenter_target) + * 0(%ebp) arg6 + */ + ENTRY(entry_SYSENTER_32) ++ /* ++ * On entry-stack with all userspace-regs live - save and ++ * restore eflags and %eax to use it as scratch-reg for the cr3 ++ * switch. ++ */ ++ pushfl ++ pushl %eax ++ SWITCH_TO_KERNEL_CR3 scratch_reg=%eax ++ popl %eax ++ popfl ++ ++ /* Stack empty again, switch to task stack */ + movl TSS_entry_stack(%esp), %esp + + .Lsysenter_past_esp: +@@ -826,6 +892,9 @@ ENTRY(entry_SYSENTER_32) + /* Switch to entry stack */ + movl %eax, %esp + ++ /* Now ready to switch the cr3 */ ++ SWITCH_TO_USER_CR3 scratch_reg=%eax ++ + /* + * Restore all flags except IF. (We restore IF separately because + * STI gives a one-instruction window in which we won't be interrupted, +@@ -906,7 +975,23 @@ restore_all: + .Lrestore_all_notrace: + CHECK_AND_APPLY_ESPFIX + .Lrestore_nocheck: +- RESTORE_REGS 4 # skip orig_eax/error_code ++ /* ++ * First restore user segments. This can cause exceptions, so we ++ * run it with kernel cr3. ++ */ ++ RESTORE_SEGMENTS ++ ++ /* ++ * Segments are restored - no more exceptions from here on except on ++ * iret, but that handled safely. ++ */ ++ SWITCH_TO_USER_CR3 scratch_reg=%eax ++ ++ /* Restore rest */ ++ RESTORE_INT_REGS ++ ++ /* Unwind stack to the iret frame */ ++ RESTORE_SKIP_SEGMENTS 4 # skip orig_eax/error_code + .Lirq_return: + INTERRUPT_RETURN + +-- +2.16.2 + diff --git a/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0015-x86-pgtable-Rename-pti_set_user_pgd-to-pti_set_user_.patch b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0015-x86-pgtable-Rename-pti_set_user_pgd-to-pti_set_user_.patch new file mode 100644 index 00000000..60452628 --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0015-x86-pgtable-Rename-pti_set_user_pgd-to-pti_set_user_.patch @@ -0,0 +1,81 @@ +From 55797d951b45c9eb709a4e7483eef89d738c2427 Mon Sep 17 00:00:00 2001 +From: Joerg Roedel +Date: Thu, 1 Mar 2018 13:40:39 +0100 +Subject: [PATCH 15/34] x86/pgtable: Rename pti_set_user_pgd to + pti_set_user_pgtbl + +With the way page-table folding is implemented on 32 bit, we +are not only setting PGDs with this functions, but also PUDs +and even PMDs. Give the function a more generic name to +reflect that. + +Signed-off-by: Joerg Roedel +--- + arch/x86/include/asm/pgtable_64.h | 12 ++++++------ + arch/x86/mm/pti.c | 2 +- + 2 files changed, 7 insertions(+), 7 deletions(-) + +diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h +index 81462e9a34f6..b68bda56db67 100644 +--- a/arch/x86/include/asm/pgtable_64.h ++++ b/arch/x86/include/asm/pgtable_64.h +@@ -195,21 +195,21 @@ static inline bool pgdp_maps_userspace(void *__ptr) + } + + #ifdef CONFIG_PAGE_TABLE_ISOLATION +-pgd_t __pti_set_user_pgd(pgd_t *pgdp, pgd_t pgd); ++pgd_t __pti_set_user_pgtbl(pgd_t *pgdp, pgd_t pgd); + + /* + * Take a PGD location (pgdp) and a pgd value that needs to be set there. + * Populates the user and returns the resulting PGD that must be set in + * the kernel copy of the page tables. + */ +-static inline pgd_t pti_set_user_pgd(pgd_t *pgdp, pgd_t pgd) ++static inline pgd_t pti_set_user_pgtbl(pgd_t *pgdp, pgd_t pgd) + { + if (!static_cpu_has(X86_FEATURE_PTI)) + return pgd; +- return __pti_set_user_pgd(pgdp, pgd); ++ return __pti_set_user_pgtbl(pgdp, pgd); + } + #else +-static inline pgd_t pti_set_user_pgd(pgd_t *pgdp, pgd_t pgd) ++static inline pgd_t pti_set_user_pgtbl(pgd_t *pgdp, pgd_t pgd) + { + return pgd; + } +@@ -218,7 +218,7 @@ static inline pgd_t pti_set_user_pgd(pgd_t *pgdp, pgd_t pgd) + static inline void native_set_p4d(p4d_t *p4dp, p4d_t p4d) + { + #if defined(CONFIG_PAGE_TABLE_ISOLATION) && !defined(CONFIG_X86_5LEVEL) +- p4dp->pgd = pti_set_user_pgd(&p4dp->pgd, p4d.pgd); ++ p4dp->pgd = pti_set_user_pgtbl(&p4dp->pgd, p4d.pgd); + #else + *p4dp = p4d; + #endif +@@ -236,7 +236,7 @@ static inline void native_p4d_clear(p4d_t *p4d) + static inline void native_set_pgd(pgd_t *pgdp, pgd_t pgd) + { + #ifdef CONFIG_PAGE_TABLE_ISOLATION +- *pgdp = pti_set_user_pgd(pgdp, pgd); ++ *pgdp = pti_set_user_pgtbl(pgdp, pgd); + #else + *pgdp = pgd; + #endif +diff --git a/arch/x86/mm/pti.c b/arch/x86/mm/pti.c +index ce38f165489b..8f53d2101f64 100644 +--- a/arch/x86/mm/pti.c ++++ b/arch/x86/mm/pti.c +@@ -102,7 +102,7 @@ void __init pti_check_boottime_disable(void) + setup_force_cpu_cap(X86_FEATURE_PTI); + } + +-pgd_t __pti_set_user_pgd(pgd_t *pgdp, pgd_t pgd) ++pgd_t __pti_set_user_pgtbl(pgd_t *pgdp, pgd_t pgd) + { + /* + * Changes to the high (kernel) portion of the kernelmode page +-- +2.16.2 + diff --git a/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0016-x86-pgtable-pae-Unshare-kernel-PMDs-when-PTI-is-enab.patch b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0016-x86-pgtable-pae-Unshare-kernel-PMDs-when-PTI-is-enab.patch new file mode 100644 index 00000000..dc9e750d --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0016-x86-pgtable-pae-Unshare-kernel-PMDs-when-PTI-is-enab.patch @@ -0,0 +1,35 @@ +From 5439accd9f31dacdfbf67a18440d5805e8a0bfad Mon Sep 17 00:00:00 2001 +From: Joerg Roedel +Date: Fri, 2 Feb 2018 10:41:36 +0100 +Subject: [PATCH 16/34] x86/pgtable/pae: Unshare kernel PMDs when PTI is + enabled + +With PTI we need to map the per-process LDT into the kernel +address-space for each process, so we need separate kernel +PMDs per PGD. + +Signed-off-by: Joerg Roedel +--- + arch/x86/include/asm/pgtable-3level_types.h | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/arch/x86/include/asm/pgtable-3level_types.h b/arch/x86/include/asm/pgtable-3level_types.h +index 876b4c77d983..ed8a200ecdaf 100644 +--- a/arch/x86/include/asm/pgtable-3level_types.h ++++ b/arch/x86/include/asm/pgtable-3level_types.h +@@ -21,9 +21,10 @@ typedef union { + #endif /* !__ASSEMBLY__ */ + + #ifdef CONFIG_PARAVIRT +-#define SHARED_KERNEL_PMD (pv_info.shared_kernel_pmd) ++#define SHARED_KERNEL_PMD ((!static_cpu_has(X86_FEATURE_PTI) && \ ++ (pv_info.shared_kernel_pmd))) + #else +-#define SHARED_KERNEL_PMD 1 ++#define SHARED_KERNEL_PMD (!static_cpu_has(X86_FEATURE_PTI)) + #endif + + /* +-- +2.16.2 + diff --git a/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0017-x86-pgtable-32-Allocate-8k-page-tables-when-PTI-is-e.patch b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0017-x86-pgtable-32-Allocate-8k-page-tables-when-PTI-is-e.patch new file mode 100644 index 00000000..1cf7b9c7 --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0017-x86-pgtable-32-Allocate-8k-page-tables-when-PTI-is-e.patch @@ -0,0 +1,98 @@ +From 35cdf0541e9d5c7a47b59530fc8a42ac9ab767f8 Mon Sep 17 00:00:00 2001 +From: Joerg Roedel +Date: Tue, 16 Jan 2018 13:10:57 +0100 +Subject: [PATCH 17/34] x86/pgtable/32: Allocate 8k page-tables when PTI is + enabled + +Allocate a kernel and a user page-table root when PTI is +enabled. Also allocate a full page per root for PAE because +otherwise the bit to flip in cr3 to switch between them +would be non-constant, which creates a lot of hassle. +Keep that for a later optimization. + +Signed-off-by: Joerg Roedel +--- + arch/x86/kernel/head_32.S | 20 +++++++++++++++----- + arch/x86/mm/pgtable.c | 5 +++-- + 2 files changed, 18 insertions(+), 7 deletions(-) + +diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S +index c29020907886..1f35d600b69f 100644 +--- a/arch/x86/kernel/head_32.S ++++ b/arch/x86/kernel/head_32.S +@@ -512,11 +512,18 @@ ENTRY(initial_code) + ENTRY(setup_once_ref) + .long setup_once + ++#ifdef CONFIG_PAGE_TABLE_ISOLATION ++#define PGD_ALIGN (2 * PAGE_SIZE) ++#define PTI_USER_PGD_FILL 1024 ++#else ++#define PGD_ALIGN (PAGE_SIZE) ++#define PTI_USER_PGD_FILL 0 ++#endif + /* + * BSS section + */ + __PAGE_ALIGNED_BSS +- .align PAGE_SIZE ++ .align PGD_ALIGN + #ifdef CONFIG_X86_PAE + .globl initial_pg_pmd + initial_pg_pmd: +@@ -526,14 +533,17 @@ initial_pg_pmd: + initial_page_table: + .fill 1024,4,0 + #endif ++ .align PGD_ALIGN + initial_pg_fixmap: + .fill 1024,4,0 +-.globl empty_zero_page +-empty_zero_page: +- .fill 4096,1,0 + .globl swapper_pg_dir ++ .align PGD_ALIGN + swapper_pg_dir: + .fill 1024,4,0 ++ .fill PTI_USER_PGD_FILL,4,0 ++.globl empty_zero_page ++empty_zero_page: ++ .fill 4096,1,0 + EXPORT_SYMBOL(empty_zero_page) + + /* +@@ -542,7 +552,7 @@ EXPORT_SYMBOL(empty_zero_page) + #ifdef CONFIG_X86_PAE + __PAGE_ALIGNED_DATA + /* Page-aligned for the benefit of paravirt? */ +- .align PAGE_SIZE ++ .align PGD_ALIGN + ENTRY(initial_page_table) + .long pa(initial_pg_pmd+PGD_IDENT_ATTR),0 /* low identity map */ + # if KPMDS == 3 +diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c +index 004abf9ebf12..a81d42e48922 100644 +--- a/arch/x86/mm/pgtable.c ++++ b/arch/x86/mm/pgtable.c +@@ -338,7 +338,8 @@ static inline pgd_t *_pgd_alloc(void) + * We allocate one page for pgd. + */ + if (!SHARED_KERNEL_PMD) +- return (pgd_t *)__get_free_page(PGALLOC_GFP); ++ return (pgd_t *)__get_free_pages(PGALLOC_GFP, ++ PGD_ALLOCATION_ORDER); + + /* + * Now PAE kernel is not running as a Xen domain. We can allocate +@@ -350,7 +351,7 @@ static inline pgd_t *_pgd_alloc(void) + static inline void _pgd_free(pgd_t *pgd) + { + if (!SHARED_KERNEL_PMD) +- free_page((unsigned long)pgd); ++ free_pages((unsigned long)pgd, PGD_ALLOCATION_ORDER); + else + kmem_cache_free(pgd_cache, pgd); + } +-- +2.16.2 + diff --git a/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0018-x86-pgtable-Move-pgdp-kernel-user-conversion-functio.patch b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0018-x86-pgtable-Move-pgdp-kernel-user-conversion-functio.patch new file mode 100644 index 00000000..ff12561b --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0018-x86-pgtable-Move-pgdp-kernel-user-conversion-functio.patch @@ -0,0 +1,137 @@ +From 69dfcb6ee23f6841982e059f58cc9be921b669dc Mon Sep 17 00:00:00 2001 +From: Joerg Roedel +Date: Tue, 16 Jan 2018 11:53:38 +0100 +Subject: [PATCH 18/34] x86/pgtable: Move pgdp kernel/user conversion functions + to pgtable.h + +Make them available on 32 bit and clone_pgd_range() happy. + +Signed-off-by: Joerg Roedel +--- + arch/x86/include/asm/pgtable.h | 49 +++++++++++++++++++++++++++++++++++++++ + arch/x86/include/asm/pgtable_64.h | 49 --------------------------------------- + 2 files changed, 49 insertions(+), 49 deletions(-) + +diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h +index e42b8943cb1a..0a9f746cbdc1 100644 +--- a/arch/x86/include/asm/pgtable.h ++++ b/arch/x86/include/asm/pgtable.h +@@ -1109,6 +1109,55 @@ static inline int pud_write(pud_t pud) + return pud_flags(pud) & _PAGE_RW; + } + ++#ifdef CONFIG_PAGE_TABLE_ISOLATION ++/* ++ * All top-level PAGE_TABLE_ISOLATION page tables are order-1 pages ++ * (8k-aligned and 8k in size). The kernel one is at the beginning 4k and ++ * the user one is in the last 4k. To switch between them, you ++ * just need to flip the 12th bit in their addresses. ++ */ ++#define PTI_PGTABLE_SWITCH_BIT PAGE_SHIFT ++ ++/* ++ * This generates better code than the inline assembly in ++ * __set_bit(). ++ */ ++static inline void *ptr_set_bit(void *ptr, int bit) ++{ ++ unsigned long __ptr = (unsigned long)ptr; ++ ++ __ptr |= BIT(bit); ++ return (void *)__ptr; ++} ++static inline void *ptr_clear_bit(void *ptr, int bit) ++{ ++ unsigned long __ptr = (unsigned long)ptr; ++ ++ __ptr &= ~BIT(bit); ++ return (void *)__ptr; ++} ++ ++static inline pgd_t *kernel_to_user_pgdp(pgd_t *pgdp) ++{ ++ return ptr_set_bit(pgdp, PTI_PGTABLE_SWITCH_BIT); ++} ++ ++static inline pgd_t *user_to_kernel_pgdp(pgd_t *pgdp) ++{ ++ return ptr_clear_bit(pgdp, PTI_PGTABLE_SWITCH_BIT); ++} ++ ++static inline p4d_t *kernel_to_user_p4dp(p4d_t *p4dp) ++{ ++ return ptr_set_bit(p4dp, PTI_PGTABLE_SWITCH_BIT); ++} ++ ++static inline p4d_t *user_to_kernel_p4dp(p4d_t *p4dp) ++{ ++ return ptr_clear_bit(p4dp, PTI_PGTABLE_SWITCH_BIT); ++} ++#endif /* CONFIG_PAGE_TABLE_ISOLATION */ ++ + /* + * clone_pgd_range(pgd_t *dst, pgd_t *src, int count); + * +diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h +index b68bda56db67..5e680838761d 100644 +--- a/arch/x86/include/asm/pgtable_64.h ++++ b/arch/x86/include/asm/pgtable_64.h +@@ -131,55 +131,6 @@ static inline pud_t native_pudp_get_and_clear(pud_t *xp) + #endif + } + +-#ifdef CONFIG_PAGE_TABLE_ISOLATION +-/* +- * All top-level PAGE_TABLE_ISOLATION page tables are order-1 pages +- * (8k-aligned and 8k in size). The kernel one is at the beginning 4k and +- * the user one is in the last 4k. To switch between them, you +- * just need to flip the 12th bit in their addresses. +- */ +-#define PTI_PGTABLE_SWITCH_BIT PAGE_SHIFT +- +-/* +- * This generates better code than the inline assembly in +- * __set_bit(). +- */ +-static inline void *ptr_set_bit(void *ptr, int bit) +-{ +- unsigned long __ptr = (unsigned long)ptr; +- +- __ptr |= BIT(bit); +- return (void *)__ptr; +-} +-static inline void *ptr_clear_bit(void *ptr, int bit) +-{ +- unsigned long __ptr = (unsigned long)ptr; +- +- __ptr &= ~BIT(bit); +- return (void *)__ptr; +-} +- +-static inline pgd_t *kernel_to_user_pgdp(pgd_t *pgdp) +-{ +- return ptr_set_bit(pgdp, PTI_PGTABLE_SWITCH_BIT); +-} +- +-static inline pgd_t *user_to_kernel_pgdp(pgd_t *pgdp) +-{ +- return ptr_clear_bit(pgdp, PTI_PGTABLE_SWITCH_BIT); +-} +- +-static inline p4d_t *kernel_to_user_p4dp(p4d_t *p4dp) +-{ +- return ptr_set_bit(p4dp, PTI_PGTABLE_SWITCH_BIT); +-} +- +-static inline p4d_t *user_to_kernel_p4dp(p4d_t *p4dp) +-{ +- return ptr_clear_bit(p4dp, PTI_PGTABLE_SWITCH_BIT); +-} +-#endif /* CONFIG_PAGE_TABLE_ISOLATION */ +- + /* + * Page table pages are page-aligned. The lower half of the top + * level is used for userspace and the top half for the kernel. +-- +2.16.2 + diff --git a/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0019-x86-pgtable-Move-pti_set_user_pgtbl-to-pgtable.h.patch b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0019-x86-pgtable-Move-pti_set_user_pgtbl-to-pgtable.h.patch new file mode 100644 index 00000000..f7ccdc80 --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0019-x86-pgtable-Move-pti_set_user_pgtbl-to-pgtable.h.patch @@ -0,0 +1,84 @@ +From 88eb961770b7b265bf4725f0d687af8c9cf33467 Mon Sep 17 00:00:00 2001 +From: Joerg Roedel +Date: Tue, 16 Jan 2018 15:50:39 +0100 +Subject: [PATCH 19/34] x86/pgtable: Move pti_set_user_pgtbl() to pgtable.h + +There it is also usable from 32 bit code. + +Signed-off-by: Joerg Roedel +--- + arch/x86/include/asm/pgtable.h | 23 +++++++++++++++++++++++ + arch/x86/include/asm/pgtable_64.h | 21 --------------------- + 2 files changed, 23 insertions(+), 21 deletions(-) + +diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h +index 0a9f746cbdc1..1e900c1f8ab1 100644 +--- a/arch/x86/include/asm/pgtable.h ++++ b/arch/x86/include/asm/pgtable.h +@@ -618,8 +618,31 @@ static inline int is_new_memtype_allowed(u64 paddr, unsigned long size, + + pmd_t *populate_extra_pmd(unsigned long vaddr); + pte_t *populate_extra_pte(unsigned long vaddr); ++ ++#ifdef CONFIG_PAGE_TABLE_ISOLATION ++pgd_t __pti_set_user_pgtbl(pgd_t *pgdp, pgd_t pgd); ++ ++/* ++ * Take a PGD location (pgdp) and a pgd value that needs to be set there. ++ * Populates the user and returns the resulting PGD that must be set in ++ * the kernel copy of the page tables. ++ */ ++static inline pgd_t pti_set_user_pgtbl(pgd_t *pgdp, pgd_t pgd) ++{ ++ if (!static_cpu_has(X86_FEATURE_PTI)) ++ return pgd; ++ return __pti_set_user_pgtbl(pgdp, pgd); ++} ++#else /* CONFIG_PAGE_TABLE_ISOLATION */ ++static inline pgd_t pti_set_user_pgtbl(pgd_t *pgdp, pgd_t pgd) ++{ ++ return pgd; ++} ++#endif /* CONFIG_PAGE_TABLE_ISOLATION */ ++ + #endif /* __ASSEMBLY__ */ + ++ + #ifdef CONFIG_X86_32 + # include + #else +diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h +index 5e680838761d..4cbf5173dd76 100644 +--- a/arch/x86/include/asm/pgtable_64.h ++++ b/arch/x86/include/asm/pgtable_64.h +@@ -145,27 +145,6 @@ static inline bool pgdp_maps_userspace(void *__ptr) + return (ptr & ~PAGE_MASK) < (PAGE_SIZE / 2); + } + +-#ifdef CONFIG_PAGE_TABLE_ISOLATION +-pgd_t __pti_set_user_pgtbl(pgd_t *pgdp, pgd_t pgd); +- +-/* +- * Take a PGD location (pgdp) and a pgd value that needs to be set there. +- * Populates the user and returns the resulting PGD that must be set in +- * the kernel copy of the page tables. +- */ +-static inline pgd_t pti_set_user_pgtbl(pgd_t *pgdp, pgd_t pgd) +-{ +- if (!static_cpu_has(X86_FEATURE_PTI)) +- return pgd; +- return __pti_set_user_pgtbl(pgdp, pgd); +-} +-#else +-static inline pgd_t pti_set_user_pgtbl(pgd_t *pgdp, pgd_t pgd) +-{ +- return pgd; +-} +-#endif +- + static inline void native_set_p4d(p4d_t *p4dp, p4d_t p4d) + { + #if defined(CONFIG_PAGE_TABLE_ISOLATION) && !defined(CONFIG_X86_5LEVEL) +-- +2.16.2 + diff --git a/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0020-x86-pgtable-Move-two-more-functions-from-pgtable_64..patch b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0020-x86-pgtable-Move-two-more-functions-from-pgtable_64..patch new file mode 100644 index 00000000..419f6fe9 --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0020-x86-pgtable-Move-two-more-functions-from-pgtable_64..patch @@ -0,0 +1,120 @@ +From 2bcb4034a5d3e49213d4b7e72187b106a50d53f3 Mon Sep 17 00:00:00 2001 +From: Joerg Roedel +Date: Tue, 16 Jan 2018 12:48:14 +0100 +Subject: [PATCH 20/34] x86/pgtable: Move two more functions from pgtable_64.h + to pgtable.h + +These two functions are required for PTI on 32 bit: + + * pgdp_maps_userspace() + * pgd_large() + +Also re-implement pgdp_maps_userspace() so that it will work +on 64 and 32 bit kernels. + +Signed-off-by: Joerg Roedel +--- + arch/x86/include/asm/pgtable-2level_types.h | 3 +++ + arch/x86/include/asm/pgtable-3level_types.h | 1 + + arch/x86/include/asm/pgtable.h | 16 ++++++++++++++++ + arch/x86/include/asm/pgtable_64.h | 15 --------------- + arch/x86/include/asm/pgtable_64_types.h | 2 ++ + 5 files changed, 22 insertions(+), 15 deletions(-) + +diff --git a/arch/x86/include/asm/pgtable-2level_types.h b/arch/x86/include/asm/pgtable-2level_types.h +index f982ef808e7e..6deb6cd236e3 100644 +--- a/arch/x86/include/asm/pgtable-2level_types.h ++++ b/arch/x86/include/asm/pgtable-2level_types.h +@@ -35,4 +35,7 @@ typedef union { + + #define PTRS_PER_PTE 1024 + ++/* This covers all VMSPLIT_* and VMSPLIT_*_OPT variants */ ++#define PGD_KERNEL_START (CONFIG_PAGE_OFFSET >> PGDIR_SHIFT) ++ + #endif /* _ASM_X86_PGTABLE_2LEVEL_DEFS_H */ +diff --git a/arch/x86/include/asm/pgtable-3level_types.h b/arch/x86/include/asm/pgtable-3level_types.h +index ed8a200ecdaf..925ac1bc45cb 100644 +--- a/arch/x86/include/asm/pgtable-3level_types.h ++++ b/arch/x86/include/asm/pgtable-3level_types.h +@@ -45,5 +45,6 @@ typedef union { + */ + #define PTRS_PER_PTE 512 + ++#define PGD_KERNEL_START (CONFIG_PAGE_OFFSET >> PGDIR_SHIFT) + + #endif /* _ASM_X86_PGTABLE_3LEVEL_DEFS_H */ +diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h +index 1e900c1f8ab1..981e49a8cdb2 100644 +--- a/arch/x86/include/asm/pgtable.h ++++ b/arch/x86/include/asm/pgtable.h +@@ -1132,6 +1132,22 @@ static inline int pud_write(pud_t pud) + return pud_flags(pud) & _PAGE_RW; + } + ++/* ++ * Page table pages are page-aligned. The lower half of the top ++ * level is used for userspace and the top half for the kernel. ++ * ++ * Returns true for parts of the PGD that map userspace and ++ * false for the parts that map the kernel. ++ */ ++static inline bool pgdp_maps_userspace(void *__ptr) ++{ ++ unsigned long ptr = (unsigned long)__ptr; ++ ++ return (((ptr & ~PAGE_MASK) / sizeof(pgd_t)) < PGD_KERNEL_START); ++} ++ ++static inline int pgd_large(pgd_t pgd) { return 0; } ++ + #ifdef CONFIG_PAGE_TABLE_ISOLATION + /* + * All top-level PAGE_TABLE_ISOLATION page tables are order-1 pages +diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h +index 4cbf5173dd76..e11b92585de4 100644 +--- a/arch/x86/include/asm/pgtable_64.h ++++ b/arch/x86/include/asm/pgtable_64.h +@@ -131,20 +131,6 @@ static inline pud_t native_pudp_get_and_clear(pud_t *xp) + #endif + } + +-/* +- * Page table pages are page-aligned. The lower half of the top +- * level is used for userspace and the top half for the kernel. +- * +- * Returns true for parts of the PGD that map userspace and +- * false for the parts that map the kernel. +- */ +-static inline bool pgdp_maps_userspace(void *__ptr) +-{ +- unsigned long ptr = (unsigned long)__ptr; +- +- return (ptr & ~PAGE_MASK) < (PAGE_SIZE / 2); +-} +- + static inline void native_set_p4d(p4d_t *p4dp, p4d_t p4d) + { + #if defined(CONFIG_PAGE_TABLE_ISOLATION) && !defined(CONFIG_X86_5LEVEL) +@@ -187,7 +173,6 @@ extern void sync_global_pgds(unsigned long start, unsigned long end); + /* + * Level 4 access. + */ +-static inline int pgd_large(pgd_t pgd) { return 0; } + #define mk_kernel_pgd(address) __pgd((address) | _KERNPG_TABLE) + + /* PUD - Level3 access */ +diff --git a/arch/x86/include/asm/pgtable_64_types.h b/arch/x86/include/asm/pgtable_64_types.h +index 6b8f73dcbc2c..e57003a3f58a 100644 +--- a/arch/x86/include/asm/pgtable_64_types.h ++++ b/arch/x86/include/asm/pgtable_64_types.h +@@ -124,4 +124,6 @@ typedef struct { pteval_t pte; } pte_t; + + #define EARLY_DYNAMIC_PAGE_TABLES 64 + ++#define PGD_KERNEL_START ((PAGE_SIZE / 2) / sizeof(pgd_t)) ++ + #endif /* _ASM_X86_PGTABLE_64_DEFS_H */ +-- +2.16.2 + diff --git a/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0021-x86-mm-pae-Populate-valid-user-PGD-entries.patch b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0021-x86-mm-pae-Populate-valid-user-PGD-entries.patch new file mode 100644 index 00000000..04281249 --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0021-x86-mm-pae-Populate-valid-user-PGD-entries.patch @@ -0,0 +1,73 @@ +From 85228cdba0d4634d6a1a162be0d755bd8ed3bdfa Mon Sep 17 00:00:00 2001 +From: Joerg Roedel +Date: Tue, 16 Jan 2018 15:28:57 +0100 +Subject: [PATCH 21/34] x86/mm/pae: Populate valid user PGD entries + +Generic page-table code populates all non-leaf entries with +_KERNPG_TABLE bits set. This is fine for all paging modes +except PAE. + +In PAE mode only a subset of the bits is allowed to be set. +Make sure we only set allowed bits by masking out the +reserved bits. + +Signed-off-by: Joerg Roedel +--- + arch/x86/include/asm/pgtable_types.h | 28 ++++++++++++++++++++++++++-- + 1 file changed, 26 insertions(+), 2 deletions(-) + +diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h +index 3696398a9475..48fc70b2d044 100644 +--- a/arch/x86/include/asm/pgtable_types.h ++++ b/arch/x86/include/asm/pgtable_types.h +@@ -50,6 +50,7 @@ + #define _PAGE_GLOBAL (_AT(pteval_t, 1) << _PAGE_BIT_GLOBAL) + #define _PAGE_SOFTW1 (_AT(pteval_t, 1) << _PAGE_BIT_SOFTW1) + #define _PAGE_SOFTW2 (_AT(pteval_t, 1) << _PAGE_BIT_SOFTW2) ++#define _PAGE_SOFTW3 (_AT(pteval_t, 1) << _PAGE_BIT_SOFTW3) + #define _PAGE_PAT (_AT(pteval_t, 1) << _PAGE_BIT_PAT) + #define _PAGE_PAT_LARGE (_AT(pteval_t, 1) << _PAGE_BIT_PAT_LARGE) + #define _PAGE_SPECIAL (_AT(pteval_t, 1) << _PAGE_BIT_SPECIAL) +@@ -267,14 +268,37 @@ typedef struct pgprot { pgprotval_t pgprot; } pgprot_t; + + typedef struct { pgdval_t pgd; } pgd_t; + ++#ifdef CONFIG_X86_PAE ++ ++/* ++ * PHYSICAL_PAGE_MASK might be non-constant when SME is compiled in, so we can't ++ * use it here. ++ */ ++ ++#define PGD_PAE_PAGE_MASK ((signed long)PAGE_MASK) ++#define PGD_PAE_PHYS_MASK (((1ULL << __PHYSICAL_MASK_SHIFT)-1) & PGD_PAE_PAGE_MASK) ++ ++/* ++ * PAE allows Base Address, P, PWT, PCD and AVL bits to be set in PGD entries. ++ * All other bits are Reserved MBZ ++ */ ++#define PGD_ALLOWED_BITS (PGD_PAE_PHYS_MASK | _PAGE_PRESENT | \ ++ _PAGE_PWT | _PAGE_PCD | \ ++ _PAGE_SOFTW1 | _PAGE_SOFTW2 | _PAGE_SOFTW3 ) ++ ++#else ++/* No need to mask any bits for !PAE */ ++#define PGD_ALLOWED_BITS (~0ULL) ++#endif ++ + static inline pgd_t native_make_pgd(pgdval_t val) + { +- return (pgd_t) { val }; ++ return (pgd_t) { val & PGD_ALLOWED_BITS }; + } + + static inline pgdval_t native_pgd_val(pgd_t pgd) + { +- return pgd.pgd; ++ return pgd.pgd & PGD_ALLOWED_BITS; + } + + static inline pgdval_t pgd_flags(pgd_t pgd) +-- +2.16.2 + diff --git a/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0022-x86-mm-pae-Populate-the-user-page-table-with-user-pg.patch b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0022-x86-mm-pae-Populate-the-user-page-table-with-user-pg.patch new file mode 100644 index 00000000..02bc60df --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0022-x86-mm-pae-Populate-the-user-page-table-with-user-pg.patch @@ -0,0 +1,42 @@ +From f05eb123abd9d8696ef340e62a37348381ff95fa Mon Sep 17 00:00:00 2001 +From: Joerg Roedel +Date: Tue, 16 Jan 2018 15:55:17 +0100 +Subject: [PATCH 22/34] x86/mm/pae: Populate the user page-table with user + pgd's + +When we populate a PGD entry, make sure we populate it in +the user page-table too. + +Signed-off-by: Joerg Roedel +--- + arch/x86/include/asm/pgtable-3level.h | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/arch/x86/include/asm/pgtable-3level.h b/arch/x86/include/asm/pgtable-3level.h +index bc4af5453802..ab2aa4468293 100644 +--- a/arch/x86/include/asm/pgtable-3level.h ++++ b/arch/x86/include/asm/pgtable-3level.h +@@ -98,6 +98,9 @@ static inline void native_set_pmd(pmd_t *pmdp, pmd_t pmd) + + static inline void native_set_pud(pud_t *pudp, pud_t pud) + { ++#ifdef CONFIG_PAGE_TABLE_ISOLATION ++ pud.p4d.pgd = pti_set_user_pgtbl(&pudp->p4d.pgd, pud.p4d.pgd); ++#endif + set_64bit((unsigned long long *)(pudp), native_pud_val(pud)); + } + +@@ -194,6 +197,10 @@ static inline pud_t native_pudp_get_and_clear(pud_t *pudp) + { + union split_pud res, *orig = (union split_pud *)pudp; + ++#ifdef CONFIG_PAGE_TABLE_ISOLATION ++ pti_set_user_pgtbl(&pudp->p4d.pgd, __pgd(0)); ++#endif ++ + /* xchg acts as a barrier before setting of the high bits */ + res.pud_low = xchg(&orig->pud_low, 0); + res.pud_high = orig->pud_high; +-- +2.16.2 + diff --git a/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0023-x86-mm-legacy-Populate-the-user-page-table-with-user.patch b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0023-x86-mm-legacy-Populate-the-user-page-table-with-user.patch new file mode 100644 index 00000000..50bb46d8 --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0023-x86-mm-legacy-Populate-the-user-page-table-with-user.patch @@ -0,0 +1,50 @@ +From 08a22d9c7b62e9c9e08eaf9508f3ef881768a636 Mon Sep 17 00:00:00 2001 +From: Joerg Roedel +Date: Tue, 16 Jan 2018 16:29:13 +0100 +Subject: [PATCH 23/34] x86/mm/legacy: Populate the user page-table with user + pgd's + +Also populate the user-spage pgd's in the user page-table. + +Signed-off-by: Joerg Roedel +--- + arch/x86/include/asm/pgtable-2level.h | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/arch/x86/include/asm/pgtable-2level.h b/arch/x86/include/asm/pgtable-2level.h +index 685ffe8a0eaf..c399ea5eea41 100644 +--- a/arch/x86/include/asm/pgtable-2level.h ++++ b/arch/x86/include/asm/pgtable-2level.h +@@ -19,6 +19,9 @@ static inline void native_set_pte(pte_t *ptep , pte_t pte) + + static inline void native_set_pmd(pmd_t *pmdp, pmd_t pmd) + { ++#ifdef CONFIG_PAGE_TABLE_ISOLATION ++ pmd.pud.p4d.pgd = pti_set_user_pgtbl(&pmdp->pud.p4d.pgd, pmd.pud.p4d.pgd); ++#endif + *pmdp = pmd; + } + +@@ -58,6 +61,9 @@ static inline pte_t native_ptep_get_and_clear(pte_t *xp) + #ifdef CONFIG_SMP + static inline pmd_t native_pmdp_get_and_clear(pmd_t *xp) + { ++#ifdef CONFIG_PAGE_TABLE_ISOLATION ++ pti_set_user_pgtbl(&xp->pud.p4d.pgd, __pgd(0)); ++#endif + return __pmd(xchg((pmdval_t *)xp, 0)); + } + #else +@@ -67,6 +73,9 @@ static inline pmd_t native_pmdp_get_and_clear(pmd_t *xp) + #ifdef CONFIG_SMP + static inline pud_t native_pudp_get_and_clear(pud_t *xp) + { ++#ifdef CONFIG_PAGE_TABLE_ISOLATION ++ pti_set_user_pgtbl(&xp->p4d.pgd, __pgd(0)); ++#endif + return __pud(xchg((pudval_t *)xp, 0)); + } + #else +-- +2.16.2 + diff --git a/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0024-x86-mm-pti-Add-an-overflow-check-to-pti_clone_pmds.patch b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0024-x86-mm-pti-Add-an-overflow-check-to-pti_clone_pmds.patch new file mode 100644 index 00000000..3619c152 --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0024-x86-mm-pti-Add-an-overflow-check-to-pti_clone_pmds.patch @@ -0,0 +1,33 @@ +From 9fb9b9305a94eb64cd9bfc007d0457aa16a3429c Mon Sep 17 00:00:00 2001 +From: Joerg Roedel +Date: Tue, 16 Jan 2018 16:23:52 +0100 +Subject: [PATCH 24/34] x86/mm/pti: Add an overflow check to pti_clone_pmds() + +The addr counter will overflow if we clone the last PMD of +the address space, resulting in an endless loop. + +Check for that and bail out of the loop when it happens. + +Signed-off-by: Joerg Roedel +--- + arch/x86/mm/pti.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/arch/x86/mm/pti.c b/arch/x86/mm/pti.c +index 8f53d2101f64..96a690e6c9b1 100644 +--- a/arch/x86/mm/pti.c ++++ b/arch/x86/mm/pti.c +@@ -282,6 +282,10 @@ pti_clone_pmds(unsigned long start, unsigned long end, pmdval_t clear) + p4d_t *p4d; + pud_t *pud; + ++ /* Overflow check */ ++ if (addr < start) ++ break; ++ + pgd = pgd_offset_k(addr); + if (WARN_ON(pgd_none(*pgd))) + return; +-- +2.16.2 + diff --git a/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0025-x86-mm-pti-Define-X86_CR3_PTI_PCID_USER_BIT-on-x86_3.patch b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0025-x86-mm-pti-Define-X86_CR3_PTI_PCID_USER_BIT-on-x86_3.patch new file mode 100644 index 00000000..b927eac1 --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0025-x86-mm-pti-Define-X86_CR3_PTI_PCID_USER_BIT-on-x86_3.patch @@ -0,0 +1,41 @@ +From b4c87612168011f7e95681027bf1de290da8d668 Mon Sep 17 00:00:00 2001 +From: Joerg Roedel +Date: Tue, 16 Jan 2018 11:35:19 +0100 +Subject: [PATCH 25/34] x86/mm/pti: Define X86_CR3_PTI_PCID_USER_BIT on x86_32 + +Move it out of the X86_64 specific processor defines so +that its visible for 32bit too. + +Reviewed-by: Andy Lutomirski +Signed-off-by: Joerg Roedel +--- + arch/x86/include/asm/processor-flags.h | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/arch/x86/include/asm/processor-flags.h b/arch/x86/include/asm/processor-flags.h +index 625a52a5594f..02c2cbda4a74 100644 +--- a/arch/x86/include/asm/processor-flags.h ++++ b/arch/x86/include/asm/processor-flags.h +@@ -39,10 +39,6 @@ + #define CR3_PCID_MASK 0xFFFull + #define CR3_NOFLUSH BIT_ULL(63) + +-#ifdef CONFIG_PAGE_TABLE_ISOLATION +-# define X86_CR3_PTI_PCID_USER_BIT 11 +-#endif +- + #else + /* + * CR3_ADDR_MASK needs at least bits 31:5 set on PAE systems, and we save +@@ -53,4 +49,8 @@ + #define CR3_NOFLUSH 0 + #endif + ++#ifdef CONFIG_PAGE_TABLE_ISOLATION ++# define X86_CR3_PTI_PCID_USER_BIT 11 ++#endif ++ + #endif /* _ASM_X86_PROCESSOR_FLAGS_H */ +-- +2.16.2 + diff --git a/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0026-x86-mm-pti-Clone-CPU_ENTRY_AREA-on-PMD-level-on-x86_.patch b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0026-x86-mm-pti-Clone-CPU_ENTRY_AREA-on-PMD-level-on-x86_.patch new file mode 100644 index 00000000..26d863cf --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0026-x86-mm-pti-Clone-CPU_ENTRY_AREA-on-PMD-level-on-x86_.patch @@ -0,0 +1,56 @@ +From c3b8f5b6bbb097409895ea8e00042034408cac54 Mon Sep 17 00:00:00 2001 +From: Joerg Roedel +Date: Tue, 16 Jan 2018 14:13:04 +0100 +Subject: [PATCH 26/34] x86/mm/pti: Clone CPU_ENTRY_AREA on PMD level on x86_32 + +Cloning on the P4D level would clone the complete kernel +address space into the user-space page-tables for PAE +kernels. Cloning on PMD level is fine for PAE and legacy +paging. + +Signed-off-by: Joerg Roedel +--- + arch/x86/mm/pti.c | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +diff --git a/arch/x86/mm/pti.c b/arch/x86/mm/pti.c +index 96a690e6c9b1..3ffd92309aca 100644 +--- a/arch/x86/mm/pti.c ++++ b/arch/x86/mm/pti.c +@@ -312,6 +312,7 @@ pti_clone_pmds(unsigned long start, unsigned long end, pmdval_t clear) + } + } + ++#ifdef CONFIG_X86_64 + /* + * Clone a single p4d (i.e. a top-level entry on 4-level systems and a + * next-level entry on 5-level systems. +@@ -335,6 +336,25 @@ static void __init pti_clone_user_shared(void) + pti_clone_p4d(CPU_ENTRY_AREA_BASE); + } + ++#else /* CONFIG_X86_64 */ ++ ++/* ++ * On 32 bit PAE systems with 1GB of Kernel address space there is only ++ * one pgd/p4d for the whole kernel. Cloning that would map the whole ++ * address space into the user page-tables, making PTI useless. So clone ++ * the page-table on the PMD level to prevent that. ++ */ ++static void __init pti_clone_user_shared(void) ++{ ++ unsigned long start, end; ++ ++ start = CPU_ENTRY_AREA_BASE; ++ end = start + (PAGE_SIZE * CPU_ENTRY_AREA_PAGES); ++ ++ pti_clone_pmds(start, end, _PAGE_GLOBAL); ++} ++#endif /* CONFIG_X86_64 */ ++ + /* + * Clone the ESPFIX P4D into the user space visinble page table + */ +-- +2.16.2 + diff --git a/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0027-x86-mm-dump_pagetables-Define-INIT_PGD.patch b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0027-x86-mm-dump_pagetables-Define-INIT_PGD.patch new file mode 100644 index 00000000..bf454270 --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0027-x86-mm-dump_pagetables-Define-INIT_PGD.patch @@ -0,0 +1,61 @@ +From 35f7b44b3ce2d5b4c4fe2fabb8905bfff44559d4 Mon Sep 17 00:00:00 2001 +From: Joerg Roedel +Date: Thu, 8 Feb 2018 09:11:57 +0100 +Subject: [PATCH 27/34] x86/mm/dump_pagetables: Define INIT_PGD + +Define INIT_PGD to point to the correct initial page-table +for 32 and 64 bit and use it where needed. This fixes the +build on 32 bit with CONFIG_PAGE_TABLE_ISOLATION enabled. + +Signed-off-by: Joerg Roedel +--- + arch/x86/mm/dump_pagetables.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/arch/x86/mm/dump_pagetables.c b/arch/x86/mm/dump_pagetables.c +index 2a4849e92831..2151ebb6a282 100644 +--- a/arch/x86/mm/dump_pagetables.c ++++ b/arch/x86/mm/dump_pagetables.c +@@ -105,6 +105,8 @@ static struct addr_marker address_markers[] = { + [END_OF_SPACE_NR] = { -1, NULL } + }; + ++#define INIT_PGD ((pgd_t *) &init_top_pgt) ++ + #else /* CONFIG_X86_64 */ + + enum address_markers_idx { +@@ -133,6 +135,8 @@ static struct addr_marker address_markers[] = { + [END_OF_SPACE_NR] = { -1, NULL } + }; + ++#define INIT_PGD (swapper_pg_dir) ++ + #endif /* !CONFIG_X86_64 */ + + /* Multipliers for offsets within the PTEs */ +@@ -478,11 +482,7 @@ static inline bool is_hypervisor_range(int idx) + static void ptdump_walk_pgd_level_core(struct seq_file *m, pgd_t *pgd, + bool checkwx, bool dmesg) + { +-#ifdef CONFIG_X86_64 +- pgd_t *start = (pgd_t *) &init_top_pgt; +-#else +- pgd_t *start = swapper_pg_dir; +-#endif ++ pgd_t *start = INIT_PGD; + pgprotval_t prot; + int i; + struct pg_state st = {}; +@@ -543,7 +543,7 @@ EXPORT_SYMBOL_GPL(ptdump_walk_pgd_level_debugfs); + static void ptdump_walk_user_pgd_level_checkwx(void) + { + #ifdef CONFIG_PAGE_TABLE_ISOLATION +- pgd_t *pgd = (pgd_t *) &init_top_pgt; ++ pgd_t *pgd = INIT_PGD; + + if (!static_cpu_has(X86_FEATURE_PTI)) + return; +-- +2.16.2 + diff --git a/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0028-x86-pgtable-pae-Use-separate-kernel-PMDs-for-user-pa.patch b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0028-x86-pgtable-pae-Use-separate-kernel-PMDs-for-user-pa.patch new file mode 100644 index 00000000..48d3ba08 --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0028-x86-pgtable-pae-Use-separate-kernel-PMDs-for-user-pa.patch @@ -0,0 +1,213 @@ +From c15cbcd9bc3d2e8aaecffc5053dbcf382fe6e56d Mon Sep 17 00:00:00 2001 +From: Joerg Roedel +Date: Wed, 7 Feb 2018 15:37:52 +0100 +Subject: [PATCH 28/34] x86/pgtable/pae: Use separate kernel PMDs for user + page-table + +We need separate kernel PMDs in the user page-table when PTI +is enabled to map the per-process LDT for user-space. + +Signed-off-by: Joerg Roedel +--- + arch/x86/mm/pgtable.c | 100 ++++++++++++++++++++++++++++++++++++++++---------- + 1 file changed, 81 insertions(+), 19 deletions(-) + +diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c +index a81d42e48922..d95bc7b1ffb4 100644 +--- a/arch/x86/mm/pgtable.c ++++ b/arch/x86/mm/pgtable.c +@@ -177,6 +177,14 @@ static void pgd_dtor(pgd_t *pgd) + */ + #define PREALLOCATED_PMDS UNSHARED_PTRS_PER_PGD + ++/* ++ * We allocate separate PMDs for the kernel part of the user page-table ++ * when PTI is enabled. We need them to map the per-process LDT into the ++ * user-space page-table. ++ */ ++#define PREALLOCATED_USER_PMDS (static_cpu_has(X86_FEATURE_PTI) ? \ ++ KERNEL_PGD_PTRS : 0) ++ + void pud_populate(struct mm_struct *mm, pud_t *pudp, pmd_t *pmd) + { + paravirt_alloc_pmd(mm, __pa(pmd) >> PAGE_SHIFT); +@@ -197,14 +205,14 @@ void pud_populate(struct mm_struct *mm, pud_t *pudp, pmd_t *pmd) + + /* No need to prepopulate any pagetable entries in non-PAE modes. */ + #define PREALLOCATED_PMDS 0 +- ++#define PREALLOCATED_USER_PMDS 0 + #endif /* CONFIG_X86_PAE */ + +-static void free_pmds(struct mm_struct *mm, pmd_t *pmds[]) ++static void free_pmds(struct mm_struct *mm, pmd_t *pmds[], int count) + { + int i; + +- for(i = 0; i < PREALLOCATED_PMDS; i++) ++ for(i = 0; i < count; i++) + if (pmds[i]) { + pgtable_pmd_page_dtor(virt_to_page(pmds[i])); + free_page((unsigned long)pmds[i]); +@@ -212,7 +220,7 @@ static void free_pmds(struct mm_struct *mm, pmd_t *pmds[]) + } + } + +-static int preallocate_pmds(struct mm_struct *mm, pmd_t *pmds[]) ++static int preallocate_pmds(struct mm_struct *mm, pmd_t *pmds[], int count) + { + int i; + bool failed = false; +@@ -221,7 +229,7 @@ static int preallocate_pmds(struct mm_struct *mm, pmd_t *pmds[]) + if (mm == &init_mm) + gfp &= ~__GFP_ACCOUNT; + +- for(i = 0; i < PREALLOCATED_PMDS; i++) { ++ for(i = 0; i < count; i++) { + pmd_t *pmd = (pmd_t *)__get_free_page(gfp); + if (!pmd) + failed = true; +@@ -236,7 +244,7 @@ static int preallocate_pmds(struct mm_struct *mm, pmd_t *pmds[]) + } + + if (failed) { +- free_pmds(mm, pmds); ++ free_pmds(mm, pmds, count); + return -ENOMEM; + } + +@@ -249,23 +257,38 @@ static int preallocate_pmds(struct mm_struct *mm, pmd_t *pmds[]) + * preallocate which never got a corresponding vma will need to be + * freed manually. + */ ++static void mop_up_one_pmd(struct mm_struct *mm, pgd_t *pgdp) ++{ ++ pgd_t pgd = *pgdp; ++ ++ if (pgd_val(pgd) != 0) { ++ pmd_t *pmd = (pmd_t *)pgd_page_vaddr(pgd); ++ ++ *pgdp = native_make_pgd(0); ++ ++ paravirt_release_pmd(pgd_val(pgd) >> PAGE_SHIFT); ++ pmd_free(mm, pmd); ++ mm_dec_nr_pmds(mm); ++ } ++} ++ + static void pgd_mop_up_pmds(struct mm_struct *mm, pgd_t *pgdp) + { + int i; + +- for(i = 0; i < PREALLOCATED_PMDS; i++) { +- pgd_t pgd = pgdp[i]; ++ for(i = 0; i < PREALLOCATED_PMDS; i++) ++ mop_up_one_pmd(mm, &pgdp[i]); + +- if (pgd_val(pgd) != 0) { +- pmd_t *pmd = (pmd_t *)pgd_page_vaddr(pgd); ++#ifdef CONFIG_PAGE_TABLE_ISOLATION + +- pgdp[i] = native_make_pgd(0); ++ if (!static_cpu_has(X86_FEATURE_PTI)) ++ return; + +- paravirt_release_pmd(pgd_val(pgd) >> PAGE_SHIFT); +- pmd_free(mm, pmd); +- mm_dec_nr_pmds(mm); +- } +- } ++ pgdp = kernel_to_user_pgdp(pgdp); ++ ++ for (i = 0; i < PREALLOCATED_USER_PMDS; i++) ++ mop_up_one_pmd(mm, &pgdp[i + KERNEL_PGD_BOUNDARY]); ++#endif + } + + static void pgd_prepopulate_pmd(struct mm_struct *mm, pgd_t *pgd, pmd_t *pmds[]) +@@ -291,6 +314,38 @@ static void pgd_prepopulate_pmd(struct mm_struct *mm, pgd_t *pgd, pmd_t *pmds[]) + } + } + ++#ifdef CONFIG_PAGE_TABLE_ISOLATION ++static void pgd_prepopulate_user_pmd(struct mm_struct *mm, ++ pgd_t *k_pgd, pmd_t *pmds[]) ++{ ++ pgd_t *s_pgd = kernel_to_user_pgdp(swapper_pg_dir); ++ pgd_t *u_pgd = kernel_to_user_pgdp(k_pgd); ++ p4d_t *u_p4d; ++ pud_t *u_pud; ++ int i; ++ ++ u_p4d = p4d_offset(u_pgd, 0); ++ u_pud = pud_offset(u_p4d, 0); ++ ++ s_pgd += KERNEL_PGD_BOUNDARY; ++ u_pud += KERNEL_PGD_BOUNDARY; ++ ++ for (i = 0; i < PREALLOCATED_USER_PMDS; i++, u_pud++, s_pgd++) { ++ pmd_t *pmd = pmds[i]; ++ ++ memcpy(pmd, (pmd_t *)pgd_page_vaddr(*s_pgd), ++ sizeof(pmd_t) * PTRS_PER_PMD); ++ ++ pud_populate(mm, u_pud, pmd); ++ } ++ ++} ++#else ++static void pgd_prepopulate_user_pmd(struct mm_struct *mm, ++ pgd_t *k_pgd, pmd_t *pmds[]) ++{ ++} ++#endif + /* + * Xen paravirt assumes pgd table should be in one page. 64 bit kernel also + * assumes that pgd should be in one page. +@@ -371,6 +426,7 @@ static inline void _pgd_free(pgd_t *pgd) + pgd_t *pgd_alloc(struct mm_struct *mm) + { + pgd_t *pgd; ++ pmd_t *u_pmds[PREALLOCATED_USER_PMDS]; + pmd_t *pmds[PREALLOCATED_PMDS]; + + pgd = _pgd_alloc(); +@@ -380,12 +436,15 @@ pgd_t *pgd_alloc(struct mm_struct *mm) + + mm->pgd = pgd; + +- if (preallocate_pmds(mm, pmds) != 0) ++ if (preallocate_pmds(mm, pmds, PREALLOCATED_PMDS) != 0) + goto out_free_pgd; + +- if (paravirt_pgd_alloc(mm) != 0) ++ if (preallocate_pmds(mm, u_pmds, PREALLOCATED_USER_PMDS) != 0) + goto out_free_pmds; + ++ if (paravirt_pgd_alloc(mm) != 0) ++ goto out_free_user_pmds; ++ + /* + * Make sure that pre-populating the pmds is atomic with + * respect to anything walking the pgd_list, so that they +@@ -395,13 +454,16 @@ pgd_t *pgd_alloc(struct mm_struct *mm) + + pgd_ctor(mm, pgd); + pgd_prepopulate_pmd(mm, pgd, pmds); ++ pgd_prepopulate_user_pmd(mm, pgd, u_pmds); + + spin_unlock(&pgd_lock); + + return pgd; + ++out_free_user_pmds: ++ free_pmds(mm, u_pmds, PREALLOCATED_USER_PMDS); + out_free_pmds: +- free_pmds(mm, pmds); ++ free_pmds(mm, pmds, PREALLOCATED_PMDS); + out_free_pgd: + _pgd_free(pgd); + out: +-- +2.16.2 + diff --git a/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0029-x86-ldt-Reserve-address-space-range-on-32-bit-for-th.patch b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0029-x86-ldt-Reserve-address-space-range-on-32-bit-for-th.patch new file mode 100644 index 00000000..28f11c02 --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0029-x86-ldt-Reserve-address-space-range-on-32-bit-for-th.patch @@ -0,0 +1,75 @@ +From dd247e8ec4d2eeefdcb6ad173f1eef8007f54101 Mon Sep 17 00:00:00 2001 +From: Joerg Roedel +Date: Tue, 16 Jan 2018 12:40:07 +0100 +Subject: [PATCH 29/34] x86/ldt: Reserve address-space range on 32 bit for the + LDT + +Reserve 2MB/4MB of address-space for mapping the LDT to +user-space on 32 bit PTI kernels. + +Signed-off-by: Joerg Roedel +--- + arch/x86/include/asm/pgtable_32_types.h | 7 +++++-- + arch/x86/mm/dump_pagetables.c | 9 +++++++++ + 2 files changed, 14 insertions(+), 2 deletions(-) + +diff --git a/arch/x86/include/asm/pgtable_32_types.h b/arch/x86/include/asm/pgtable_32_types.h +index 0777e18a1d23..eb2e97afb27d 100644 +--- a/arch/x86/include/asm/pgtable_32_types.h ++++ b/arch/x86/include/asm/pgtable_32_types.h +@@ -48,13 +48,16 @@ extern bool __vmalloc_start_set; /* set once high_memory is set */ + ((FIXADDR_TOT_START - PAGE_SIZE * (CPU_ENTRY_AREA_PAGES + 1)) \ + & PMD_MASK) + +-#define PKMAP_BASE \ ++#define LDT_BASE_ADDR \ + ((CPU_ENTRY_AREA_BASE - PAGE_SIZE) & PMD_MASK) + ++#define PKMAP_BASE \ ++ ((LDT_BASE_ADDR - PAGE_SIZE) & PMD_MASK) ++ + #ifdef CONFIG_HIGHMEM + # define VMALLOC_END (PKMAP_BASE - 2 * PAGE_SIZE) + #else +-# define VMALLOC_END (CPU_ENTRY_AREA_BASE - 2 * PAGE_SIZE) ++# define VMALLOC_END (LDT_BASE_ADDR - 2 * PAGE_SIZE) + #endif + + #define MODULES_VADDR VMALLOC_START +diff --git a/arch/x86/mm/dump_pagetables.c b/arch/x86/mm/dump_pagetables.c +index 2151ebb6a282..fdefdf05739c 100644 +--- a/arch/x86/mm/dump_pagetables.c ++++ b/arch/x86/mm/dump_pagetables.c +@@ -116,6 +116,9 @@ enum address_markers_idx { + VMALLOC_END_NR, + #ifdef CONFIG_HIGHMEM + PKMAP_BASE_NR, ++#endif ++#ifdef CONFIG_MODIFY_LDT_SYSCALL ++ LDT_NR, + #endif + CPU_ENTRY_AREA_NR, + FIXADDR_START_NR, +@@ -129,6 +132,9 @@ static struct addr_marker address_markers[] = { + [VMALLOC_END_NR] = { 0UL, "vmalloc() End" }, + #ifdef CONFIG_HIGHMEM + [PKMAP_BASE_NR] = { 0UL, "Persistent kmap() Area" }, ++#endif ++#ifdef CONFIG_MODIFY_LDT_SYSCALL ++ [LDT_NR] = { 0UL, "LDT remap" }, + #endif + [CPU_ENTRY_AREA_NR] = { 0UL, "CPU entry area" }, + [FIXADDR_START_NR] = { 0UL, "Fixmap area" }, +@@ -579,6 +585,9 @@ static int __init pt_dump_init(void) + # endif + address_markers[FIXADDR_START_NR].start_address = FIXADDR_START; + address_markers[CPU_ENTRY_AREA_NR].start_address = CPU_ENTRY_AREA_BASE; ++# ifdef CONFIG_MODIFY_LDT_SYSCALL ++ address_markers[LDT_NR].start_address = LDT_BASE_ADDR; ++# endif + #endif + return 0; + } +-- +2.16.2 + diff --git a/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0030-x86-ldt-Define-LDT_END_ADDR.patch b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0030-x86-ldt-Define-LDT_END_ADDR.patch new file mode 100644 index 00000000..f6aebd55 --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0030-x86-ldt-Define-LDT_END_ADDR.patch @@ -0,0 +1,64 @@ +From e00857066a9f75a64a00528d451be9899ec7328f Mon Sep 17 00:00:00 2001 +From: Joerg Roedel +Date: Wed, 7 Feb 2018 17:44:44 +0100 +Subject: [PATCH 30/34] x86/ldt: Define LDT_END_ADDR + +It marks the end of the address-space range reserved for the +LDT. The LDT-code will use it when unmapping the LDT for +user-space. + +Signed-off-by: Joerg Roedel +--- + arch/x86/include/asm/pgtable_32_types.h | 2 ++ + arch/x86/include/asm/pgtable_64_types.h | 2 ++ + arch/x86/kernel/ldt.c | 2 +- + 3 files changed, 5 insertions(+), 1 deletion(-) + +diff --git a/arch/x86/include/asm/pgtable_32_types.h b/arch/x86/include/asm/pgtable_32_types.h +index eb2e97afb27d..02bd445d1aee 100644 +--- a/arch/x86/include/asm/pgtable_32_types.h ++++ b/arch/x86/include/asm/pgtable_32_types.h +@@ -51,6 +51,8 @@ extern bool __vmalloc_start_set; /* set once high_memory is set */ + #define LDT_BASE_ADDR \ + ((CPU_ENTRY_AREA_BASE - PAGE_SIZE) & PMD_MASK) + ++#define LDT_END_ADDR (LDT_BASE_ADDR + PMD_SIZE) ++ + #define PKMAP_BASE \ + ((LDT_BASE_ADDR - PAGE_SIZE) & PMD_MASK) + +diff --git a/arch/x86/include/asm/pgtable_64_types.h b/arch/x86/include/asm/pgtable_64_types.h +index e57003a3f58a..15188baa7762 100644 +--- a/arch/x86/include/asm/pgtable_64_types.h ++++ b/arch/x86/include/asm/pgtable_64_types.h +@@ -90,12 +90,14 @@ typedef struct { pteval_t pte; } pte_t; + # define __VMEMMAP_BASE _AC(0xffd4000000000000, UL) + # define LDT_PGD_ENTRY _AC(-112, UL) + # define LDT_BASE_ADDR (LDT_PGD_ENTRY << PGDIR_SHIFT) ++#define LDT_END_ADDR (LDT_BASE_ADDR + PGDIR_SIZE) + #else + # define VMALLOC_SIZE_TB _AC(32, UL) + # define __VMALLOC_BASE _AC(0xffffc90000000000, UL) + # define __VMEMMAP_BASE _AC(0xffffea0000000000, UL) + # define LDT_PGD_ENTRY _AC(-3, UL) + # define LDT_BASE_ADDR (LDT_PGD_ENTRY << PGDIR_SHIFT) ++#define LDT_END_ADDR (LDT_BASE_ADDR + PGDIR_SIZE) + #endif + + #ifdef CONFIG_RANDOMIZE_MEMORY +diff --git a/arch/x86/kernel/ldt.c b/arch/x86/kernel/ldt.c +index 26d713ecad34..f3c2fbf3c458 100644 +--- a/arch/x86/kernel/ldt.c ++++ b/arch/x86/kernel/ldt.c +@@ -202,7 +202,7 @@ static void free_ldt_pgtables(struct mm_struct *mm) + #ifdef CONFIG_PAGE_TABLE_ISOLATION + struct mmu_gather tlb; + unsigned long start = LDT_BASE_ADDR; +- unsigned long end = start + (1UL << PGDIR_SHIFT); ++ unsigned long end = LDT_END_ADDR; + + if (!static_cpu_has(X86_FEATURE_PTI)) + return; +-- +2.16.2 + diff --git a/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0031-x86-ldt-Split-out-sanity-check-in-map_ldt_struct.patch b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0031-x86-ldt-Split-out-sanity-check-in-map_ldt_struct.patch new file mode 100644 index 00000000..14453bad --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0031-x86-ldt-Split-out-sanity-check-in-map_ldt_struct.patch @@ -0,0 +1,146 @@ +From 126ef631acff4fe06d76992f40e04237d7d57344 Mon Sep 17 00:00:00 2001 +From: Joerg Roedel +Date: Wed, 7 Feb 2018 18:02:18 +0100 +Subject: [PATCH 31/34] x86/ldt: Split out sanity check in map_ldt_struct() + +This splits out the mapping sanity check and the actual +mapping of the LDT to user-space from the map_ldt_struct() +function in a way so that it is re-usable for PAE paging. + +Signed-off-by: Joerg Roedel +--- + arch/x86/kernel/ldt.c | 82 ++++++++++++++++++++++++++++++++++++--------------- + 1 file changed, 58 insertions(+), 24 deletions(-) + +diff --git a/arch/x86/kernel/ldt.c b/arch/x86/kernel/ldt.c +index f3c2fbf3c458..8ab7df99c868 100644 +--- a/arch/x86/kernel/ldt.c ++++ b/arch/x86/kernel/ldt.c +@@ -100,6 +100,49 @@ static struct ldt_struct *alloc_ldt_struct(unsigned int num_entries) + return new_ldt; + } + ++#ifdef CONFIG_PAGE_TABLE_ISOLATION ++ ++static void do_sanity_check(struct mm_struct *mm, ++ bool had_kernel_mapping, ++ bool had_user_mapping) ++{ ++ if (mm->context.ldt) { ++ /* ++ * We already had an LDT. The top-level entry should already ++ * have been allocated and synchronized with the usermode ++ * tables. ++ */ ++ WARN_ON(!had_kernel_mapping); ++ if (static_cpu_has(X86_FEATURE_PTI)) ++ WARN_ON(!had_user_mapping); ++ } else { ++ /* ++ * This is the first time we're mapping an LDT for this process. ++ * Sync the pgd to the usermode tables. ++ */ ++ WARN_ON(had_kernel_mapping); ++ if (static_cpu_has(X86_FEATURE_PTI)) ++ WARN_ON(had_user_mapping); ++ } ++} ++ ++static void map_ldt_struct_to_user(struct mm_struct *mm) ++{ ++ pgd_t *pgd = pgd_offset(mm, LDT_BASE_ADDR); ++ ++ if (static_cpu_has(X86_FEATURE_PTI) && !mm->context.ldt) ++ set_pgd(kernel_to_user_pgdp(pgd), *pgd); ++} ++ ++static void sanity_check_ldt_mapping(struct mm_struct *mm) ++{ ++ pgd_t *pgd = pgd_offset(mm, LDT_BASE_ADDR); ++ bool had_kernel = (pgd->pgd != 0); ++ bool had_user = (kernel_to_user_pgdp(pgd)->pgd != 0); ++ ++ do_sanity_check(mm, had_kernel, had_user); ++} ++ + /* + * If PTI is enabled, this maps the LDT into the kernelmode and + * usermode tables for the given mm. +@@ -115,9 +158,8 @@ static struct ldt_struct *alloc_ldt_struct(unsigned int num_entries) + static int + map_ldt_struct(struct mm_struct *mm, struct ldt_struct *ldt, int slot) + { +-#ifdef CONFIG_PAGE_TABLE_ISOLATION +- bool is_vmalloc, had_top_level_entry; + unsigned long va; ++ bool is_vmalloc; + spinlock_t *ptl; + pgd_t *pgd; + int i; +@@ -131,13 +173,15 @@ map_ldt_struct(struct mm_struct *mm, struct ldt_struct *ldt, int slot) + */ + WARN_ON(ldt->slot != -1); + ++ /* Check if the current mappings are sane */ ++ sanity_check_ldt_mapping(mm); ++ + /* + * Did we already have the top level entry allocated? We can't + * use pgd_none() for this because it doens't do anything on + * 4-level page table kernels. + */ + pgd = pgd_offset(mm, LDT_BASE_ADDR); +- had_top_level_entry = (pgd->pgd != 0); + + is_vmalloc = is_vmalloc_addr(ldt->entries); + +@@ -168,35 +212,25 @@ map_ldt_struct(struct mm_struct *mm, struct ldt_struct *ldt, int slot) + pte_unmap_unlock(ptep, ptl); + } + +- if (mm->context.ldt) { +- /* +- * We already had an LDT. The top-level entry should already +- * have been allocated and synchronized with the usermode +- * tables. +- */ +- WARN_ON(!had_top_level_entry); +- if (static_cpu_has(X86_FEATURE_PTI)) +- WARN_ON(!kernel_to_user_pgdp(pgd)->pgd); +- } else { +- /* +- * This is the first time we're mapping an LDT for this process. +- * Sync the pgd to the usermode tables. +- */ +- WARN_ON(had_top_level_entry); +- if (static_cpu_has(X86_FEATURE_PTI)) { +- WARN_ON(kernel_to_user_pgdp(pgd)->pgd); +- set_pgd(kernel_to_user_pgdp(pgd), *pgd); +- } +- } ++ /* Propagate LDT mapping to the user page-table */ ++ map_ldt_struct_to_user(mm); + + va = (unsigned long)ldt_slot_va(slot); + flush_tlb_mm_range(mm, va, va + LDT_SLOT_STRIDE, 0); + + ldt->slot = slot; +-#endif + return 0; + } + ++#else /* !CONFIG_PAGE_TABLE_ISOLATION */ ++ ++static int ++map_ldt_struct(struct mm_struct *mm, struct ldt_struct *ldt, int slot) ++{ ++ return 0; ++} ++#endif /* CONFIG_PAGE_TABLE_ISOLATION */ ++ + static void free_ldt_pgtables(struct mm_struct *mm) + { + #ifdef CONFIG_PAGE_TABLE_ISOLATION +-- +2.16.2 + diff --git a/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0032-x86-ldt-Enable-LDT-user-mapping-for-PAE.patch b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0032-x86-ldt-Enable-LDT-user-mapping-for-PAE.patch new file mode 100644 index 00000000..d1d98bfc --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0032-x86-ldt-Enable-LDT-user-mapping-for-PAE.patch @@ -0,0 +1,107 @@ +From 1d4ac3c5063abdada00ad78e0ccf74c7de4b365d Mon Sep 17 00:00:00 2001 +From: Joerg Roedel +Date: Wed, 7 Feb 2018 18:11:54 +0100 +Subject: [PATCH 32/34] x86/ldt: Enable LDT user-mapping for PAE + +This adds the needed special case for PAE to get the LDT +mapped into the user page-table when PTI is enabled. The big +difference to the other paging modes is that we don't have a +full top-level PGD entry available for the LDT, but only PMD +entry. + +Signed-off-by: Joerg Roedel +--- + arch/x86/include/asm/mmu_context.h | 4 --- + arch/x86/kernel/ldt.c | 53 ++++++++++++++++++++++++++++++++++++++ + 2 files changed, 53 insertions(+), 4 deletions(-) + +diff --git a/arch/x86/include/asm/mmu_context.h b/arch/x86/include/asm/mmu_context.h +index c931b88982a0..af96cfb2ab13 100644 +--- a/arch/x86/include/asm/mmu_context.h ++++ b/arch/x86/include/asm/mmu_context.h +@@ -70,11 +70,7 @@ struct ldt_struct { + + static inline void *ldt_slot_va(int slot) + { +-#ifdef CONFIG_X86_64 + return (void *)(LDT_BASE_ADDR + LDT_SLOT_STRIDE * slot); +-#else +- BUG(); +-#endif + } + + /* +diff --git a/arch/x86/kernel/ldt.c b/arch/x86/kernel/ldt.c +index 8ab7df99c868..778745199d96 100644 +--- a/arch/x86/kernel/ldt.c ++++ b/arch/x86/kernel/ldt.c +@@ -126,6 +126,57 @@ static void do_sanity_check(struct mm_struct *mm, + } + } + ++#ifdef CONFIG_X86_PAE ++ ++static pmd_t *pgd_to_pmd_walk(pgd_t *pgd, unsigned long va) ++{ ++ p4d_t *p4d; ++ pud_t *pud; ++ ++ if (pgd->pgd == 0) ++ return NULL; ++ ++ p4d = p4d_offset(pgd, va); ++ if (p4d_none(*p4d)) ++ return NULL; ++ ++ pud = pud_offset(p4d, va); ++ if (pud_none(*pud)) ++ return NULL; ++ ++ return pmd_offset(pud, va); ++} ++ ++static void map_ldt_struct_to_user(struct mm_struct *mm) ++{ ++ pgd_t *k_pgd = pgd_offset(mm, LDT_BASE_ADDR); ++ pgd_t *u_pgd = kernel_to_user_pgdp(k_pgd); ++ pmd_t *k_pmd, *u_pmd; ++ ++ k_pmd = pgd_to_pmd_walk(k_pgd, LDT_BASE_ADDR); ++ u_pmd = pgd_to_pmd_walk(u_pgd, LDT_BASE_ADDR); ++ ++ if (static_cpu_has(X86_FEATURE_PTI) && !mm->context.ldt) ++ set_pmd(u_pmd, *k_pmd); ++} ++ ++static void sanity_check_ldt_mapping(struct mm_struct *mm) ++{ ++ pgd_t *k_pgd = pgd_offset(mm, LDT_BASE_ADDR); ++ pgd_t *u_pgd = kernel_to_user_pgdp(k_pgd); ++ bool had_kernel, had_user; ++ pmd_t *k_pmd, *u_pmd; ++ ++ k_pmd = pgd_to_pmd_walk(k_pgd, LDT_BASE_ADDR); ++ u_pmd = pgd_to_pmd_walk(u_pgd, LDT_BASE_ADDR); ++ had_kernel = (k_pmd->pmd != 0); ++ had_user = (u_pmd->pmd != 0); ++ ++ do_sanity_check(mm, had_kernel, had_user); ++} ++ ++#else /* !CONFIG_X86_PAE */ ++ + static void map_ldt_struct_to_user(struct mm_struct *mm) + { + pgd_t *pgd = pgd_offset(mm, LDT_BASE_ADDR); +@@ -143,6 +194,8 @@ static void sanity_check_ldt_mapping(struct mm_struct *mm) + do_sanity_check(mm, had_kernel, had_user); + } + ++#endif /* CONFIG_X86_PAE */ ++ + /* + * If PTI is enabled, this maps the LDT into the kernelmode and + * usermode tables for the given mm. +-- +2.16.2 + diff --git a/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0033-x86-pti-Allow-CONFIG_PAGE_TABLE_ISOLATION-for-x86_32.patch b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0033-x86-pti-Allow-CONFIG_PAGE_TABLE_ISOLATION-for-x86_32.patch new file mode 100644 index 00000000..d6842089 --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0033-x86-pti-Allow-CONFIG_PAGE_TABLE_ISOLATION-for-x86_32.patch @@ -0,0 +1,25 @@ +From c15b3c596de19962f32b8aecb5abe56a9455a342 Mon Sep 17 00:00:00 2001 +From: Joerg Roedel +Date: Tue, 16 Jan 2018 11:33:01 +0100 +Subject: [PATCH 33/34] x86/pti: Allow CONFIG_PAGE_TABLE_ISOLATION for x86_32 + +Allow PTI to be compiled on x86_32. + +Signed-off-by: Joerg Roedel +--- + security/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/security/Kconfig b/security/Kconfig +index b0cb9a5f9448..93d85fda0f54 100644 +--- a/security/Kconfig ++++ b/security/Kconfig +@@ -56,7 +56,7 @@ config SECURITY_NETWORK + + config PAGE_TABLE_ISOLATION + bool "Remove the kernel mapping in user mode" +- depends on X86_64 && !UML ++ depends on X86 && !UML + default y + help + This feature reduces the number of hardware side channels by diff --git a/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0034-x86-mm-pti-Add-Warning-when-booting-on-a-PCID-capabl.patch b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0034-x86-mm-pti-Add-Warning-when-booting-on-a-PCID-capabl.patch new file mode 100644 index 00000000..1339d475 --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0034-x86-mm-pti-Add-Warning-when-booting-on-a-PCID-capabl.patch @@ -0,0 +1,45 @@ +From e7591bc0c06694418c773c099f84b79003257069 Mon Sep 17 00:00:00 2001 +From: Joerg Roedel +Date: Mon, 12 Feb 2018 19:47:19 +0100 +Subject: [PATCH 34/34] x86/mm/pti: Add Warning when booting on a PCID capable + CPU + +Warn the user in case the performance can be significantly +improved by switching to a 64-bit kernel. + +Suggested-by: Andy Lutomirski +Signed-off-by: Joerg Roedel +--- + arch/x86/mm/pti.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/arch/x86/mm/pti.c b/arch/x86/mm/pti.c +index 3ffd92309aca..8f5aa0dda327 100644 +--- a/arch/x86/mm/pti.c ++++ b/arch/x86/mm/pti.c +@@ -385,6 +385,22 @@ void __init pti_init(void) + + pr_info("enabled\n"); + ++#ifdef CONFIG_X86_32 ++ if (boot_cpu_has(X86_FEATURE_PCID)) { ++ /* Use printk to work around pr_fmt() */ ++ printk(KERN_WARNING "\n"); ++ printk(KERN_WARNING "************************************************************\n"); ++ printk(KERN_WARNING "** WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! **\n"); ++ printk(KERN_WARNING "** **\n"); ++ printk(KERN_WARNING "** You are using 32-bit PTI on a 64-bit PCID-capable CPU. **\n"); ++ printk(KERN_WARNING "** Your performance will increase dramatically if you **\n"); ++ printk(KERN_WARNING "** switch to a 64-bit kernel! **\n"); ++ printk(KERN_WARNING "** **\n"); ++ printk(KERN_WARNING "** WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! **\n"); ++ printk(KERN_WARNING "************************************************************\n"); ++ } ++#endif ++ + pti_clone_user_shared(); + pti_clone_entry_text(); + pti_setup_espfix64(); +-- +2.16.2 + diff --git a/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0100-tone-down-PCID-on-32bit-message.patch b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0100-tone-down-PCID-on-32bit-message.patch new file mode 100644 index 00000000..9e14a8ea --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/mageia/pti32bit-0100-tone-down-PCID-on-32bit-message.patch @@ -0,0 +1,32 @@ + +Dont scare people with something that should be an informal message. + +Signed-off-by: Thomas Backlund + +--- linux/arch/x86/mm/pti.c.orig ++++ linux/arch/x86/mm/pti.c +@@ -388,16 +388,14 @@ void __init pti_init(void) + #ifdef CONFIG_X86_32 + if (boot_cpu_has(X86_FEATURE_PCID)) { + /* Use printk to work around pr_fmt() */ +- printk(KERN_WARNING "\n"); +- printk(KERN_WARNING "************************************************************\n"); +- printk(KERN_WARNING "** WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! **\n"); +- printk(KERN_WARNING "** **\n"); +- printk(KERN_WARNING "** You are using 32-bit PTI on a 64-bit PCID-capable CPU. **\n"); +- printk(KERN_WARNING "** Your performance will increase dramatically if you **\n"); +- printk(KERN_WARNING "** switch to a 64-bit kernel! **\n"); +- printk(KERN_WARNING "** **\n"); +- printk(KERN_WARNING "** WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! **\n"); +- printk(KERN_WARNING "************************************************************\n"); ++ printk(KERN_INFO "\n"); ++ printk(KERN_INFO "************************************************************\n"); ++ printk(KERN_INFO "** **\n"); ++ printk(KERN_INFO "** You are using 32-bit PTI on a 64-bit PCID-capable CPU. **\n"); ++ printk(KERN_INFO "** Your performance will increase dramatically if you **\n"); ++ printk(KERN_INFO "** switch to a 64-bit install. **\n"); ++ printk(KERN_INFO "** **\n"); ++ printk(KERN_INFO "************************************************************\n"); + } + #endif + diff --git a/kernel/tools/cpupowertools/files/patches/mageia/scsi-core-Avoid-that-ATA-error-handling-can-trigger-a-kernel-hang-or-oops.patch b/kernel/tools/cpupowertools/files/patches/mageia/scsi-core-Avoid-that-ATA-error-handling-can-trigger-a-kernel-hang-or-oops.patch new file mode 100644 index 00000000..c2bdadef --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/mageia/scsi-core-Avoid-that-ATA-error-handling-can-trigger-a-kernel-hang-or-oops.patch @@ -0,0 +1,126 @@ +From 3be8828fc507cdafe7040a3dcf361a2bcd8e305b Mon Sep 17 00:00:00 2001 +From: Bart Van Assche +Date: Thu, 22 Feb 2018 11:30:20 -0800 +Subject: scsi: core: Avoid that ATA error handling can trigger a kernel hang + or oops + +Avoid that the recently introduced call_rcu() call in the SCSI core +triggers a double call_rcu() call. + +Reported-by: Natanael Copa +Reported-by: Damien Le Moal +References: https://bugzilla.kernel.org/show_bug.cgi?id=198861 +Fixes: 3bd6f43f5cb3 ("scsi: core: Ensure that the SCSI error handler gets woken up") +Signed-off-by: Bart Van Assche +Reviewed-by: Damien Le Moal +Tested-by: Damien Le Moal +Cc: Natanael Copa +Cc: Damien Le Moal +Cc: Alexandre Oliva +Cc: Pavel Tikhomirov +Cc: Hannes Reinecke +Cc: Johannes Thumshirn +Cc: +Signed-off-by: Martin K. Petersen +--- + drivers/scsi/hosts.c | 3 --- + drivers/scsi/scsi_error.c | 5 +++-- + drivers/scsi/scsi_lib.c | 2 ++ + include/scsi/scsi_cmnd.h | 3 +++ + include/scsi/scsi_host.h | 2 -- + 5 files changed, 8 insertions(+), 7 deletions(-) + +diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c +index 57bf43e..dd94649 100644 +--- a/drivers/scsi/hosts.c ++++ b/drivers/scsi/hosts.c +@@ -328,8 +328,6 @@ static void scsi_host_dev_release(struct device *dev) + if (shost->work_q) + destroy_workqueue(shost->work_q); + +- destroy_rcu_head(&shost->rcu); +- + if (shost->shost_state == SHOST_CREATED) { + /* + * Free the shost_dev device name here if scsi_host_alloc() +@@ -404,7 +402,6 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) + INIT_LIST_HEAD(&shost->starved_list); + init_waitqueue_head(&shost->host_wait); + mutex_init(&shost->scan_mutex); +- init_rcu_head(&shost->rcu); + + index = ida_simple_get(&host_index_ida, 0, 0, GFP_KERNEL); + if (index < 0) +diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c +index d042915..ca53a5f 100644 +--- a/drivers/scsi/scsi_error.c ++++ b/drivers/scsi/scsi_error.c +@@ -223,7 +223,8 @@ static void scsi_eh_reset(struct scsi_cmnd *scmd) + + static void scsi_eh_inc_host_failed(struct rcu_head *head) + { +- struct Scsi_Host *shost = container_of(head, typeof(*shost), rcu); ++ struct scsi_cmnd *scmd = container_of(head, typeof(*scmd), rcu); ++ struct Scsi_Host *shost = scmd->device->host; + unsigned long flags; + + spin_lock_irqsave(shost->host_lock, flags); +@@ -259,7 +260,7 @@ void scsi_eh_scmd_add(struct scsi_cmnd *scmd) + * Ensure that all tasks observe the host state change before the + * host_failed change. + */ +- call_rcu(&shost->rcu, scsi_eh_inc_host_failed); ++ call_rcu(&scmd->rcu, scsi_eh_inc_host_failed); + } + + /** +diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c +index 5cbc69b..4af1682 100644 +--- a/drivers/scsi/scsi_lib.c ++++ b/drivers/scsi/scsi_lib.c +@@ -670,6 +670,7 @@ static bool scsi_end_request(struct request *req, blk_status_t error, + if (!blk_rq_is_scsi(req)) { + WARN_ON_ONCE(!(cmd->flags & SCMD_INITIALIZED)); + cmd->flags &= ~SCMD_INITIALIZED; ++ destroy_rcu_head(&cmd->rcu); + } + + if (req->mq_ctx) { +@@ -1150,6 +1151,7 @@ static void scsi_initialize_rq(struct request *rq) + struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(rq); + + scsi_req_init(&cmd->req); ++ init_rcu_head(&cmd->rcu); + cmd->jiffies_at_alloc = jiffies; + cmd->retries = 0; + } +diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h +index 949a016..0382cea 100644 +--- a/include/scsi/scsi_cmnd.h ++++ b/include/scsi/scsi_cmnd.h +@@ -69,6 +69,9 @@ struct scsi_cmnd { + struct list_head list; /* scsi_cmnd participates in queue lists */ + struct list_head eh_entry; /* entry for the host eh_cmd_q */ + struct delayed_work abort_work; ++ ++ struct rcu_head rcu; ++ + int eh_eflags; /* Used by error handlr */ + + /* +diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h +index 1a1df0d..a8b7bf8 100644 +--- a/include/scsi/scsi_host.h ++++ b/include/scsi/scsi_host.h +@@ -571,8 +571,6 @@ struct Scsi_Host { + struct blk_mq_tag_set tag_set; + }; + +- struct rcu_head rcu; +- + atomic_t host_busy; /* commands actually active on low-level */ + atomic_t host_blocked; + +-- +cgit v1.1 + diff --git a/kernel/tools/cpupowertools/files/patches/mageia/scsi-core-return-BLK_STS_OK-for-DID_OK-in-__scsi_error_from_host_byte.patch b/kernel/tools/cpupowertools/files/patches/mageia/scsi-core-return-BLK_STS_OK-for-DID_OK-in-__scsi_error_from_host_byte.patch new file mode 100644 index 00000000..30489291 --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/mageia/scsi-core-return-BLK_STS_OK-for-DID_OK-in-__scsi_error_from_host_byte.patch @@ -0,0 +1,34 @@ +From e39a97353e5378eb46bf01679799c5704d397f32 Mon Sep 17 00:00:00 2001 +From: Hannes Reinecke +Date: Mon, 26 Feb 2018 08:39:59 +0100 +Subject: scsi: core: return BLK_STS_OK for DID_OK in + __scsi_error_from_host_byte() + +When converting __scsi_error_from_host_byte() to BLK_STS error codes the +case DID_OK was forgotten, resulting in it always returning an error. + +Fixes: 2a842acab109 ("block: introduce new block status code type") +Cc: Doug Gilbert +Signed-off-by: Hannes Reinecke +Reviewed-by: Douglas Gilbert +Signed-off-by: Martin K. Petersen +--- + drivers/scsi/scsi_lib.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c +index 4af1682..c984404 100644 +--- a/drivers/scsi/scsi_lib.c ++++ b/drivers/scsi/scsi_lib.c +@@ -720,6 +720,8 @@ static blk_status_t __scsi_error_from_host_byte(struct scsi_cmnd *cmd, + int result) + { + switch (host_byte(result)) { ++ case DID_OK: ++ return BLK_STS_OK; + case DID_TRANSPORT_FAILFAST: + return BLK_STS_TRANSPORT; + case DID_TARGET_FAILURE: +-- +cgit v1.1 + diff --git a/kernel/tools/cpupowertools/files/patches/mageia/scsi-qla2xxx-Fix-NULL-pointer-crash-due-to-active-timer-for-ABTS.patch b/kernel/tools/cpupowertools/files/patches/mageia/scsi-qla2xxx-Fix-NULL-pointer-crash-due-to-active-timer-for-ABTS.patch new file mode 100644 index 00000000..07d56db5 --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/mageia/scsi-qla2xxx-Fix-NULL-pointer-crash-due-to-active-timer-for-ABTS.patch @@ -0,0 +1,119 @@ +From 1514839b366417934e2f1328edb50ed1e8a719f5 Mon Sep 17 00:00:00 2001 +From: "himanshu.madhani@cavium.com" +Date: Mon, 12 Feb 2018 10:28:14 -0800 +Subject: scsi: qla2xxx: Fix NULL pointer crash due to active timer for ABTS + +This patch fixes NULL pointer crash due to active timer running for abort +IOCB. + +From crash dump analysis it was discoverd that get_next_timer_interrupt() +encountered a corrupted entry on the timer list. + + #9 [ffff95e1f6f0fd40] page_fault at ffffffff914fe8f8 + [exception RIP: get_next_timer_interrupt+440] + RIP: ffffffff90ea3088 RSP: ffff95e1f6f0fdf0 RFLAGS: 00010013 + RAX: ffff95e1f6451028 RBX: 000218e2389e5f40 RCX: 00000001232ad600 + RDX: 0000000000000001 RSI: ffff95e1f6f0fdf0 RDI: 0000000001232ad6 + RBP: ffff95e1f6f0fe40 R8: ffff95e1f6451188 R9: 0000000000000001 + R10: 0000000000000016 R11: 0000000000000016 R12: 00000001232ad5f6 + R13: ffff95e1f6450000 R14: ffff95e1f6f0fdf8 R15: ffff95e1f6f0fe10 + ORIG_RAX: ffffffffffffffff CS: 0010 SS: 0018 + +Looking at the assembly of get_next_timer_interrupt(), address came +from %r8 (ffff95e1f6451188) which is pointing to list_head with single +entry at ffff95e5ff621178. + + 0xffffffff90ea307a : mov (%r8),%rdx + 0xffffffff90ea307d : cmp %r8,%rdx + 0xffffffff90ea3080 : je 0xffffffff90ea30a7 + 0xffffffff90ea3082 : nopw 0x0(%rax,%rax,1) + 0xffffffff90ea3088 : testb $0x1,0x18(%rdx) + + crash> rd ffff95e1f6451188 10 + ffff95e1f6451188: ffff95e5ff621178 ffff95e5ff621178 x.b.....x.b..... + ffff95e1f6451198: ffff95e1f6451198 ffff95e1f6451198 ..E.......E..... + ffff95e1f64511a8: ffff95e1f64511a8 ffff95e1f64511a8 ..E.......E..... + ffff95e1f64511b8: ffff95e77cf509a0 ffff95e77cf509a0 ...|.......|.... + ffff95e1f64511c8: ffff95e1f64511c8 ffff95e1f64511c8 ..E.......E..... + + crash> rd ffff95e5ff621178 10 + ffff95e5ff621178: 0000000000000001 ffff95e15936aa00 ..........6Y.... + ffff95e5ff621188: 0000000000000000 00000000ffffffff ................ + ffff95e5ff621198: 00000000000000a0 0000000000000010 ................ + ffff95e5ff6211a8: ffff95e5ff621198 000000000000000c ..b............. + ffff95e5ff6211b8: 00000f5800000000 ffff95e751f8d720 ....X... ..Q.... + + ffff95e5ff621178 belongs to freed mempool object at ffff95e5ff621080. + + CACHE NAME OBJSIZE ALLOCATED TOTAL SLABS SSIZE + ffff95dc7fd74d00 mnt_cache 384 19785 24948 594 16k + SLAB MEMORY NODE TOTAL ALLOCATED FREE + ffffdc5dabfd8800 ffff95e5ff620000 1 42 29 13 + FREE / [ALLOCATED] + ffff95e5ff621080 (cpu 6 cache) + +Examining the contents of that memory reveals a pointer to a constant string +in the driver, "abort\0", which is set by qla24xx_async_abort_cmd(). + + crash> rd ffffffffc059277c 20 + ffffffffc059277c: 6e490074726f6261 0074707572726574 abort.Interrupt. + ffffffffc059278c: 00676e696c6c6f50 6920726576697244 Polling.Driver i + ffffffffc059279c: 646f6d207325206e 6974736554000a65 n %s mode..Testi + ffffffffc05927ac: 636976656420676e 786c252074612065 ng device at %lx + ffffffffc05927bc: 6b63656843000a2e 646f727020676e69 ...Checking prod + ffffffffc05927cc: 6f20444920746375 0a2e706968632066 uct ID of chip.. + ffffffffc05927dc: 5120646e756f4600 204130303232414c .Found QLA2200A + ffffffffc05927ec: 43000a2e70696843 20676e696b636568 Chip...Checking + ffffffffc05927fc: 65786f626c69616d 6c636e69000a2e73 mailboxes...incl + ffffffffc059280c: 756e696c2f656475 616d2d616d642f78 ude/linux/dma-ma + + crash> struct -ox srb_iocb + struct srb_iocb { + union { + struct {...} logio; + struct {...} els_logo; + struct {...} tmf; + struct {...} fxiocb; + struct {...} abt; + struct ct_arg ctarg; + struct {...} mbx; + struct {...} nack; + [0x0 ] } u; + [0xb8] struct timer_list timer; + [0x108] void (*timeout)(void *); + } + SIZE: 0x110 + + crash> ! bc + ibase=16 + obase=10 + B8+40 + F8 + +The object is a srb_t, and at offset 0xf8 within that structure +(i.e. ffff95e5ff621080 + f8 -> ffff95e5ff621178) is a struct timer_list. + +Cc: #4.4+ +Fixes: 4440e46d5db7 ("[SCSI] qla2xxx: Add IOCB Abort command asynchronous handling.") +Signed-off-by: Himanshu Madhani +Reviewed-by: Johannes Thumshirn +Signed-off-by: Martin K. Petersen +--- + drivers/scsi/qla2xxx/qla_init.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c +index 2dea112..0487062 100644 +--- a/drivers/scsi/qla2xxx/qla_init.c ++++ b/drivers/scsi/qla2xxx/qla_init.c +@@ -1527,6 +1527,7 @@ qla24xx_abort_sp_done(void *ptr, int res) + srb_t *sp = ptr; + struct srb_iocb *abt = &sp->u.iocb_cmd; + ++ del_timer(&sp->u.iocb_cmd.timer); + complete(&abt->u.abt.comp); + } + +-- +cgit v1.1 + diff --git a/kernel/tools/cpupowertools/files/patches/mageia/series b/kernel/tools/cpupowertools/files/patches/mageia/series index f2118064..eaf1d51c 100644 --- a/kernel/tools/cpupowertools/files/patches/mageia/series +++ b/kernel/tools/cpupowertools/files/patches/mageia/series @@ -14,6 +14,7 @@ ### ### Stable Queue ### +patch-4.14.25-rc1.patch ### ### Arch x86 @@ -45,35 +46,40 @@ pti32bit-0003-x86-entry-32-Load-task-stack-from-x86_tss.sp1-in-SYS.patch pti32bit-0004-x86-entry-32-Put-ESPFIX-code-into-a-macro.patch pti32bit-0005-x86-entry-32-Unshare-NMI-return-path.patch pti32bit-0006-x86-entry-32-Split-off-return-to-kernel-path.patch +# could be disabled as not needed according to Linus @ LKML pti32bit-0007-x86-entry-32-Restore-segments-before-int-registers.patch pti32bit-0008-x86-entry-32-Enter-the-kernel-via-trampoline-stack.patch pti32bit-0009-x86-entry-32-Leave-the-kernel-via-trampoline-stack.patch pti32bit-0010-x86-entry-32-Introduce-SAVE_ALL_NMI-and-RESTORE_ALL_.patch -pti32bit-0011-x86-entry-32-Add-PTI-cr3-switches-to-NMI-handler-cod.patch -pti32bit-0012-x86-entry-32-Add-PTI-cr3-switch-to-non-NMI-entry-exi.patch -pti32bit-0013-x86-entry-32-Handle-Entry-from-Kernel-Mode-on-Entry-.patch -pti32bit-0014-x86-pgtable-pae-Unshare-kernel-PMDs-when-PTI-is-enab.patch -pti32bit-0015-x86-pgtable-32-Allocate-8k-page-tables-when-PTI-is-e.patch -pti32bit-0016-x86-pgtable-Move-pgdp-kernel-user-conversion-functio.patch -pti32bit-0017-x86-pgtable-Move-pti_set_user_pgd-to-pgtable.h.patch -pti32bit-0018-x86-pgtable-Move-two-more-functions-from-pgtable_64..patch -pti32bit-0019-x86-mm-pae-Populate-valid-user-PGD-entries.patch -pti32bit-0020-x86-mm-pae-Populate-the-user-page-table-with-user-pg.patch -pti32bit-0021-x86-mm-legacy-Populate-the-user-page-table-with-user.patch -pti32bit-0022-x86-mm-pti-Add-an-overflow-check-to-pti_clone_pmds.patch -pti32bit-0023-x86-mm-pti-Define-X86_CR3_PTI_PCID_USER_BIT-on-x86_3.patch -pti32bit-0024-x86-mm-pti-Clone-CPU_ENTRY_AREA-on-PMD-level-on-x86_.patch -pti32bit-0025-x86-mm-dump_pagetables-Define-INIT_PGD.patch -pti32bit-0026-x86-pgtable-pae-Use-separate-kernel-PMDs-for-user-pa.patch -pti32bit-0027-x86-ldt-Reserve-address-space-range-on-32-bit-for-th.patch -pti32bit-0028-x86-ldt-Define-LDT_END_ADDR.patch -pti32bit-0029-x86-ldt-Split-out-sanity-check-in-map_ldt_struct.patch -pti32bit-0030-x86-ldt-Enable-LDT-user-mapping-for-PAE.patch -pti32bit-0031-x86-pti-Allow-CONFIG_PAGE_TABLE_ISOLATION-for-x86_32.patch +pti32bit-0011-x86-entry-32-Handle-Entry-from-Kernel-Mode-on-Entry-.patch +pti32bit-0012-x86-entry-32-Simplify-debug-entry-point.patch +pti32bit-0013-x86-entry-32-Add-PTI-cr3-switches-to-NMI-handler-cod.patch +pti32bit-0014-x86-entry-32-Add-PTI-cr3-switch-to-non-NMI-entry-exi.patch +pti32bit-0015-x86-pgtable-Rename-pti_set_user_pgd-to-pti_set_user_.patch +pti32bit-0016-x86-pgtable-pae-Unshare-kernel-PMDs-when-PTI-is-enab.patch +pti32bit-0017-x86-pgtable-32-Allocate-8k-page-tables-when-PTI-is-e.patch +pti32bit-0018-x86-pgtable-Move-pgdp-kernel-user-conversion-functio.patch +pti32bit-0019-x86-pgtable-Move-pti_set_user_pgtbl-to-pgtable.h.patch +pti32bit-0020-x86-pgtable-Move-two-more-functions-from-pgtable_64..patch +pti32bit-0021-x86-mm-pae-Populate-valid-user-PGD-entries.patch +pti32bit-0022-x86-mm-pae-Populate-the-user-page-table-with-user-pg.patch +pti32bit-0023-x86-mm-legacy-Populate-the-user-page-table-with-user.patch +pti32bit-0024-x86-mm-pti-Add-an-overflow-check-to-pti_clone_pmds.patch +pti32bit-0025-x86-mm-pti-Define-X86_CR3_PTI_PCID_USER_BIT-on-x86_3.patch +pti32bit-0026-x86-mm-pti-Clone-CPU_ENTRY_AREA-on-PMD-level-on-x86_.patch +pti32bit-0027-x86-mm-dump_pagetables-Define-INIT_PGD.patch +pti32bit-0028-x86-pgtable-pae-Use-separate-kernel-PMDs-for-user-pa.patch +pti32bit-0029-x86-ldt-Reserve-address-space-range-on-32-bit-for-th.patch +pti32bit-0030-x86-ldt-Define-LDT_END_ADDR.patch +pti32bit-0031-x86-ldt-Split-out-sanity-check-in-map_ldt_struct.patch +pti32bit-0032-x86-ldt-Enable-LDT-user-mapping-for-PAE.patch +pti32bit-0033-x86-pti-Allow-CONFIG_PAGE_TABLE_ISOLATION-for-x86_32.patch +pti32bit-0034-x86-mm-pti-Add-Warning-when-booting-on-a-PCID-capabl.patch +# tone down warning about PCID on 32bit +pti32bit-0100-tone-down-PCID-on-32bit-message.patch # selected fixes from x86/pti x86-pti-0070-nospec-Kill-array_index_nospec_mask_check.patch -x86-pti-0071-nospec-Allow-index-argument-to-have-const-qualified-.patch x86-pti-0072-nospec-Include-asm-barrier.h-dependency.patch x86-pti-0073-x86-microcode-Propagate-return-value-from-updating-f.patch x86-pti-0074-x86-CPU-Add-a-microcode-loader-callback.patch @@ -186,6 +192,15 @@ block-bfq-limit-sectors-served-with-interactive-weig.patch block-bfq-put-async-queues-for-root-bfq-groups-too.patch block-bfq-add-requeue-request-hook.patch +# HPT RR 644L +ata-ahci-Add-PCI-id-for-the-Highpoint-Rocketraid-644L-card.patch +PCI-Add-function-1-DMA-alias-quirk-for-Highpoint-RocketRAID-644L.patch + +# scsi +scsi-core-Avoid-that-ATA-error-handling-can-trigger-a-kernel-hang-or-oops.patch +scsi-core-return-BLK_STS_OK-for-DID_OK-in-__scsi_error_from_host_byte.patch +scsi-qla2xxx-Fix-NULL-pointer-crash-due-to-active-timer-for-ABTS.patch + ### ### Char ### @@ -251,6 +266,10 @@ hwmon-k10temp-Add-support-for-temperature-offsets.patch input-i8042-quirks-for-Fujitsu-Lifebook-A544-and-Lif.patch +# mga #22703 +input-goodix-disable-IRQs-while-suspended.patch +input-goodix-add-support-for-GDIX1002.patch + ### ### idle ### @@ -309,6 +328,9 @@ net-tls-Correct-length-of-scatterlist-in-tls_sw_sendpage.patch # silence message that gets reported as a bug net-netfilter-xt_addrtype-silence-BROADCAST-message.patch +# CVE-2018-1065 +net-netfilter-add-back-stackpointer-size-checks.patch + ### ### pinctrl ### @@ -340,6 +362,12 @@ platform-x86-ideapad-laptop-Increase-timeout-to-wait-for-ec-answer.patch ### Sound ### +sound-ALSA-hda-Fix-a-wrong-FIXUP-for-alc289-on-Dell-machines.patch + +# skl/kbl fixes +sound-ASoC-Intel-Skylake-Fix-jack-name-format-substitution.patch +sound-ASoC-Intel-kbl-fix-jack-name.patch + ### ### Staging ### @@ -448,6 +476,8 @@ video-mageia-logo.patch ### ARM ### +arch-ARM-omap2-hide-omap3_save_secure_ram-on-non-OMAP3-bu.patch + ### ### IA64 ### diff --git a/kernel/tools/cpupowertools/files/patches/mageia/sound-ALSA-hda-Fix-a-wrong-FIXUP-for-alc289-on-Dell-machines.patch b/kernel/tools/cpupowertools/files/patches/mageia/sound-ALSA-hda-Fix-a-wrong-FIXUP-for-alc289-on-Dell-machines.patch new file mode 100644 index 00000000..449e697a --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/mageia/sound-ALSA-hda-Fix-a-wrong-FIXUP-for-alc289-on-Dell-machines.patch @@ -0,0 +1,35 @@ +From: Hui Wang +Subject: [PATCH] ALSA: hda - Fix a wrong FIXUP for alc289 on Dell machines +Date: Fri, 2 Mar 2018 13:05:36 +0800 + +With the alc289, the Pin 0x1b is Headphone-Mic, so we should assign +ALC269_FIXUP_DELL4_MIC_NO_PRESENCE rather than +ALC225_FIXUP_DELL1_MIC_NO_PRESENCE to it. And this change is suggested +by Kailang of Realtek and is verified on the machine. + +(This fixes the commit 3f2f7c55) + +Cc: Kailang Yang +Cc: +Signed-off-by: Hui Wang +--- + sound/pci/hda/patch_realtek.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index b9c93fa..7a9a867 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -6872,7 +6872,7 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { + {0x12, 0x90a60120}, + {0x14, 0x90170110}, + {0x21, 0x0321101f}), +- SND_HDA_PIN_QUIRK(0x10ec0289, 0x1028, "Dell", ALC225_FIXUP_DELL1_MIC_NO_PRESENCE, ++ SND_HDA_PIN_QUIRK(0x10ec0289, 0x1028, "Dell", ALC269_FIXUP_DELL4_MIC_NO_PRESENCE, + {0x12, 0xb7a60130}, + {0x14, 0x90170110}, + {0x21, 0x04211020}), +-- +2.7.4 + + diff --git a/kernel/tools/cpupowertools/files/patches/mageia/sound-ASoC-Intel-Skylake-Fix-jack-name-format-substitution.patch b/kernel/tools/cpupowertools/files/patches/mageia/sound-ASoC-Intel-Skylake-Fix-jack-name-format-substitution.patch new file mode 100644 index 00000000..b3fd6ec2 --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/mageia/sound-ASoC-Intel-Skylake-Fix-jack-name-format-substitution.patch @@ -0,0 +1,35 @@ +From d1c4cb447a7efcb5608a33cdfed8ab4234378b0a Mon Sep 17 00:00:00 2001 +From: Chintan Patel +Date: Mon, 18 Sep 2017 08:43:18 -0700 +Subject: [PATCH] ASoC: Intel: Skylake: Fix jack name format substitution + +Jack name is not getting formatted correctly hence resulting +in invalid name for HDMI/DP input devices. + +This was recently exposed due changes brought by MST: +commit 3a13347f05fd ("ASoC: Intel: kbl: Add jack port initialize +in kbl machine drivers") + +Signed-off-by: Chintan Patel +Acked-By: Vinod Koul +Signed-off-by: Mark Brown +--- + sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c +index 88ff54220007..9cd0769ccd34 100644 +--- a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c ++++ b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c +@@ -604,6 +604,8 @@ static int kabylake_card_late_probe(struct snd_soc_card *card) + + list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) { + codec = pcm->codec_dai->codec; ++ snprintf(jack_name, sizeof(jack_name), ++ "HDMI/DP, pcm=%d Jack", pcm->device); + err = snd_soc_card_jack_new(card, jack_name, + SND_JACK_AVOUT, &ctx->kabylake_hdmi[i], + NULL, 0); +-- +2.16.2 + diff --git a/kernel/tools/cpupowertools/files/patches/mageia/sound-ASoC-Intel-kbl-fix-jack-name.patch b/kernel/tools/cpupowertools/files/patches/mageia/sound-ASoC-Intel-kbl-fix-jack-name.patch new file mode 100644 index 00000000..75359b31 --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/mageia/sound-ASoC-Intel-kbl-fix-jack-name.patch @@ -0,0 +1,32 @@ +From cedb6415f9ece6d3368aa0ac8a433caff799792a Mon Sep 17 00:00:00 2001 +From: Vinod Koul +Date: Tue, 31 Oct 2017 16:47:27 +0530 +Subject: [PATCH] ASoC: Intel: kbl: fix jack name + +Commit d1c4cb447a7e ("ASoC: Intel: Skylake: Fix jack name format +substitution") added Jack name but erroneously added a space as well, +so remove the space in Jack name. + +Fixes: d1c4cb447a7e ("ASoC: Intel: Skylake: Fix jack name format substitution") +Signed-off-by: Vinod Koul +Signed-off-by: Mark Brown +--- + sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c +index 9cd0769ccd34..69ab55956492 100644 +--- a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c ++++ b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c +@@ -605,7 +605,7 @@ static int kabylake_card_late_probe(struct snd_soc_card *card) + list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) { + codec = pcm->codec_dai->codec; + snprintf(jack_name, sizeof(jack_name), +- "HDMI/DP, pcm=%d Jack", pcm->device); ++ "HDMI/DP,pcm=%d Jack", pcm->device); + err = snd_soc_card_jack_new(card, jack_name, + SND_JACK_AVOUT, &ctx->kabylake_hdmi[i], + NULL, 0); +-- +2.16.2 + diff --git a/kernel/tools/cpupowertools/files/patches/pisilinux/kernel-5.4-build-fix.patch b/kernel/tools/cpupowertools/files/patches/pisilinux/kernel-5.4-build-fix.patch new file mode 100644 index 00000000..c1de3106 --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/pisilinux/kernel-5.4-build-fix.patch @@ -0,0 +1,18 @@ +--- a/Makefile.orig 2019-11-25 03:32:01.000000000 +0300 ++++ b/Makefile 2019-12-11 03:20:12.876664698 +0300 +@@ -509,15 +509,6 @@ + # ignore whole output directory + outputmakefile: + ifdef building_out_of_srctree +- $(Q)if [ -f $(srctree)/.config -o \ +- -d $(srctree)/include/config -o \ +- -d $(srctree)/arch/$(SRCARCH)/include/generated ]; then \ +- echo >&2 "***"; \ +- echo >&2 "*** The source tree is not clean, please run 'make$(if $(findstring command line, $(origin ARCH)), ARCH=$(ARCH)) mrproper'"; \ +- echo >&2 "*** in $(abs_srctree)";\ +- echo >&2 "***"; \ +- false; \ +- fi + $(Q)ln -fsn $(srctree) source + $(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkmakefile $(srctree) + $(Q)test -e .gitignore || \ diff --git a/kernel/tools/cpupowertools/files/patches/pisilinux/revert-Makefile.patch b/kernel/tools/cpupowertools/files/patches/pisilinux/revert-Makefile.patch new file mode 100644 index 00000000..b4b37d09 --- /dev/null +++ b/kernel/tools/cpupowertools/files/patches/pisilinux/revert-Makefile.patch @@ -0,0 +1,780 @@ +--- a/Makefile.orig 2019-11-25 03:32:01.000000000 +0300 ++++ b/Makefile 2019-12-11 16:59:26.708807035 +0300 +@@ -3,7 +3,7 @@ + PATCHLEVEL = 4 + SUBLEVEL = 0 + EXTRAVERSION = +-NAME = Kleptomaniac Octopus ++NAME = Bobtail Squid + + # *DOCUMENTATION* + # To see a list of typical targets execute "make help" +@@ -206,16 +206,30 @@ + KBUILD_CHECKSRC = 0 + endif + +-# Use make M=dir or set the environment variable KBUILD_EXTMOD to specify the +-# directory of external module to build. Setting M= takes precedence. ++# Use make M=dir to specify directory of external module to build ++# Old syntax make ... SUBDIRS=$PWD is still supported ++# Setting the environment variable KBUILD_EXTMOD take precedence ++ifdef SUBDIRS ++ $(warning ================= WARNING ================) ++ $(warning 'SUBDIRS' will be removed after Linux 5.3) ++ $(warning ) ++ $(warning If you are building an individual subdirectory) ++ $(warning in the kernel tree, you can do like this:) ++ $(warning $$ make path/to/dir/you/want/to/build/) ++ $(warning (Do not forget the trailing slash)) ++ $(warning ) ++ $(warning If you are building an external module,) ++ $(warning Please use 'M=' or 'KBUILD_EXTMOD' instead) ++ $(warning ==========================================) ++ KBUILD_EXTMOD ?= $(SUBDIRS) ++endif ++ + ifeq ("$(origin M)", "command line") + KBUILD_EXTMOD := $(M) + endif + + export KBUILD_CHECKSRC KBUILD_EXTMOD + +-extmod-prefix = $(if $(KBUILD_EXTMOD),$(KBUILD_EXTMOD)/) +- + ifeq ($(abs_srctree),$(abs_objtree)) + # building in the source tree + srctree := . +@@ -257,62 +271,52 @@ + %asm-generic kernelversion %src-pkg + no-sync-config-targets := $(no-dot-config-targets) install %install \ + kernelrelease +-single-targets := %.a %.i %.ko %.lds %.ll %.lst %.mod %.o %.s %.symtypes %/ + +-config-build := +-mixed-build := +-need-config := 1 +-may-sync-config := 1 +-single-build := ++config-targets := 0 ++mixed-targets := 0 ++dot-config := 1 ++may-sync-config := 1 + + ifneq ($(filter $(no-dot-config-targets), $(MAKECMDGOALS)),) + ifeq ($(filter-out $(no-dot-config-targets), $(MAKECMDGOALS)),) +- need-config := ++ dot-config := 0 + endif + endif + + ifneq ($(filter $(no-sync-config-targets), $(MAKECMDGOALS)),) + ifeq ($(filter-out $(no-sync-config-targets), $(MAKECMDGOALS)),) +- may-sync-config := ++ may-sync-config := 0 + endif + endif + + ifneq ($(KBUILD_EXTMOD),) +- may-sync-config := ++ may-sync-config := 0 + endif + + ifeq ($(KBUILD_EXTMOD),) + ifneq ($(filter config %config,$(MAKECMDGOALS)),) +- config-build := 1 ++ config-targets := 1 + ifneq ($(words $(MAKECMDGOALS)),1) +- mixed-build := 1 ++ mixed-targets := 1 + endif + endif + endif + +-# We cannot build single targets and the others at the same time +-ifneq ($(filter $(single-targets), $(MAKECMDGOALS)),) +- single-build := 1 +- ifneq ($(filter-out $(single-targets), $(MAKECMDGOALS)),) +- mixed-build := 1 +- endif +-endif +- + # For "make -j clean all", "make -j mrproper defconfig all", etc. + ifneq ($(filter $(clean-targets),$(MAKECMDGOALS)),) + ifneq ($(filter-out $(clean-targets),$(MAKECMDGOALS)),) +- mixed-build := 1 ++ mixed-targets := 1 + endif + endif + + # install and modules_install need also be processed one by one + ifneq ($(filter install,$(MAKECMDGOALS)),) + ifneq ($(filter modules_install,$(MAKECMDGOALS)),) +- mixed-build := 1 ++ mixed-targets := 1 + endif + endif + +-ifdef mixed-build ++ifeq ($(mixed-targets),1) + # =========================================================================== + # We're called with mixed targets (*config and build targets). + # Handle them one by one. +@@ -328,7 +332,7 @@ + $(MAKE) -f $(srctree)/Makefile $$i; \ + done + +-else # !mixed-build ++else + + include scripts/Kbuild.include + +@@ -388,7 +392,9 @@ + export KCONFIG_CONFIG + + # SHELL used by kbuild +-CONFIG_SHELL := sh ++CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \ ++ else if [ -x /bin/bash ]; then echo /bin/bash; \ ++ else echo sh; fi ; fi) + + HOST_LFS_CFLAGS := $(shell getconf LFS_CFLAGS 2>/dev/null) + HOST_LFS_LDFLAGS := $(shell getconf LFS_LDFLAGS 2>/dev/null) +@@ -425,7 +431,6 @@ + PYTHON2 = python2 + PYTHON3 = python3 + CHECK = sparse +-BASH = bash + + CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ \ + -Wbitwise -Wno-return-void -Wno-unknown-attribute $(CF) +@@ -465,13 +470,12 @@ + KBUILD_CFLAGS_KERNEL := + KBUILD_AFLAGS_MODULE := -DMODULE + KBUILD_CFLAGS_MODULE := -DMODULE +-KBUILD_LDFLAGS_MODULE := +-export KBUILD_LDS_MODULE := $(srctree)/scripts/module-common.lds ++KBUILD_LDFLAGS_MODULE := -T $(srctree)/scripts/module-common.lds + KBUILD_LDFLAGS := + GCC_PLUGINS_CFLAGS := + CLANG_FLAGS := + +-export ARCH SRCARCH CONFIG_SHELL BASH HOSTCC KBUILD_HOSTCFLAGS CROSS_COMPILE AS LD CC ++export ARCH SRCARCH CONFIG_SHELL HOSTCC KBUILD_HOSTCFLAGS CROSS_COMPILE AS LD CC + export CPP AR NM STRIP OBJCOPY OBJDUMP OBJSIZE PAHOLE LEX YACC AWK INSTALLKERNEL + export PERL PYTHON PYTHON2 PYTHON3 CHECK CHECKFLAGS MAKE UTS_MACHINE HOSTCXX + export KBUILD_HOSTCXXFLAGS KBUILD_HOSTLDFLAGS KBUILD_HOSTLDLIBS LDFLAGS_MODULE +@@ -482,6 +486,7 @@ + export KBUILD_AFLAGS AFLAGS_KERNEL AFLAGS_MODULE + export KBUILD_AFLAGS_MODULE KBUILD_CFLAGS_MODULE KBUILD_LDFLAGS_MODULE + export KBUILD_AFLAGS_KERNEL KBUILD_CFLAGS_KERNEL ++export KBUILD_ARFLAGS + + # Files to ignore in find ... statements + +@@ -501,7 +506,6 @@ + $(Q)rm -f .tmp_quiet_recordmcount + + PHONY += outputmakefile +-# Before starting out-of-tree build, make sure the source tree is clean. + # outputmakefile generates a Makefile in the output directory, if using a + # separate output directory. This allows convenient use of make in the + # output directory. +@@ -509,15 +513,6 @@ + # ignore whole output directory + outputmakefile: + ifdef building_out_of_srctree +- $(Q)if [ -f $(srctree)/.config -o \ +- -d $(srctree)/include/config -o \ +- -d $(srctree)/arch/$(SRCARCH)/include/generated ]; then \ +- echo >&2 "***"; \ +- echo >&2 "*** The source tree is not clean, please run 'make$(if $(findstring command line, $(origin ARCH)), ARCH=$(ARCH)) mrproper'"; \ +- echo >&2 "*** in $(abs_srctree)";\ +- echo >&2 "***"; \ +- false; \ +- fi + $(Q)ln -fsn $(srctree) source + $(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkmakefile $(srctree) + $(Q)test -e .gitignore || \ +@@ -549,7 +544,7 @@ + # and from include/config/auto.conf.cmd to detect the compiler upgrade. + CC_VERSION_TEXT = $(shell $(CC) --version 2>/dev/null | head -n 1) + +-ifdef config-build ++ifeq ($(config-targets),1) + # =========================================================================== + # *config targets only - make sure prerequisites are updated, and descend + # in scripts/kconfig to make the *config target +@@ -560,13 +555,13 @@ + include arch/$(SRCARCH)/Makefile + export KBUILD_DEFCONFIG KBUILD_KCONFIG CC_VERSION_TEXT + +-config: outputmakefile scripts_basic FORCE ++config: scripts_basic outputmakefile FORCE + $(Q)$(MAKE) $(build)=scripts/kconfig $@ + +-%config: outputmakefile scripts_basic FORCE ++%config: scripts_basic outputmakefile FORCE + $(Q)$(MAKE) $(build)=scripts/kconfig $@ + +-else #!config-build ++else + # =========================================================================== + # Build targets only - this includes vmlinux, arch specific targets, clean + # targets and others. In general all targets except *config targets. +@@ -599,7 +594,7 @@ + # in addition to whatever we do anyway. + # Just "make" or "make all" shall build modules as well + +-ifneq ($(filter all _all modules nsdeps,$(MAKECMDGOALS)),) ++ifneq ($(filter all _all modules,$(MAKECMDGOALS)),) + KBUILD_MODULES := 1 + endif + +@@ -609,7 +604,7 @@ + + export KBUILD_MODULES KBUILD_BUILTIN + +-ifdef need-config ++ifeq ($(dot-config),1) + include include/config/auto.conf + endif + +@@ -650,10 +645,15 @@ + export RETPOLINE_CFLAGS + export RETPOLINE_VDSO_CFLAGS + ++# The arch Makefile can set ARCH_{CPP,A,C}FLAGS to override the default ++# values of the respective KBUILD_* variables ++ARCH_CPPFLAGS := ++ARCH_AFLAGS := ++ARCH_CFLAGS := + include arch/$(SRCARCH)/Makefile + +-ifdef need-config +-ifdef may-sync-config ++ifeq ($(dot-config),1) ++ifeq ($(may-sync-config),1) + # Read in dependencies to all Kconfig* files, make sure to run syncconfig if + # changes are detected. This should be included after arch/$(SRCARCH)/Makefile + # because some architectures define CROSS_COMPILE there. +@@ -676,7 +676,7 @@ + # The syncconfig should be executed only once to make all the targets. + %/auto.conf %/auto.conf.cmd %/tristate.conf: $(KCONFIG_CONFIG) + $(Q)$(MAKE) -f $(srctree)/Makefile syncconfig +-else # !may-sync-config ++else + # External modules and some install targets need include/generated/autoconf.h + # and include/config/auto.conf but do not care if they are up-to-date. + # Use auto.conf to trigger the test +@@ -692,7 +692,7 @@ + /bin/false) + + endif # may-sync-config +-endif # need-config ++endif # $(dot-config) + + KBUILD_CFLAGS += $(call cc-option,-fno-delete-null-pointer-checks,) + KBUILD_CFLAGS += $(call cc-disable-warning,frame-address,) +@@ -700,12 +700,10 @@ + KBUILD_CFLAGS += $(call cc-disable-warning, format-overflow) + KBUILD_CFLAGS += $(call cc-disable-warning, address-of-packed-member) + +-ifdef CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE +-KBUILD_CFLAGS += -O2 +-else ifdef CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE_O3 +-KBUILD_CFLAGS += -O3 +-else ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE +-KBUILD_CFLAGS += -Os ++ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE ++KBUILD_CFLAGS += -Os ++else ++KBUILD_CFLAGS += -O2 + endif + + ifdef CONFIG_CC_DISABLE_WARN_MAYBE_UNINITIALIZED +@@ -753,11 +751,6 @@ + # These warnings generated too much noise in a regular build. + # Use make W=1 to enable them (see scripts/Makefile.extrawarn) + KBUILD_CFLAGS += -Wno-unused-but-set-variable +- +-# Warn about unmarked fall-throughs in switch statement. +-# Disabled for clang while comment to attribute conversion happens and +-# https://github.com/ClangBuiltLinux/linux/issues/636 is discussed. +-KBUILD_CFLAGS += $(call cc-option,-Wimplicit-fallthrough,) + endif + + KBUILD_CFLAGS += $(call cc-disable-warning, unused-const-variable) +@@ -852,6 +845,9 @@ + # warn about C99 declaration after statement + KBUILD_CFLAGS += -Wdeclaration-after-statement + ++# Warn about unmarked fall-throughs in switch statement. ++KBUILD_CFLAGS += $(call cc-option,-Wimplicit-fallthrough,) ++ + # Variable Length Arrays (VLAs) should not be used anywhere in the kernel + KBUILD_CFLAGS += -Wvla + +@@ -897,14 +893,18 @@ + KBUILD_CFLAGS += $(call cc-option,-fcf-protection=none) + endif + ++# use the deterministic mode of AR if available ++KBUILD_ARFLAGS := $(call ar-option,D) ++ + include scripts/Makefile.kasan + include scripts/Makefile.extrawarn + include scripts/Makefile.ubsan + +-# Add user supplied CPPFLAGS, AFLAGS and CFLAGS as the last assignments +-KBUILD_CPPFLAGS += $(KCPPFLAGS) +-KBUILD_AFLAGS += $(KAFLAGS) +-KBUILD_CFLAGS += $(KCFLAGS) ++# Add any arch overrides and user supplied CPPFLAGS, AFLAGS and CFLAGS as the ++# last assignments ++KBUILD_CPPFLAGS += $(ARCH_CPPFLAGS) $(KCPPFLAGS) ++KBUILD_AFLAGS += $(ARCH_AFLAGS) $(KAFLAGS) ++KBUILD_CFLAGS += $(ARCH_CFLAGS) $(KCFLAGS) + + KBUILD_LDFLAGS_MODULE += --build-id + LDFLAGS_vmlinux += --build-id +@@ -913,13 +913,6 @@ + LDFLAGS_vmlinux += $(call ld-option, -X,) + endif + +-ifeq ($(CONFIG_RELR),y) +-LDFLAGS_vmlinux += --pack-dyn-relocs=relr +-endif +- +-# make the checker run with the right architecture +-CHECKFLAGS += --arch=$(ARCH) +- + # insure the checker run with the right endianness + CHECKFLAGS += $(if $(CONFIG_CPU_BIG_ENDIAN),-mbig-endian,-mlittle-endian) + +@@ -1010,7 +1003,7 @@ + + PHONY += prepare0 + +-export MODORDER := $(extmod-prefix)modules.order ++export MODORDER := $(if $(KBUILD_EXTMOD),$(KBUILD_EXTMOD)/)modules.order + + ifeq ($(KBUILD_EXTMOD),) + core-y += kernel/ certs/ mm/ fs/ ipc/ security/ crypto/ block/ +@@ -1023,9 +1016,6 @@ + $(patsubst %/,%,$(filter %/, $(init-) $(core-) \ + $(drivers-) $(net-) $(libs-) $(virt-)))) + +-build-dirs := $(vmlinux-dirs) +-clean-dirs := $(vmlinux-alldirs) +- + init-y := $(patsubst %/, %/built-in.a, $(init-y)) + core-y := $(patsubst %/, %/built-in.a, $(core-y)) + drivers-y := $(patsubst %/, %/built-in.a, $(drivers-y)) +@@ -1040,7 +1030,7 @@ + export KBUILD_VMLINUX_LIBS := $(libs-y1) + export KBUILD_LDS := arch/$(SRCARCH)/kernel/vmlinux.lds + export LDFLAGS_vmlinux +-# used by scripts/Makefile.package ++# used by scripts/package/Makefile + export KBUILD_ALLDIRS := $(sort $(filter-out arch/%,$(vmlinux-alldirs)) LICENSES arch include scripts tools) + + vmlinux-deps := $(KBUILD_LDS) $(KBUILD_VMLINUX_OBJS) $(KBUILD_VMLINUX_LIBS) +@@ -1048,7 +1038,7 @@ + # Recurse until adjust_autoksyms.sh is satisfied + PHONY += autoksyms_recursive + ifdef CONFIG_TRIM_UNUSED_KSYMS +-autoksyms_recursive: descend modules.order ++autoksyms_recursive: $(vmlinux-deps) modules.order + $(Q)$(CONFIG_SHELL) $(srctree)/scripts/adjust_autoksyms.sh \ + "$(MAKE) -f $(srctree)/Makefile vmlinux" + endif +@@ -1080,7 +1070,17 @@ + + # The actual objects are generated when descending, + # make sure no implicit rule kicks in +-$(sort $(vmlinux-deps)): descend ; ++$(sort $(vmlinux-deps)): $(vmlinux-dirs) ; ++ ++# Handle descending into subdirectories listed in $(vmlinux-dirs) ++# Preset locale variables to speed up the build process. Limit locale ++# tweaks to this spot to avoid wrong language settings when running ++# make menuconfig etc. ++# Error messages still appears in the original language ++ ++PHONY += $(vmlinux-dirs) ++$(vmlinux-dirs): prepare ++ $(Q)$(MAKE) $(build)=$@ need-builtin=1 need-modorder=1 + + filechk_kernel.release = \ + echo "$(KERNELVERSION)$$($(CONFIG_SHELL) $(srctree)/scripts/setlocalversion $(srctree))" +@@ -1102,9 +1102,24 @@ + # archprepare is used in arch Makefiles and when processed asm symlink, + # version.h and scripts_basic is processed / created. + +-PHONY += prepare archprepare ++PHONY += prepare archprepare prepare3 + +-archprepare: outputmakefile archheaders archscripts scripts include/config/kernel.release \ ++# prepare3 is used to check if we are building in a separate output directory, ++# and if so do: ++# 1) Check that make has not been executed in the kernel src $(srctree) ++prepare3: include/config/kernel.release ++ifdef building_out_of_srctree ++ @$(kecho) ' Using $(srctree) as source for kernel' ++ $(Q)if [ -f $(srctree)/.config -o \ ++ -d $(srctree)/include/config -o \ ++ -d $(srctree)/arch/$(SRCARCH)/include/generated ]; then \ ++ echo >&2 " $(srctree) is not clean, please run 'make ARCH=$(ARCH) mrproper'"; \ ++ echo >&2 " in the '$(srctree)' directory.";\ ++ /bin/false; \ ++ fi; ++endif ++ ++archprepare: archheaders archscripts scripts prepare3 outputmakefile \ + asm-generic $(version_h) $(autoksyms_h) include/generated/utsrelease.h + + prepare0: archprepare +@@ -1220,15 +1235,16 @@ + kselftest: + $(Q)$(MAKE) -C $(srctree)/tools/testing/selftests run_tests + +-kselftest-%: FORCE +- $(Q)$(MAKE) -C $(srctree)/tools/testing/selftests $* ++PHONY += kselftest-clean ++kselftest-clean: ++ $(Q)$(MAKE) -C $(srctree)/tools/testing/selftests clean + + PHONY += kselftest-merge + kselftest-merge: + $(if $(wildcard $(objtree)/.config),, $(error No .config exists, config your kernel first!)) + $(Q)find $(srctree)/tools/testing/selftests -name config | \ + xargs $(srctree)/scripts/kconfig/merge_config.sh -m $(objtree)/.config +- $(Q)$(MAKE) -f $(srctree)/Makefile olddefconfig ++ +$(Q)$(MAKE) -f $(srctree)/Makefile olddefconfig + + # --------------------------------------------------------------------------- + # Devicetree files +@@ -1239,11 +1255,11 @@ + + ifneq ($(dtstree),) + +-%.dtb: include/config/kernel.release scripts_dtc ++%.dtb: prepare3 scripts_dtc + $(Q)$(MAKE) $(build)=$(dtstree) $(dtstree)/$@ + + PHONY += dtbs dtbs_install dt_binding_check +-dtbs dtbs_check: include/config/kernel.release scripts_dtc ++dtbs dtbs_check: prepare3 scripts_dtc + $(Q)$(MAKE) $(build)=$(dtstree) + + dtbs_check: export CHECK_DTBS=1 +@@ -1282,16 +1298,17 @@ + + PHONY += modules + modules: $(if $(KBUILD_BUILTIN),vmlinux) modules.order modules.builtin ++ @$(kecho) ' Building modules, stage 2.'; + $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost + $(Q)$(CONFIG_SHELL) $(srctree)/scripts/modules-check.sh + +-modules.order: descend +- $(Q)$(AWK) '!x[$$0]++' $(addsuffix /$@, $(build-dirs)) > $@ ++modules.order: $(vmlinux-dirs) ++ $(Q)$(AWK) '!x[$$0]++' $(addsuffix /$@, $(vmlinux-dirs)) > $@ + +-modbuiltin-dirs := $(addprefix _modbuiltin_, $(build-dirs)) ++modbuiltin-dirs := $(addprefix _modbuiltin_, $(vmlinux-dirs)) + + modules.builtin: $(modbuiltin-dirs) +- $(Q)$(AWK) '!x[$$0]++' $(addsuffix /$@, $(build-dirs)) > $@ ++ $(Q)$(AWK) '!x[$$0]++' $(addsuffix /$@, $(vmlinux-dirs)) > $@ + + PHONY += $(modbuiltin-dirs) + # tristate.conf is not included from this Makefile. Add it as a prerequisite +@@ -1364,14 +1381,12 @@ + + # Directories & files removed with 'make mrproper' + MRPROPER_DIRS += include/config include/generated \ +- arch/$(SRCARCH)/include/generated .tmp_objdiff \ +- debian/ snap/ tar-install/ ++ arch/$(SRCARCH)/include/generated .tmp_objdiff + MRPROPER_FILES += .config .config.old .version \ + Module.symvers \ + signing_key.pem signing_key.priv signing_key.x509 \ + x509.genkey extra_certificates signing_key.x509.keyid \ +- signing_key.x509.signer vmlinux-gdb.py \ +- *.spec ++ signing_key.x509.signer vmlinux-gdb.py + + # Directories & files removed with 'make distclean' + DISTCLEAN_DIRS += +@@ -1381,8 +1396,11 @@ + # + clean: rm-dirs := $(CLEAN_DIRS) + clean: rm-files := $(CLEAN_FILES) ++clean-dirs := $(addprefix _clean_, . $(vmlinux-alldirs)) + +-PHONY += archclean vmlinuxclean ++PHONY += $(clean-dirs) clean archclean vmlinuxclean ++$(clean-dirs): ++ $(Q)$(MAKE) $(clean)=$(patsubst _clean_%,%,$@) + + vmlinuxclean: + $(Q)$(CONFIG_SHELL) $(srctree)/scripts/link-vmlinux.sh clean +@@ -1423,11 +1441,13 @@ + + # Packaging of the kernel to various formats + # --------------------------------------------------------------------------- ++package-dir := scripts/package + + %src-pkg: FORCE +- $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.package $@ ++ $(Q)$(MAKE) $(build)=$(package-dir) $@ + %pkg: include/config/kernel.release FORCE +- $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.package $@ ++ $(Q)$(MAKE) $(build)=$(package-dir) $@ ++ + + # Brief documentation of the typical targets used + # --------------------------------------------------------------------------- +@@ -1480,9 +1500,6 @@ + @echo ' headerdep - Detect inclusion cycles in headers' + @echo ' coccicheck - Check with Coccinelle' + @echo '' +- @echo 'Tools:' +- @echo ' nsdeps - Generate missing symbol namespace dependencies' +- @echo '' + @echo 'Kernel selftest:' + @echo ' kselftest - Build and run kernel selftest (run as root)' + @echo ' Build, install, and boot kernel before' +@@ -1493,10 +1510,8 @@ + @echo '' + @$(if $(dtstree), \ + echo 'Devicetree:'; \ +- echo '* dtbs - Build device tree blobs for enabled boards'; \ +- echo ' dtbs_install - Install dtbs to $(INSTALL_DTBS_PATH)'; \ +- echo ' dt_binding_check - Validate device tree binding documents'; \ +- echo ' dtbs_check - Validate device tree source files';\ ++ echo '* dtbs - Build device tree blobs for enabled boards'; \ ++ echo ' dtbs_install - Install dtbs to $(INSTALL_DTBS_PATH)'; \ + echo '') + + @echo 'Userspace tools targets:' +@@ -1504,7 +1519,7 @@ + @echo ' or "cd tools; make help"' + @echo '' + @echo 'Kernel packaging:' +- @$(MAKE) -f $(srctree)/scripts/Makefile.package help ++ @$(MAKE) $(build)=$(package-dir) help + @echo '' + @echo 'Documentation targets:' + @$(MAKE) -f $(srctree)/Documentation/Makefile dochelp +@@ -1529,7 +1544,7 @@ + @echo ' make C=1 [targets] Check re-compiled c source with $$CHECK (sparse by default)' + @echo ' make C=2 [targets] Force check of all c source with $$CHECK' + @echo ' make RECORDMCOUNT_WARN=1 [targets] Warn about ignored mcount sections' +- @echo ' make W=n [targets] Enable extra build checks, n=1,2,3 where' ++ @echo ' make W=n [targets] Enable extra gcc checks, n=1,2,3 where' + @echo ' 1: warnings which may be relevant and do not occur too often' + @echo ' 2: warnings which occur quite often but may still be relevant' + @echo ' 3: more obscure warnings, can most likely be ignored' +@@ -1558,7 +1573,7 @@ + DOC_TARGETS := xmldocs latexdocs pdfdocs htmldocs epubdocs cleandocs \ + linkcheckdocs dochelp refcheckdocs + PHONY += $(DOC_TARGETS) +-$(DOC_TARGETS): ++$(DOC_TARGETS): scripts_basic FORCE + $(Q)$(MAKE) $(build)=Documentation $@ + + # Misc +@@ -1603,9 +1618,13 @@ + echo " is missing; modules will have no dependencies and modversions."; \ + echo ) + +-build-dirs := $(KBUILD_EXTMOD) +-PHONY += modules +-modules: descend $(objtree)/Module.symvers ++module-dirs := $(addprefix _module_,$(KBUILD_EXTMOD)) ++PHONY += $(module-dirs) modules ++$(module-dirs): prepare $(objtree)/Module.symvers ++ $(Q)$(MAKE) $(build)=$(patsubst _module_%,%,$@) need-modorder=1 ++ ++modules: $(module-dirs) ++ @$(kecho) ' Building modules, stage 2.'; + $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost + + PHONY += modules_install +@@ -1621,12 +1640,13 @@ + _emodinst_post: _emodinst_ + $(call cmd,depmod) + +-clean-dirs := $(KBUILD_EXTMOD) +-clean: rm-files := $(KBUILD_EXTMOD)/Module.symvers ++clean-dirs := $(addprefix _clean_,$(KBUILD_EXTMOD)) + +-PHONY += / +-/: +- @echo >&2 '"$(MAKE) /" is no longer supported. Please use "$(MAKE) ./" instead.' ++PHONY += $(clean-dirs) clean ++$(clean-dirs): ++ $(Q)$(MAKE) $(clean)=$(patsubst _clean_%,%,$@) ++ ++clean: rm-files := $(KBUILD_EXTMOD)/Module.symvers + + PHONY += help + help: +@@ -1641,21 +1661,6 @@ + PHONY += prepare + endif # KBUILD_EXTMOD + +-# Handle descending into subdirectories listed in $(build-dirs) +-# Preset locale variables to speed up the build process. Limit locale +-# tweaks to this spot to avoid wrong language settings when running +-# make menuconfig etc. +-# Error messages still appears in the original language +-PHONY += descend $(build-dirs) +-descend: $(build-dirs) +-$(build-dirs): prepare +- $(Q)$(MAKE) $(build)=$@ single-build=$(single-build) need-builtin=1 need-modorder=1 +- +-clean-dirs := $(addprefix _clean_, $(clean-dirs)) +-PHONY += $(clean-dirs) clean +-$(clean-dirs): +- $(Q)$(MAKE) $(clean)=$(patsubst _clean_%,%,$@) +- + clean: $(clean-dirs) + $(call cmd,rmdirs) + $(call cmd,rmfiles) +@@ -1664,7 +1669,7 @@ + -o -name '*.ko.*' \ + -o -name '*.dtb' -o -name '*.dtb.S' -o -name '*.dt.yaml' \ + -o -name '*.dwo' -o -name '*.lst' \ +- -o -name '*.su' -o -name '*.mod' -o -name '*.ns_deps' \ ++ -o -name '*.su' -o -name '*.mod' \ + -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \ + -o -name '*.lex.c' -o -name '*.tab.[ch]' \ + -o -name '*.asn1.[ch]' \ +@@ -1677,20 +1682,11 @@ + # Generate tags for editors + # --------------------------------------------------------------------------- + quiet_cmd_tags = GEN $@ +- cmd_tags = $(BASH) $(srctree)/scripts/tags.sh $@ ++ cmd_tags = $(CONFIG_SHELL) $(srctree)/scripts/tags.sh $@ + + tags TAGS cscope gtags: FORCE + $(call cmd,tags) + +-# Script to generate missing namespace dependencies +-# --------------------------------------------------------------------------- +- +-PHONY += nsdeps +- +-nsdeps: modules +- $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost nsdeps +- $(Q)$(CONFIG_SHELL) $(srctree)/scripts/$@ +- + # Scripts to check various things for consistency + # --------------------------------------------------------------------------- + +@@ -1707,7 +1703,7 @@ + | xargs $(PERL) -w $(srctree)/scripts/checkversion.pl + + coccicheck: +- $(Q)$(BASH) $(srctree)/scripts/$@ ++ $(Q)$(CONFIG_SHELL) $(srctree)/scripts/$@ + + namespacecheck: + $(PERL) $(srctree)/scripts/namespace.pl +@@ -1755,47 +1751,45 @@ + + # Single targets + # --------------------------------------------------------------------------- +-# To build individual files in subdirectories, you can do like this: +-# +-# make foo/bar/baz.s +-# +-# The supported suffixes for single-target are listed in 'single-targets' +-# +-# To build only under specific subdirectories, you can do like this: +-# +-# make foo/bar/baz/ +- +-ifdef single-build +- +-single-all := $(filter $(single-targets), $(MAKECMDGOALS)) +- +-# .ko is special because modpost is needed +-single-ko := $(sort $(filter %.ko, $(single-all))) +-single-no-ko := $(sort $(patsubst %.ko,%.mod, $(single-all))) +- +-$(single-ko): single_modpost +- @: +-$(single-no-ko): descend +- @: +- ++# Single targets are compatible with: ++# - build with mixed source and output ++# - build with separate output dir 'make O=...' ++# - external modules ++# ++# target-dir => where to store outputfile ++# build-dir => directory in kernel source tree to use ++ ++build-target = $(if $(KBUILD_EXTMOD), $(KBUILD_EXTMOD)/)$@ ++build-dir = $(patsubst %/,%,$(dir $(build-target))) ++ ++%.i: prepare FORCE ++ $(Q)$(MAKE) $(build)=$(build-dir) $(build-target) ++%.ll: prepare FORCE ++ $(Q)$(MAKE) $(build)=$(build-dir) $(build-target) ++%.lst: prepare FORCE ++ $(Q)$(MAKE) $(build)=$(build-dir) $(build-target) ++%.o: prepare FORCE ++ $(Q)$(MAKE) $(build)=$(build-dir) $(build-target) ++%.s: prepare FORCE ++ $(Q)$(MAKE) $(build)=$(build-dir) $(build-target) ++%.symtypes: prepare FORCE ++ $(Q)$(MAKE) $(build)=$(build-dir) $(build-target) + ifeq ($(KBUILD_EXTMOD),) +-# For the single build of in-tree modules, use a temporary file to avoid ++# For the single build of an in-tree module, use a temporary file to avoid + # the situation of modules_install installing an invalid modules.order. +-MODORDER := .modules.tmp ++%.ko: MODORDER := .modules.tmp + endif +- +-PHONY += single_modpost +-single_modpost: $(single-no-ko) +- $(Q){ $(foreach m, $(single-ko), echo $(extmod-prefix)$m;) } > $(MODORDER) ++%.ko: prepare FORCE ++ $(Q)$(MAKE) $(build)=$(build-dir) $(build-target:.ko=.mod) ++ $(Q)echo $(build-target) > $(MODORDER) + $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost + +-KBUILD_MODULES := 1 +- +-export KBUILD_SINGLE_TARGETS := $(addprefix $(extmod-prefix), $(single-no-ko)) ++# Modules ++PHONY += / ++/: ./ + +-single-build = $(if $(filter-out $@/, $(single-no-ko)),1) +- +-endif ++%/: prepare FORCE ++ $(Q)$(MAKE) KBUILD_MODULES=1 $(build)=$(build-dir) need-modorder=1 + + # FIXME Should go into a make.lib or something + # =========================================================================== +@@ -1816,9 +1810,9 @@ + + -include $(foreach f,$(existing-targets),$(dir $(f)).$(notdir $(f)).cmd) + +-endif # config-targets +-endif # mixed-build +-endif # need-sub-make ++endif # ifeq ($(config-targets),1) ++endif # ifeq ($(mixed-targets),1) ++endif # need-sub-make + + PHONY += FORCE + FORCE: diff --git a/kernel/tools/cpupowertools/pspec.xml b/kernel/tools/cpupowertools/pspec.xml index 393619c4..894ce3fd 100644 --- a/kernel/tools/cpupowertools/pspec.xml +++ b/kernel/tools/cpupowertools/pspec.xml @@ -12,19 +12,22 @@ app:console

CPU power management tools cpupowertools contains utilities to manage power management and frequency scaling policies of modern CPUs. - https://www.kernel.org/pub/linux/kernel/v4.x/linux-4.19.tar.gz + https://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/linux-5.4.tar.gz pciutils-devel - patches/linux/patch-4.19.56.xz - - - - - patches/mageia_4_19/fs-aufs-4.19.patch - patches/mageia_4_19/fs-aufs-4.19-modular.patch + patches/linux/patch-5.4.6.xz + + patches/mageia/fs-aufs-5.4.patch + patches/mageia/fs-aufs-5.4-modular.patch + patches/mageia/fs-vboxsf.patch + patches/mageia/CVE-2019-12379.patch + + + + patches/pisilinux/revert-Makefile.patch @@ -41,6 +44,7 @@ /usr/include /usr/share/man/man1/cpupower* /usr/share/locale/*/*/cpupower.mo + /usr/share/bash-completion/completions/cpupower cpupower.conf.d @@ -51,6 +55,13 @@ + + 2019-12-27 + 5.4.6 + Version bump + Idris Kalp + idriskalp@gmail.com + 2019-06-26 4.19.56 From c8e969d3f4839a38cc2e7c7b1de94332834f0b6f Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 19:01:22 +0300 Subject: [PATCH 154/160] mkinitcpio rebuild --- kernel/tools/mkinitcpio/pspec.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/kernel/tools/mkinitcpio/pspec.xml b/kernel/tools/mkinitcpio/pspec.xml index 8c5b7a32..44c10bb8 100644 --- a/kernel/tools/mkinitcpio/pspec.xml +++ b/kernel/tools/mkinitcpio/pspec.xml @@ -51,6 +51,13 @@ + + 2019-12-27 + 19.1 + Rebuild + Idris Kalp + idriskalp@gmail.com + 2018-07-15 19.1 From 12f97a745987ee7c16e3bb6b6136f4e7023d4876 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 19:06:03 +0300 Subject: [PATCH 155/160] busybox 1.30.1 --- system/base/busybox/files/config | 1416 ++++++++++++++++-------------- system/base/busybox/pspec.xml | 11 +- 2 files changed, 777 insertions(+), 650 deletions(-) diff --git a/system/base/busybox/files/config b/system/base/busybox/files/config index 97f598fc..69253a64 100644 --- a/system/base/busybox/files/config +++ b/system/base/busybox/files/config @@ -1,58 +1,41 @@ # # Automatically generated make config: don't edit -# Busybox version: 1.24.1 -# Fri Jan 29 23:10:26 2016 +# Busybox version: 1.30.1 +# Sun Sep 1 18:10:19 2019 # CONFIG_HAVE_DOT_CONFIG=y # -# Busybox Settings -# - -# -# General Configuration +# Settings # CONFIG_DESKTOP=y # CONFIG_EXTRA_COMPAT is not set -# CONFIG_INCLUDE_SUSv2 is not set -# CONFIG_USE_PORTABLE_CODE is not set -CONFIG_PLATFORM_LINUX=y -# CONFIG_FEATURE_BUFFERS_USE_MALLOC is not set -CONFIG_FEATURE_BUFFERS_GO_ON_STACK=y -# CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set -CONFIG_SHOW_USAGE=y -# CONFIG_FEATURE_VERBOSE_USAGE is not set -CONFIG_FEATURE_COMPRESS_USAGE=y -# CONFIG_FEATURE_INSTALLER is not set -# CONFIG_INSTALL_NO_USR is not set -# CONFIG_LOCALE_SUPPORT is not set -CONFIG_UNICODE_SUPPORT=y -# CONFIG_UNICODE_USING_LOCALE is not set -# CONFIG_FEATURE_CHECK_UNICODE_IN_ENV is not set -CONFIG_SUBST_WCHAR=63 -CONFIG_LAST_SUPPORTED_WCHAR=767 -# CONFIG_UNICODE_COMBINING_WCHARS is not set -# CONFIG_UNICODE_WIDE_WCHARS is not set -# CONFIG_UNICODE_BIDI_SUPPORT is not set -# CONFIG_UNICODE_NEUTRAL_TABLE is not set -# CONFIG_UNICODE_PRESERVE_BROKEN is not set -# CONFIG_PAM is not set -CONFIG_FEATURE_USE_SENDFILE=y +# CONFIG_FEDORA_COMPAT is not set +CONFIG_INCLUDE_SUSv2=y CONFIG_LONG_OPTS=y -# CONFIG_FEATURE_DEVPTS is not set -# CONFIG_FEATURE_CLEAN_UP is not set +CONFIG_SHOW_USAGE=y +CONFIG_FEATURE_VERBOSE_USAGE=y +CONFIG_FEATURE_COMPRESS_USAGE=y +CONFIG_LFS=y +# CONFIG_PAM is not set +CONFIG_FEATURE_DEVPTS=y # CONFIG_FEATURE_UTMP is not set # CONFIG_FEATURE_WTMP is not set -# CONFIG_FEATURE_PIDFILE is not set -CONFIG_PID_FILE_PATH="" +CONFIG_FEATURE_PIDFILE=y +CONFIG_PID_FILE_PATH="/run" +CONFIG_BUSYBOX=y +# CONFIG_FEATURE_SHOW_SCRIPT is not set +CONFIG_FEATURE_INSTALLER=y +# CONFIG_INSTALL_NO_USR is not set CONFIG_FEATURE_SUID=y -# CONFIG_FEATURE_SUID_CONFIG is not set -# CONFIG_FEATURE_SUID_CONFIG_QUIET is not set -# CONFIG_SELINUX is not set -# CONFIG_FEATURE_PREFER_APPLETS is not set +CONFIG_FEATURE_SUID_CONFIG=y +CONFIG_FEATURE_SUID_CONFIG_QUIET=y +CONFIG_FEATURE_PREFER_APPLETS=y CONFIG_BUSYBOX_EXEC_PATH="/proc/self/exe" -# CONFIG_FEATURE_SYSLOG is not set -# CONFIG_FEATURE_HAVE_RPC is not set +# CONFIG_SELINUX is not set +# CONFIG_FEATURE_CLEAN_UP is not set +CONFIG_FEATURE_SYSLOG=y +CONFIG_PLATFORM_LINUX=y # # Build Options @@ -61,20 +44,35 @@ CONFIG_STATIC=y # CONFIG_PIE is not set # CONFIG_NOMMU is not set # CONFIG_BUILD_LIBBUSYBOX is not set +# CONFIG_FEATURE_LIBBUSYBOX_STATIC is not set # CONFIG_FEATURE_INDIVIDUAL is not set # CONFIG_FEATURE_SHARED_BUSYBOX is not set -CONFIG_LFS=y CONFIG_CROSS_COMPILER_PREFIX="" CONFIG_SYSROOT="" CONFIG_EXTRA_CFLAGS="" CONFIG_EXTRA_LDFLAGS="" CONFIG_EXTRA_LDLIBS="" +# CONFIG_USE_PORTABLE_CODE is not set +CONFIG_STACK_OPTIMIZATION_386=y + +# +# Installation Options ("make install" behavior) +# +# CONFIG_INSTALL_APPLET_SYMLINKS is not set +# CONFIG_INSTALL_APPLET_HARDLINKS is not set +# CONFIG_INSTALL_APPLET_SCRIPT_WRAPPERS is not set +CONFIG_INSTALL_APPLET_DONT=y +# CONFIG_INSTALL_SH_APPLET_SYMLINK is not set +# CONFIG_INSTALL_SH_APPLET_HARDLINK is not set +# CONFIG_INSTALL_SH_APPLET_SCRIPT_WRAPPER is not set +CONFIG_PREFIX="./_install" # # Debugging Options # # CONFIG_DEBUG is not set # CONFIG_DEBUG_PESSIMIZE is not set +# CONFIG_DEBUG_SANITIZE is not set # CONFIG_UNIT_TEST is not set # CONFIG_WERROR is not set CONFIG_NO_DEBUG_LIB=y @@ -82,44 +80,50 @@ CONFIG_NO_DEBUG_LIB=y # CONFIG_EFENCE is not set # -# Installation Options ("make install" behavior) +# Library Tuning # -CONFIG_INSTALL_APPLET_SYMLINKS=y -# CONFIG_INSTALL_APPLET_HARDLINKS is not set -# CONFIG_INSTALL_APPLET_SCRIPT_WRAPPERS is not set -# CONFIG_INSTALL_APPLET_DONT is not set -# CONFIG_INSTALL_SH_APPLET_SYMLINK is not set -# CONFIG_INSTALL_SH_APPLET_HARDLINK is not set -# CONFIG_INSTALL_SH_APPLET_SCRIPT_WRAPPER is not set -CONFIG_PREFIX="./_install" - -# -# Busybox Library Tuning -# -CONFIG_FEATURE_SYSTEMD=y +# CONFIG_FEATURE_USE_BSS_TAIL is not set +CONFIG_FLOAT_DURATION=y CONFIG_FEATURE_RTMINMAX=y +CONFIG_FEATURE_RTMINMAX_USE_LIBC_DEFINITIONS=y +CONFIG_FEATURE_BUFFERS_USE_MALLOC=y +# CONFIG_FEATURE_BUFFERS_GO_ON_STACK is not set +# CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set CONFIG_PASSWORD_MINLEN=6 CONFIG_MD5_SMALL=1 -CONFIG_SHA3_SMALL=1 -# CONFIG_FEATURE_FAST_TOP is not set +CONFIG_SHA3_SMALL=0 +CONFIG_FEATURE_FAST_TOP=y # CONFIG_FEATURE_ETC_NETWORKS is not set -CONFIG_FEATURE_USE_TERMIOS=y +# CONFIG_FEATURE_ETC_SERVICES is not set CONFIG_FEATURE_EDITING=y CONFIG_FEATURE_EDITING_MAX_LEN=1024 # CONFIG_FEATURE_EDITING_VI is not set -CONFIG_FEATURE_EDITING_HISTORY=15 -# CONFIG_FEATURE_EDITING_SAVEHISTORY is not set -# CONFIG_FEATURE_EDITING_SAVE_ON_EXIT is not set -# CONFIG_FEATURE_REVERSE_SEARCH is not set +CONFIG_FEATURE_EDITING_HISTORY=255 +CONFIG_FEATURE_EDITING_SAVEHISTORY=y +CONFIG_FEATURE_EDITING_SAVE_ON_EXIT=y +CONFIG_FEATURE_REVERSE_SEARCH=y CONFIG_FEATURE_TAB_COMPLETION=y -# CONFIG_FEATURE_USERNAME_COMPLETION is not set +CONFIG_FEATURE_USERNAME_COMPLETION=y CONFIG_FEATURE_EDITING_FANCY_PROMPT=y +CONFIG_FEATURE_EDITING_WINCH=y # CONFIG_FEATURE_EDITING_ASK_TERMINAL is not set -CONFIG_FEATURE_NON_POSIX_CP=y +CONFIG_LOCALE_SUPPORT=y +CONFIG_UNICODE_SUPPORT=y +CONFIG_UNICODE_USING_LOCALE=y +# CONFIG_FEATURE_CHECK_UNICODE_IN_ENV is not set +CONFIG_SUBST_WCHAR=63 +CONFIG_LAST_SUPPORTED_WCHAR=767 +# CONFIG_UNICODE_COMBINING_WCHARS is not set +# CONFIG_UNICODE_WIDE_WCHARS is not set +# CONFIG_UNICODE_BIDI_SUPPORT is not set +# CONFIG_UNICODE_NEUTRAL_TABLE is not set +# CONFIG_UNICODE_PRESERVE_BROKEN is not set +# CONFIG_FEATURE_NON_POSIX_CP is not set # CONFIG_FEATURE_VERBOSE_CP_MESSAGE is not set +CONFIG_FEATURE_USE_SENDFILE=y CONFIG_FEATURE_COPYBUF_KB=4 CONFIG_FEATURE_SKIP_ROOTFS=y -CONFIG_MONOTONIC_SYSCALL=y +# CONFIG_MONOTONIC_SYSCALL is not set CONFIG_IOCTL_HEX2STR_ERROR=y CONFIG_FEATURE_HWIB=y @@ -131,182 +135,209 @@ CONFIG_FEATURE_HWIB=y # Archival Utilities # CONFIG_FEATURE_SEAMLESS_XZ=y -# CONFIG_FEATURE_SEAMLESS_LZMA is not set -# CONFIG_FEATURE_SEAMLESS_BZ2 is not set -# CONFIG_FEATURE_SEAMLESS_GZ is not set -# CONFIG_FEATURE_SEAMLESS_Z is not set -# CONFIG_AR is not set -# CONFIG_FEATURE_AR_LONG_FILENAMES is not set -# CONFIG_FEATURE_AR_CREATE is not set -# CONFIG_UNCOMPRESS is not set +CONFIG_FEATURE_SEAMLESS_LZMA=y +CONFIG_FEATURE_SEAMLESS_BZ2=y +CONFIG_FEATURE_SEAMLESS_GZ=y +CONFIG_FEATURE_SEAMLESS_Z=y +CONFIG_AR=y +CONFIG_FEATURE_AR_LONG_FILENAMES=y +CONFIG_FEATURE_AR_CREATE=y +CONFIG_UNCOMPRESS=y CONFIG_GUNZIP=y +CONFIG_ZCAT=y +CONFIG_FEATURE_GUNZIP_LONG_OPTIONS=y CONFIG_BUNZIP2=y -# CONFIG_UNLZMA is not set -# CONFIG_FEATURE_LZMA_FAST is not set -# CONFIG_LZMA is not set +CONFIG_BZCAT=y +CONFIG_UNLZMA=y +CONFIG_LZCAT=y +CONFIG_LZMA=y CONFIG_UNXZ=y +CONFIG_XZCAT=y CONFIG_XZ=y CONFIG_BZIP2=y +CONFIG_BZIP2_SMALL=8 +CONFIG_FEATURE_BZIP2_DECOMPRESS=y CONFIG_CPIO=y CONFIG_FEATURE_CPIO_O=y # CONFIG_FEATURE_CPIO_P is not set # CONFIG_DPKG is not set # CONFIG_DPKG_DEB is not set -# CONFIG_FEATURE_DPKG_DEB_EXTRACT_ONLY is not set CONFIG_GZIP=y # CONFIG_FEATURE_GZIP_LONG_OPTIONS is not set CONFIG_GZIP_FAST=0 -# CONFIG_FEATURE_GZIP_LEVELS is not set +CONFIG_FEATURE_GZIP_LEVELS=y +CONFIG_FEATURE_GZIP_DECOMPRESS=y # CONFIG_LZOP is not set +CONFIG_UNLZOP=y +CONFIG_LZOPCAT=y # CONFIG_LZOP_COMPR_HIGH is not set # CONFIG_RPM is not set -# CONFIG_RPM2CPIO is not set +CONFIG_RPM2CPIO=y CONFIG_TAR=y -CONFIG_FEATURE_TAR_CREATE=y -# CONFIG_FEATURE_TAR_AUTODETECT is not set -# CONFIG_FEATURE_TAR_FROM is not set -# CONFIG_FEATURE_TAR_OLDGNU_COMPATIBILITY is not set -# CONFIG_FEATURE_TAR_OLDSUN_COMPATIBILITY is not set -CONFIG_FEATURE_TAR_GNU_EXTENSIONS=y CONFIG_FEATURE_TAR_LONG_OPTIONS=y -# CONFIG_FEATURE_TAR_TO_COMMAND is not set -# CONFIG_FEATURE_TAR_UNAME_GNAME is not set +CONFIG_FEATURE_TAR_CREATE=y +CONFIG_FEATURE_TAR_AUTODETECT=y +CONFIG_FEATURE_TAR_FROM=y +CONFIG_FEATURE_TAR_OLDGNU_COMPATIBILITY=y +CONFIG_FEATURE_TAR_OLDSUN_COMPATIBILITY=y +CONFIG_FEATURE_TAR_GNU_EXTENSIONS=y +CONFIG_FEATURE_TAR_TO_COMMAND=y +CONFIG_FEATURE_TAR_UNAME_GNAME=y # CONFIG_FEATURE_TAR_NOPRESERVE_TIME is not set # CONFIG_FEATURE_TAR_SELINUX is not set CONFIG_UNZIP=y +CONFIG_FEATURE_UNZIP_CDF=y +CONFIG_FEATURE_UNZIP_BZIP2=y +CONFIG_FEATURE_UNZIP_LZMA=y +CONFIG_FEATURE_UNZIP_XZ=y +CONFIG_FEATURE_LZMA_FAST=y # # Coreutils # CONFIG_BASENAME=y CONFIG_CAT=y +CONFIG_FEATURE_CATN=y +CONFIG_FEATURE_CATV=y +CONFIG_CHGRP=y +CONFIG_CHMOD=y +CONFIG_CHOWN=y +CONFIG_FEATURE_CHOWN_LONG_OPTIONS=y +CONFIG_CHROOT=y +CONFIG_CKSUM=y +CONFIG_COMM=y +CONFIG_CP=y +CONFIG_FEATURE_CP_LONG_OPTIONS=y +CONFIG_FEATURE_CP_REFLINK=y +CONFIG_CUT=y CONFIG_DATE=y CONFIG_FEATURE_DATE_ISOFMT=y # CONFIG_FEATURE_DATE_NANO is not set CONFIG_FEATURE_DATE_COMPAT=y CONFIG_DD=y CONFIG_FEATURE_DD_SIGNAL_HANDLING=y -# CONFIG_FEATURE_DD_THIRD_STATUS_LINE is not set -# CONFIG_FEATURE_DD_IBS_OBS is not set +CONFIG_FEATURE_DD_THIRD_STATUS_LINE=y +CONFIG_FEATURE_DD_IBS_OBS=y CONFIG_FEATURE_DD_STATUS=y -# CONFIG_HOSTID is not set -# CONFIG_ID is not set +CONFIG_DF=y +CONFIG_FEATURE_DF_FANCY=y +CONFIG_DIRNAME=y +CONFIG_DOS2UNIX=y +CONFIG_UNIX2DOS=y +CONFIG_DU=y +CONFIG_FEATURE_DU_DEFAULT_BLOCKSIZE_1K=y +CONFIG_ECHO=y +CONFIG_FEATURE_FANCY_ECHO=y +CONFIG_ENV=y +CONFIG_EXPAND=y +CONFIG_UNEXPAND=y +CONFIG_EXPR=y +CONFIG_EXPR_MATH_SUPPORT_64=y +CONFIG_FACTOR=y +CONFIG_FALSE=y +CONFIG_FOLD=y +CONFIG_FSYNC=y +CONFIG_HEAD=y +CONFIG_FEATURE_FANCY_HEAD=y +CONFIG_HOSTID=y +CONFIG_ID=y CONFIG_GROUPS=y +CONFIG_INSTALL=y +CONFIG_FEATURE_INSTALL_LONG_OPTIONS=y +CONFIG_LINK=y +CONFIG_LN=y +CONFIG_LOGNAME=y +CONFIG_LS=y +CONFIG_FEATURE_LS_FILETYPES=y +CONFIG_FEATURE_LS_FOLLOWLINKS=y +CONFIG_FEATURE_LS_RECURSIVE=y +CONFIG_FEATURE_LS_WIDTH=y +CONFIG_FEATURE_LS_SORTFILES=y +CONFIG_FEATURE_LS_TIMESTAMPS=y +CONFIG_FEATURE_LS_USERNAME=y +CONFIG_FEATURE_LS_COLOR=y +CONFIG_FEATURE_LS_COLOR_IS_DEFAULT=y +CONFIG_MD5SUM=y +CONFIG_SHA1SUM=y +CONFIG_SHA256SUM=y +CONFIG_SHA512SUM=y +CONFIG_SHA3SUM=y + +# +# Common options for md5sum, sha1sum, sha256sum, sha512sum, sha3sum +# +CONFIG_FEATURE_MD5_SHA1_SUM_CHECK=y +CONFIG_MKDIR=y +CONFIG_MKFIFO=y +CONFIG_MKNOD=y +CONFIG_MKTEMP=y +CONFIG_MV=y +CONFIG_NICE=y +CONFIG_NL=y +CONFIG_NOHUP=y +CONFIG_NPROC=y +CONFIG_OD=y +CONFIG_PASTE=y +CONFIG_PRINTENV=y +CONFIG_PRINTF=y +CONFIG_PWD=y +CONFIG_READLINK=y +CONFIG_FEATURE_READLINK_FOLLOW=y +CONFIG_REALPATH=y +CONFIG_RM=y +CONFIG_RMDIR=y +CONFIG_SEQ=y +CONFIG_SHRED=y CONFIG_SHUF=y +CONFIG_SLEEP=y +CONFIG_FEATURE_FANCY_SLEEP=y +CONFIG_SORT=y +CONFIG_FEATURE_SORT_BIG=y +# CONFIG_FEATURE_SORT_OPTIMIZE_MEMORY is not set +CONFIG_SPLIT=y +CONFIG_FEATURE_SPLIT_FANCY=y +CONFIG_STAT=y +CONFIG_FEATURE_STAT_FORMAT=y +CONFIG_FEATURE_STAT_FILESYSTEM=y +CONFIG_STTY=y +CONFIG_SUM=y CONFIG_SYNC=y CONFIG_FEATURE_SYNC_FANCY=y +CONFIG_TAC=y +CONFIG_TAIL=y +CONFIG_FEATURE_FANCY_TAIL=y +CONFIG_TEE=y +CONFIG_FEATURE_TEE_USE_BLOCK_IO=y CONFIG_TEST=y -# CONFIG_FEATURE_TEST_64 is not set +CONFIG_TEST1=y +CONFIG_TEST2=y +CONFIG_FEATURE_TEST_64=y +CONFIG_TIMEOUT=y CONFIG_TOUCH=y CONFIG_FEATURE_TOUCH_NODEREF=y CONFIG_FEATURE_TOUCH_SUSV3=y CONFIG_TR=y CONFIG_FEATURE_TR_CLASSES=y CONFIG_FEATURE_TR_EQUIV=y -CONFIG_TRUNCATE=y -CONFIG_UNLINK=y -CONFIG_BASE64=y -# CONFIG_WHO is not set -# CONFIG_USERS is not set -# CONFIG_CAL is not set -# CONFIG_CATV is not set -CONFIG_CHGRP=y -CONFIG_CHMOD=y -CONFIG_CHOWN=y -# CONFIG_FEATURE_CHOWN_LONG_OPTIONS is not set -CONFIG_CHROOT=y -# CONFIG_CKSUM is not set -# CONFIG_COMM is not set -CONFIG_CP=y -# CONFIG_FEATURE_CP_LONG_OPTIONS is not set -CONFIG_CUT=y -CONFIG_DF=y -# CONFIG_FEATURE_DF_FANCY is not set -CONFIG_DIRNAME=y -# CONFIG_DOS2UNIX is not set -# CONFIG_UNIX2DOS is not set -CONFIG_DU=y -CONFIG_FEATURE_DU_DEFAULT_BLOCKSIZE_1K=y -CONFIG_ECHO=y -CONFIG_FEATURE_FANCY_ECHO=y -# CONFIG_ENV is not set -# CONFIG_FEATURE_ENV_LONG_OPTIONS is not set -# CONFIG_EXPAND is not set -# CONFIG_FEATURE_EXPAND_LONG_OPTIONS is not set -# CONFIG_EXPR is not set -# CONFIG_EXPR_MATH_SUPPORT_64 is not set -CONFIG_FALSE=y -# CONFIG_FOLD is not set -# CONFIG_FSYNC is not set -CONFIG_HEAD=y -CONFIG_FEATURE_FANCY_HEAD=y -# CONFIG_INSTALL is not set -# CONFIG_FEATURE_INSTALL_LONG_OPTIONS is not set -CONFIG_LN=y -# CONFIG_LOGNAME is not set -CONFIG_LS=y -CONFIG_FEATURE_LS_FILETYPES=y -CONFIG_FEATURE_LS_FOLLOWLINKS=y -CONFIG_FEATURE_LS_RECURSIVE=y -CONFIG_FEATURE_LS_SORTFILES=y -CONFIG_FEATURE_LS_TIMESTAMPS=y -CONFIG_FEATURE_LS_USERNAME=y -CONFIG_FEATURE_LS_COLOR=y -# CONFIG_FEATURE_LS_COLOR_IS_DEFAULT is not set -# CONFIG_MD5SUM is not set -CONFIG_MKDIR=y -# CONFIG_FEATURE_MKDIR_LONG_OPTIONS is not set -# CONFIG_MKFIFO is not set -CONFIG_MKNOD=y -CONFIG_MV=y -# CONFIG_FEATURE_MV_LONG_OPTIONS is not set -# CONFIG_NICE is not set -# CONFIG_NOHUP is not set -# CONFIG_OD is not set -# CONFIG_PRINTENV is not set -CONFIG_PRINTF=y -CONFIG_PWD=y -CONFIG_READLINK=y -# CONFIG_FEATURE_READLINK_FOLLOW is not set -# CONFIG_REALPATH is not set -CONFIG_RM=y -CONFIG_RMDIR=y -# CONFIG_FEATURE_RMDIR_LONG_OPTIONS is not set -CONFIG_SEQ=y -CONFIG_SHA1SUM=y -# CONFIG_SHA256SUM is not set -# CONFIG_SHA512SUM is not set -# CONFIG_SHA3SUM is not set -CONFIG_SLEEP=y -# CONFIG_FEATURE_FANCY_SLEEP is not set -# CONFIG_FEATURE_FLOAT_SLEEP is not set -CONFIG_SORT=y -CONFIG_FEATURE_SORT_BIG=y -# CONFIG_SPLIT is not set -# CONFIG_FEATURE_SPLIT_FANCY is not set -CONFIG_STAT=y -CONFIG_FEATURE_STAT_FORMAT=y -# CONFIG_STTY is not set -# CONFIG_SUM is not set -# CONFIG_TAC is not set -CONFIG_TAIL=y -CONFIG_FEATURE_FANCY_TAIL=y -CONFIG_TEE=y -# CONFIG_FEATURE_TEE_USE_BLOCK_IO is not set CONFIG_TRUE=y -# CONFIG_TTY is not set +CONFIG_TRUNCATE=y +CONFIG_TTY=y CONFIG_UNAME=y -CONFIG_UNAME_OSNAME="Pisi GNU/Linux" -# CONFIG_UNEXPAND is not set -# CONFIG_FEATURE_UNEXPAND_LONG_OPTIONS is not set +CONFIG_UNAME_OSNAME="GNU/Linux" +CONFIG_BB_ARCH=y CONFIG_UNIQ=y +CONFIG_UNLINK=y CONFIG_USLEEP=y -# CONFIG_UUDECODE is not set -# CONFIG_UUENCODE is not set +CONFIG_UUDECODE=y +CONFIG_BASE64=y +CONFIG_UUENCODE=y CONFIG_WC=y -# CONFIG_FEATURE_WC_LARGE is not set -# CONFIG_WHOAMI is not set -# CONFIG_YES is not set +CONFIG_FEATURE_WC_LARGE=y +# CONFIG_WHO is not set +# CONFIG_W is not set +# CONFIG_USERS is not set +CONFIG_WHOAMI=y +CONFIG_YES=y # # Common options @@ -318,80 +349,77 @@ CONFIG_FEATURE_VERBOSE=y # CONFIG_FEATURE_PRESERVE_HARDLINKS=y -# -# Common options for ls, more and telnet -# -CONFIG_FEATURE_AUTOWIDTH=y - # # Common options for df, du, ls # CONFIG_FEATURE_HUMAN_READABLE=y -# -# Common options for md5sum, sha1sum, sha256sum, sha512sum, sha3sum -# -CONFIG_FEATURE_MD5_SHA1_SUM_CHECK=y - # # Console Utilities # -# CONFIG_CHVT is not set -# CONFIG_FGCONSOLE is not set +CONFIG_CHVT=y CONFIG_CLEAR=y -# CONFIG_DEALLOCVT is not set -# CONFIG_DUMPKMAP is not set -# CONFIG_KBD_MODE is not set +CONFIG_DEALLOCVT=y +CONFIG_DUMPKMAP=y +CONFIG_FGCONSOLE=y +CONFIG_KBD_MODE=y CONFIG_LOADFONT=y -CONFIG_LOADKMAP=y -# CONFIG_OPENVT is not set -CONFIG_RESET=y -# CONFIG_RESIZE is not set -# CONFIG_FEATURE_RESIZE_PRINT is not set -# CONFIG_SETCONSOLE is not set -# CONFIG_FEATURE_SETCONSOLE_LONG_OPTIONS is not set -# CONFIG_SETFONT is not set +CONFIG_SETFONT=y # CONFIG_FEATURE_SETFONT_TEXTUAL_MAP is not set CONFIG_DEFAULT_SETFONT_DIR="" -CONFIG_SETKEYCODES=y -# CONFIG_SETLOGCONS is not set -# CONFIG_SHOWKEY is not set # # Common options for loadfont and setfont # CONFIG_FEATURE_LOADFONT_PSF2=y CONFIG_FEATURE_LOADFONT_RAW=y +CONFIG_LOADKMAP=y +CONFIG_OPENVT=y +CONFIG_RESET=y +CONFIG_RESIZE=y +CONFIG_FEATURE_RESIZE_PRINT=y +CONFIG_SETCONSOLE=y +CONFIG_FEATURE_SETCONSOLE_LONG_OPTIONS=y +CONFIG_SETKEYCODES=y +CONFIG_SETLOGCONS=y +CONFIG_SHOWKEY=y # # Debian Utilities # -CONFIG_MKTEMP=y -# CONFIG_PIPE_PROGRESS is not set -# CONFIG_RUN_PARTS is not set -# CONFIG_FEATURE_RUN_PARTS_LONG_OPTIONS is not set -# CONFIG_FEATURE_RUN_PARTS_FANCY is not set -# CONFIG_START_STOP_DAEMON is not set -# CONFIG_FEATURE_START_STOP_DAEMON_FANCY is not set -# CONFIG_FEATURE_START_STOP_DAEMON_LONG_OPTIONS is not set +CONFIG_PIPE_PROGRESS=y +CONFIG_RUN_PARTS=y +CONFIG_FEATURE_RUN_PARTS_LONG_OPTIONS=y +CONFIG_FEATURE_RUN_PARTS_FANCY=y +CONFIG_START_STOP_DAEMON=y +CONFIG_FEATURE_START_STOP_DAEMON_LONG_OPTIONS=y +CONFIG_FEATURE_START_STOP_DAEMON_FANCY=y CONFIG_WHICH=y +# +# klibc-utils +# +# CONFIG_MINIPS is not set +# CONFIG_NUKE is not set +CONFIG_RESUME=y +CONFIG_RUN_INIT=y + # # Editors # CONFIG_AWK=y -# CONFIG_FEATURE_AWK_LIBM is not set +CONFIG_FEATURE_AWK_LIBM=y CONFIG_FEATURE_AWK_GNU_EXTENSIONS=y -# CONFIG_CMP is not set -# CONFIG_DIFF is not set -# CONFIG_FEATURE_DIFF_LONG_OPTIONS is not set -# CONFIG_FEATURE_DIFF_DIR is not set -# CONFIG_ED is not set -# CONFIG_PATCH is not set +CONFIG_CMP=y +CONFIG_DIFF=y +CONFIG_FEATURE_DIFF_LONG_OPTIONS=y +CONFIG_FEATURE_DIFF_DIR=y +CONFIG_ED=y +CONFIG_PATCH=y CONFIG_SED=y CONFIG_VI=y CONFIG_FEATURE_VI_MAX_LEN=4096 -CONFIG_FEATURE_VI_8BIT=y +# CONFIG_FEATURE_VI_8BIT is not set CONFIG_FEATURE_VI_COLON=y CONFIG_FEATURE_VI_YANKMARK=y CONFIG_FEATURE_VI_SEARCH=y @@ -402,7 +430,7 @@ CONFIG_FEATURE_VI_READONLY=y CONFIG_FEATURE_VI_SETOPTS=y CONFIG_FEATURE_VI_SET=y CONFIG_FEATURE_VI_WIN_RESIZE=y -# CONFIG_FEATURE_VI_ASK_TERMINAL is not set +CONFIG_FEATURE_VI_ASK_TERMINAL=y CONFIG_FEATURE_VI_UNDO=y CONFIG_FEATURE_VI_UNDO_QUEUE=y CONFIG_FEATURE_VI_UNDO_QUEUE_MAX=256 @@ -417,6 +445,7 @@ CONFIG_FEATURE_FIND_MTIME=y CONFIG_FEATURE_FIND_MMIN=y CONFIG_FEATURE_FIND_PERM=y CONFIG_FEATURE_FIND_TYPE=y +CONFIG_FEATURE_FIND_EXECUTABLE=y CONFIG_FEATURE_FIND_XDEV=y CONFIG_FEATURE_FIND_MAXDEPTH=y CONFIG_FEATURE_FIND_NEWER=y @@ -430,14 +459,15 @@ CONFIG_FEATURE_FIND_DEPTH=y CONFIG_FEATURE_FIND_PAREN=y CONFIG_FEATURE_FIND_SIZE=y CONFIG_FEATURE_FIND_PRUNE=y -# CONFIG_FEATURE_FIND_DELETE is not set +CONFIG_FEATURE_FIND_QUIT=y +CONFIG_FEATURE_FIND_DELETE=y CONFIG_FEATURE_FIND_PATH=y CONFIG_FEATURE_FIND_REGEX=y # CONFIG_FEATURE_FIND_CONTEXT is not set -# CONFIG_FEATURE_FIND_LINKS is not set +CONFIG_FEATURE_FIND_LINKS=y CONFIG_GREP=y -CONFIG_FEATURE_GREP_EGREP_ALIAS=y -CONFIG_FEATURE_GREP_FGREP_ALIAS=y +CONFIG_EGREP=y +CONFIG_FGREP=y CONFIG_FEATURE_GREP_CONTEXT=y CONFIG_XARGS=y CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION=y @@ -445,142 +475,132 @@ CONFIG_FEATURE_XARGS_SUPPORT_QUOTES=y CONFIG_FEATURE_XARGS_SUPPORT_TERMOPT=y CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM=y CONFIG_FEATURE_XARGS_SUPPORT_REPL_STR=y +CONFIG_FEATURE_XARGS_SUPPORT_PARALLEL=y +CONFIG_FEATURE_XARGS_SUPPORT_ARGS_FILE=y # # Init Utilities # -# CONFIG_BOOTCHARTD is not set -# CONFIG_FEATURE_BOOTCHARTD_BLOATED_HEADER is not set -# CONFIG_FEATURE_BOOTCHARTD_CONFIG_FILE is not set +CONFIG_BOOTCHARTD=y +CONFIG_FEATURE_BOOTCHARTD_BLOATED_HEADER=y +CONFIG_FEATURE_BOOTCHARTD_CONFIG_FILE=y CONFIG_HALT=y +CONFIG_POWEROFF=y +CONFIG_REBOOT=y +# CONFIG_FEATURE_WAIT_FOR_INIT is not set # CONFIG_FEATURE_CALL_TELINIT is not set CONFIG_TELINIT_PATH="" -# CONFIG_INIT is not set -# CONFIG_FEATURE_USE_INITTAB is not set +CONFIG_INIT=y +CONFIG_LINUXRC=y +CONFIG_FEATURE_USE_INITTAB=y # CONFIG_FEATURE_KILL_REMOVED is not set CONFIG_FEATURE_KILL_DELAY=0 -# CONFIG_FEATURE_INIT_SCTTY is not set +CONFIG_FEATURE_INIT_SCTTY=y # CONFIG_FEATURE_INIT_SYSLOG is not set -# CONFIG_FEATURE_EXTRA_QUIET is not set -# CONFIG_FEATURE_INIT_COREDUMPS is not set -# CONFIG_FEATURE_INITRD is not set -CONFIG_INIT_TERMINAL_TYPE="" -# CONFIG_MESG is not set -# CONFIG_FEATURE_MESG_ENABLE_ONLY_GROUP is not set +CONFIG_FEATURE_INIT_QUIET=y +CONFIG_FEATURE_INIT_COREDUMPS=y +CONFIG_INIT_TERMINAL_TYPE="linux" +CONFIG_FEATURE_INIT_MODIFY_CMDLINE=y # # Login/Password Management Utilities # -CONFIG_ADD_SHELL=y -CONFIG_REMOVE_SHELL=y -# CONFIG_FEATURE_SHADOWPASSWDS is not set -# CONFIG_USE_BB_PWD_GRP is not set -# CONFIG_USE_BB_SHADOW is not set +CONFIG_FEATURE_SHADOWPASSWDS=y +CONFIG_USE_BB_PWD_GRP=y +CONFIG_USE_BB_SHADOW=y CONFIG_USE_BB_CRYPT=y -# CONFIG_USE_BB_CRYPT_SHA is not set -# CONFIG_ADDUSER is not set -# CONFIG_FEATURE_ADDUSER_LONG_OPTIONS is not set -# CONFIG_FEATURE_CHECK_NAMES is not set -CONFIG_LAST_ID=0 -CONFIG_FIRST_SYSTEM_ID=0 -CONFIG_LAST_SYSTEM_ID=0 -# CONFIG_ADDGROUP is not set -# CONFIG_FEATURE_ADDGROUP_LONG_OPTIONS is not set -# CONFIG_FEATURE_ADDUSER_TO_GROUP is not set -# CONFIG_DELUSER is not set -# CONFIG_DELGROUP is not set -# CONFIG_FEATURE_DEL_USER_FROM_GROUP is not set -# CONFIG_GETTY is not set -# CONFIG_LOGIN is not set +CONFIG_USE_BB_CRYPT_SHA=y +# CONFIG_ADD_SHELL is not set +# CONFIG_REMOVE_SHELL is not set +CONFIG_ADDGROUP=y +CONFIG_FEATURE_ADDUSER_TO_GROUP=y +CONFIG_ADDUSER=y +CONFIG_FEATURE_CHECK_NAMES=y +CONFIG_LAST_ID=60000 +CONFIG_FIRST_SYSTEM_ID=100 +CONFIG_LAST_SYSTEM_ID=999 +CONFIG_CHPASSWD=y +CONFIG_FEATURE_DEFAULT_PASSWD_ALGO="des" +CONFIG_CRYPTPW=y +CONFIG_MKPASSWD=y +CONFIG_DELUSER=y +CONFIG_DELGROUP=y +CONFIG_FEATURE_DEL_USER_FROM_GROUP=y +CONFIG_GETTY=y +CONFIG_LOGIN=y # CONFIG_LOGIN_SESSION_AS_CHILD is not set -# CONFIG_LOGIN_SCRIPTS is not set -# CONFIG_FEATURE_NOLOGIN is not set -# CONFIG_FEATURE_SECURETTY is not set -# CONFIG_PASSWD is not set -# CONFIG_FEATURE_PASSWD_WEAK_CHECK is not set -# CONFIG_CRYPTPW is not set -# CONFIG_CHPASSWD is not set -CONFIG_FEATURE_DEFAULT_PASSWD_ALGO="" -# CONFIG_SU is not set -# CONFIG_FEATURE_SU_SYSLOG is not set -# CONFIG_FEATURE_SU_CHECKS_SHELLS is not set -# CONFIG_SULOGIN is not set -# CONFIG_VLOCK is not set +CONFIG_LOGIN_SCRIPTS=y +CONFIG_FEATURE_NOLOGIN=y +CONFIG_FEATURE_SECURETTY=y +CONFIG_PASSWD=y +CONFIG_FEATURE_PASSWD_WEAK_CHECK=y +CONFIG_SU=y +CONFIG_FEATURE_SU_SYSLOG=y +CONFIG_FEATURE_SU_CHECKS_SHELLS=y +# CONFIG_FEATURE_SU_BLANK_PW_NEEDS_SECURE_TTY is not set +CONFIG_SULOGIN=y +CONFIG_VLOCK=y # # Linux Ext2 FS Progs # -# CONFIG_CHATTR is not set +CONFIG_CHATTR=y CONFIG_FSCK=y -# CONFIG_LSATTR is not set -# CONFIG_TUNE2FS is not set +CONFIG_LSATTR=y +CONFIG_TUNE2FS=y # # Linux Module Utilities # -CONFIG_MODINFO=y -# CONFIG_MODPROBE_SMALL is not set -# CONFIG_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE is not set -# CONFIG_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED is not set +CONFIG_MODPROBE_SMALL=y +CONFIG_DEPMOD=y CONFIG_INSMOD=y -CONFIG_RMMOD=y CONFIG_LSMOD=y # CONFIG_FEATURE_LSMOD_PRETTY_2_6_OUTPUT is not set +CONFIG_MODINFO=y CONFIG_MODPROBE=y -CONFIG_FEATURE_MODPROBE_BLACKLIST=y -# CONFIG_DEPMOD is not set +# CONFIG_FEATURE_MODPROBE_BLACKLIST is not set +CONFIG_RMMOD=y # # Options common to multiple modutils # +CONFIG_FEATURE_CMDLINE_MODULE_OPTIONS=y +CONFIG_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED=y # CONFIG_FEATURE_2_4_MODULES is not set -# CONFIG_FEATURE_INSMOD_TRY_MMAP is not set # CONFIG_FEATURE_INSMOD_VERSION_CHECKING is not set # CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS is not set # CONFIG_FEATURE_INSMOD_LOADINKMEM is not set # CONFIG_FEATURE_INSMOD_LOAD_MAP is not set # CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL is not set # CONFIG_FEATURE_CHECK_TAINTED_MODULE is not set -CONFIG_FEATURE_MODUTILS_ALIAS=y -CONFIG_FEATURE_MODUTILS_SYMBOLS=y +# CONFIG_FEATURE_INSMOD_TRY_MMAP is not set +# CONFIG_FEATURE_MODUTILS_ALIAS is not set +# CONFIG_FEATURE_MODUTILS_SYMBOLS is not set CONFIG_DEFAULT_MODULES_DIR="/lib/modules" CONFIG_DEFAULT_DEPMOD_FILE="modules.dep" # # Linux System Utilities # -CONFIG_BLOCKDEV=y -CONFIG_FATATTR=y -CONFIG_FSTRIM=y -CONFIG_MDEV=y -CONFIG_FEATURE_MDEV_CONF=y -CONFIG_FEATURE_MDEV_RENAME=y -CONFIG_FEATURE_MDEV_RENAME_REGEXP=y -CONFIG_FEATURE_MDEV_EXEC=y -CONFIG_FEATURE_MDEV_LOAD_FIRMWARE=y -CONFIG_MOUNT=y -# CONFIG_FEATURE_MOUNT_FAKE is not set -CONFIG_FEATURE_MOUNT_VERBOSE=y -# CONFIG_FEATURE_MOUNT_HELPERS is not set -CONFIG_FEATURE_MOUNT_LABEL=y -# CONFIG_FEATURE_MOUNT_NFS is not set -CONFIG_FEATURE_MOUNT_CIFS=y -CONFIG_FEATURE_MOUNT_FLAGS=y -CONFIG_FEATURE_MOUNT_FSTAB=y -CONFIG_FEATURE_MOUNT_OTHERTAB=y -# CONFIG_REV is not set -CONFIG_UEVENT=y -# CONFIG_ACPID is not set -# CONFIG_FEATURE_ACPID_COMPAT is not set +CONFIG_ACPID=y +CONFIG_FEATURE_ACPID_COMPAT=y +CONFIG_BLKDISCARD=y CONFIG_BLKID=y -# CONFIG_FEATURE_BLKID_TYPE is not set +CONFIG_FEATURE_BLKID_TYPE=y +CONFIG_BLOCKDEV=y +CONFIG_CAL=y +CONFIG_CHRT=y CONFIG_DMESG=y CONFIG_FEATURE_DMESG_PRETTY=y -# CONFIG_FBSET is not set -# CONFIG_FEATURE_FBSET_FANCY is not set -# CONFIG_FEATURE_FBSET_READMODE is not set -# CONFIG_FDFLUSH is not set -# CONFIG_FDFORMAT is not set +CONFIG_EJECT=y +CONFIG_FEATURE_EJECT_SCSI=y +CONFIG_FALLOCATE=y +CONFIG_FATATTR=y +CONFIG_FBSET=y +CONFIG_FEATURE_FBSET_FANCY=y +CONFIG_FEATURE_FBSET_READMODE=y +CONFIG_FDFORMAT=y CONFIG_FDISK=y # CONFIG_FDISK_SUPPORT_LARGE_DISKS is not set CONFIG_FEATURE_FDISK_WRITABLE=y @@ -588,47 +608,93 @@ CONFIG_FEATURE_FDISK_WRITABLE=y # CONFIG_FEATURE_SGI_LABEL is not set # CONFIG_FEATURE_SUN_LABEL is not set # CONFIG_FEATURE_OSF_LABEL is not set -# CONFIG_FEATURE_GPT_LABEL is not set -# CONFIG_FEATURE_FDISK_ADVANCED is not set +CONFIG_FEATURE_GPT_LABEL=y +CONFIG_FEATURE_FDISK_ADVANCED=y CONFIG_FINDFS=y -# CONFIG_FLOCK is not set -# CONFIG_FREERAMDISK is not set -# CONFIG_FSCK_MINIX is not set -# CONFIG_MKFS_EXT2 is not set -# CONFIG_MKFS_MINIX is not set -# CONFIG_FEATURE_MINIX2 is not set -# CONFIG_MKFS_REISER is not set -# CONFIG_MKFS_VFAT is not set -# CONFIG_GETOPT is not set -# CONFIG_FEATURE_GETOPT_LONG is not set -# CONFIG_HEXDUMP is not set -# CONFIG_FEATURE_HEXDUMP_REVERSE is not set -# CONFIG_HD is not set +CONFIG_FLOCK=y +CONFIG_FDFLUSH=y +CONFIG_FREERAMDISK=y +CONFIG_FSCK_MINIX=y +CONFIG_FSFREEZE=y +CONFIG_FSTRIM=y +CONFIG_GETOPT=y +CONFIG_FEATURE_GETOPT_LONG=y +CONFIG_HEXDUMP=y +CONFIG_FEATURE_HEXDUMP_REVERSE=y +CONFIG_HD=y +CONFIG_XXD=y CONFIG_HWCLOCK=y -# CONFIG_FEATURE_HWCLOCK_LONG_OPTIONS is not set CONFIG_FEATURE_HWCLOCK_ADJTIME_FHS=y -# CONFIG_IPCRM is not set -# CONFIG_IPCS is not set +CONFIG_IONICE=y +CONFIG_IPCRM=y +CONFIG_IPCS=y +# CONFIG_LAST is not set +# CONFIG_FEATURE_LAST_FANCY is not set CONFIG_LOSETUP=y -# CONFIG_LSPCI is not set -# CONFIG_LSUSB is not set -# CONFIG_MKSWAP is not set -# CONFIG_FEATURE_MKSWAP_UUID is not set +CONFIG_LSPCI=y +CONFIG_LSUSB=y +CONFIG_MDEV=y +CONFIG_FEATURE_MDEV_CONF=y +CONFIG_FEATURE_MDEV_RENAME=y +CONFIG_FEATURE_MDEV_RENAME_REGEXP=y +CONFIG_FEATURE_MDEV_EXEC=y +CONFIG_FEATURE_MDEV_LOAD_FIRMWARE=y +CONFIG_MESG=y +CONFIG_FEATURE_MESG_ENABLE_ONLY_GROUP=y +CONFIG_MKE2FS=y +CONFIG_MKFS_EXT2=y +CONFIG_MKFS_MINIX=y +CONFIG_FEATURE_MINIX2=y +# CONFIG_MKFS_REISER is not set +CONFIG_MKDOSFS=y +CONFIG_MKFS_VFAT=y +CONFIG_MKSWAP=y +CONFIG_FEATURE_MKSWAP_UUID=y CONFIG_MORE=y -# CONFIG_PIVOT_ROOT is not set -# CONFIG_RDATE is not set -# CONFIG_RDEV is not set -# CONFIG_READPROFILE is not set -# CONFIG_RTCWAKE is not set -# CONFIG_SCRIPT is not set -# CONFIG_SCRIPTREPLAY is not set -# CONFIG_SETARCH is not set -# CONFIG_SWAPONOFF is not set -# CONFIG_FEATURE_SWAPON_DISCARD is not set -# CONFIG_FEATURE_SWAPON_PRI is not set +CONFIG_MOUNT=y +CONFIG_FEATURE_MOUNT_FAKE=y +CONFIG_FEATURE_MOUNT_VERBOSE=y +CONFIG_FEATURE_MOUNT_HELPERS=y +CONFIG_FEATURE_MOUNT_LABEL=y +# CONFIG_FEATURE_MOUNT_NFS is not set +CONFIG_FEATURE_MOUNT_CIFS=y +CONFIG_FEATURE_MOUNT_FLAGS=y +CONFIG_FEATURE_MOUNT_FSTAB=y +CONFIG_FEATURE_MOUNT_OTHERTAB=y +CONFIG_MOUNTPOINT=y +# CONFIG_NOLOGIN is not set +# CONFIG_NOLOGIN_DEPENDENCIES is not set +CONFIG_NSENTER=y +CONFIG_PIVOT_ROOT=y +CONFIG_RDATE=y +CONFIG_RDEV=y +CONFIG_READPROFILE=y +CONFIG_RENICE=y +CONFIG_REV=y +CONFIG_RTCWAKE=y +CONFIG_SCRIPT=y +CONFIG_SCRIPTREPLAY=y +CONFIG_SETARCH=y +CONFIG_LINUX32=y +CONFIG_LINUX64=y +CONFIG_SETPRIV=y +CONFIG_FEATURE_SETPRIV_DUMP=y +CONFIG_FEATURE_SETPRIV_CAPABILITIES=y +CONFIG_FEATURE_SETPRIV_CAPABILITY_NAMES=y +CONFIG_SETSID=y +CONFIG_SWAPON=y +CONFIG_FEATURE_SWAPON_DISCARD=y +CONFIG_FEATURE_SWAPON_PRI=y +CONFIG_SWAPOFF=y +CONFIG_FEATURE_SWAPONOFF_LABEL=y CONFIG_SWITCH_ROOT=y +CONFIG_TASKSET=y +CONFIG_FEATURE_TASKSET_FANCY=y +CONFIG_UEVENT=y CONFIG_UMOUNT=y CONFIG_FEATURE_UMOUNT_ALL=y +CONFIG_UNSHARE=y +# CONFIG_WALL is not set # # Common options for mount/umount @@ -641,6 +707,7 @@ CONFIG_VOLUMEID=y # # Filesystem/Volume identification # +CONFIG_FEATURE_VOLUMEID_BCACHE=y CONFIG_FEATURE_VOLUMEID_BTRFS=y CONFIG_FEATURE_VOLUMEID_CRAMFS=y CONFIG_FEATURE_VOLUMEID_EXFAT=y @@ -650,376 +717,407 @@ CONFIG_FEATURE_VOLUMEID_FAT=y CONFIG_FEATURE_VOLUMEID_HFS=y CONFIG_FEATURE_VOLUMEID_ISO9660=y CONFIG_FEATURE_VOLUMEID_JFS=y +# CONFIG_FEATURE_VOLUMEID_LFS is not set CONFIG_FEATURE_VOLUMEID_LINUXRAID=y CONFIG_FEATURE_VOLUMEID_LINUXSWAP=y CONFIG_FEATURE_VOLUMEID_LUKS=y +CONFIG_FEATURE_VOLUMEID_MINIX=y CONFIG_FEATURE_VOLUMEID_NILFS=y CONFIG_FEATURE_VOLUMEID_NTFS=y -# CONFIG_FEATURE_VOLUMEID_OCFS2 is not set +CONFIG_FEATURE_VOLUMEID_OCFS2=y CONFIG_FEATURE_VOLUMEID_REISERFS=y CONFIG_FEATURE_VOLUMEID_ROMFS=y -# CONFIG_FEATURE_VOLUMEID_SQUASHFS is not set -# CONFIG_FEATURE_VOLUMEID_SYSV is not set +CONFIG_FEATURE_VOLUMEID_SQUASHFS=y +CONFIG_FEATURE_VOLUMEID_SYSV=y +CONFIG_FEATURE_VOLUMEID_UBIFS=y CONFIG_FEATURE_VOLUMEID_UDF=y CONFIG_FEATURE_VOLUMEID_XFS=y # # Miscellaneous Utilities # -# CONFIG_CONSPY is not set -# CONFIG_CROND is not set -# CONFIG_FEATURE_CROND_D is not set -# CONFIG_FEATURE_CROND_CALL_SENDMAIL is not set -CONFIG_FEATURE_CROND_DIR="" -CONFIG_I2CGET=y -CONFIG_I2CSET=y -CONFIG_I2CDUMP=y -CONFIG_I2CDETECT=y -CONFIG_LESS=y -CONFIG_FEATURE_LESS_MAXLINES=9999999 -CONFIG_FEATURE_LESS_BRACKETS=y -CONFIG_FEATURE_LESS_FLAGS=y -CONFIG_FEATURE_LESS_TRUNCATE=y -# CONFIG_FEATURE_LESS_MARKS is not set -# CONFIG_FEATURE_LESS_REGEXP is not set -# CONFIG_FEATURE_LESS_WINCH is not set -# CONFIG_FEATURE_LESS_ASK_TERMINAL is not set -# CONFIG_FEATURE_LESS_DASHCMD is not set -# CONFIG_FEATURE_LESS_LINENUMS is not set -CONFIG_NANDWRITE=y -CONFIG_NANDDUMP=y -# CONFIG_RFKILL is not set -CONFIG_SETSERIAL=y -# CONFIG_TASKSET is not set -# CONFIG_FEATURE_TASKSET_FANCY is not set -# CONFIG_UBIATTACH is not set -# CONFIG_UBIDETACH is not set -CONFIG_UBIMKVOL=y -CONFIG_UBIRMVOL=y -CONFIG_UBIRSVOL=y -CONFIG_UBIUPDATEVOL=y -# CONFIG_WALL is not set -# CONFIG_ADJTIMEX is not set -# CONFIG_BBCONFIG is not set -# CONFIG_FEATURE_COMPRESS_BBCONFIG is not set -# CONFIG_BEEP is not set -CONFIG_FEATURE_BEEP_FREQ=0 -CONFIG_FEATURE_BEEP_LENGTH_MS=0 -# CONFIG_CHAT is not set -# CONFIG_FEATURE_CHAT_NOFAIL is not set +CONFIG_ADJTIMEX=y +CONFIG_BBCONFIG=y +CONFIG_FEATURE_COMPRESS_BBCONFIG=y +CONFIG_BC=y +CONFIG_DC=y +CONFIG_FEATURE_DC_BIG=y +# CONFIG_FEATURE_DC_LIBM is not set +CONFIG_FEATURE_BC_INTERACTIVE=y +CONFIG_FEATURE_BC_LONG_OPTIONS=y +CONFIG_BEEP=y +CONFIG_FEATURE_BEEP_FREQ=4000 +CONFIG_FEATURE_BEEP_LENGTH_MS=30 +CONFIG_CHAT=y +CONFIG_FEATURE_CHAT_NOFAIL=y # CONFIG_FEATURE_CHAT_TTY_HIFI is not set -# CONFIG_FEATURE_CHAT_IMPLICIT_CR is not set +CONFIG_FEATURE_CHAT_IMPLICIT_CR=y # CONFIG_FEATURE_CHAT_SWALLOW_OPTS is not set # CONFIG_FEATURE_CHAT_SEND_ESCAPES is not set # CONFIG_FEATURE_CHAT_VAR_ABORT_LEN is not set # CONFIG_FEATURE_CHAT_CLR_ABORT is not set -# CONFIG_CHRT is not set -# CONFIG_CRONTAB is not set -# CONFIG_DC is not set -# CONFIG_FEATURE_DC_LIBM is not set +# CONFIG_CONSPY is not set +CONFIG_CROND=y +CONFIG_FEATURE_CROND_D=y +CONFIG_FEATURE_CROND_CALL_SENDMAIL=y +CONFIG_FEATURE_CROND_SPECIAL_TIMES=y +CONFIG_FEATURE_CROND_DIR="/var/spool/cron" +CONFIG_CRONTAB=y # CONFIG_DEVFSD is not set # CONFIG_DEVFSD_MODLOAD is not set # CONFIG_DEVFSD_FG_NP is not set # CONFIG_DEVFSD_VERBOSE is not set # CONFIG_FEATURE_DEVFS is not set # CONFIG_DEVMEM is not set -# CONFIG_EJECT is not set -# CONFIG_FEATURE_EJECT_SCSI is not set -# CONFIG_FBSPLASH is not set -# CONFIG_FLASHCP is not set +CONFIG_FBSPLASH=y +# CONFIG_FLASH_ERASEALL is not set # CONFIG_FLASH_LOCK is not set # CONFIG_FLASH_UNLOCK is not set -# CONFIG_FLASH_ERASEALL is not set -# CONFIG_IONICE is not set -# CONFIG_INOTIFYD is not set -# CONFIG_LAST is not set -# CONFIG_FEATURE_LAST_SMALL is not set -# CONFIG_FEATURE_LAST_FANCY is not set -# CONFIG_HDPARM is not set -# CONFIG_FEATURE_HDPARM_GET_IDENTITY is not set -# CONFIG_FEATURE_HDPARM_HDIO_SCAN_HWIF is not set -# CONFIG_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF is not set -# CONFIG_FEATURE_HDPARM_HDIO_DRIVE_RESET is not set -# CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF is not set -# CONFIG_FEATURE_HDPARM_HDIO_GETSET_DMA is not set -# CONFIG_MAKEDEVS is not set +# CONFIG_FLASHCP is not set +CONFIG_HDPARM=y +CONFIG_FEATURE_HDPARM_GET_IDENTITY=y +CONFIG_FEATURE_HDPARM_HDIO_SCAN_HWIF=y +CONFIG_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF=y +CONFIG_FEATURE_HDPARM_HDIO_DRIVE_RESET=y +CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF=y +CONFIG_FEATURE_HDPARM_HDIO_GETSET_DMA=y +CONFIG_HEXEDIT=y +CONFIG_I2CGET=y +CONFIG_I2CSET=y +CONFIG_I2CDUMP=y +CONFIG_I2CDETECT=y +CONFIG_INOTIFYD=y +CONFIG_LESS=y +CONFIG_FEATURE_LESS_MAXLINES=9999999 +CONFIG_FEATURE_LESS_BRACKETS=y +CONFIG_FEATURE_LESS_FLAGS=y +CONFIG_FEATURE_LESS_TRUNCATE=y +CONFIG_FEATURE_LESS_MARKS=y +CONFIG_FEATURE_LESS_REGEXP=y +CONFIG_FEATURE_LESS_WINCH=y +CONFIG_FEATURE_LESS_ASK_TERMINAL=y +CONFIG_FEATURE_LESS_DASHCMD=y +CONFIG_FEATURE_LESS_LINENUMS=y +CONFIG_FEATURE_LESS_RAW=y +CONFIG_FEATURE_LESS_ENV=y +CONFIG_LSSCSI=y +CONFIG_MAKEDEVS=y # CONFIG_FEATURE_MAKEDEVS_LEAF is not set -# CONFIG_FEATURE_MAKEDEVS_TABLE is not set -# CONFIG_MAN is not set -# CONFIG_MICROCOM is not set -# CONFIG_MOUNTPOINT is not set -# CONFIG_MT is not set -# CONFIG_RAIDAUTORUN is not set -# CONFIG_READAHEAD is not set +CONFIG_FEATURE_MAKEDEVS_TABLE=y +CONFIG_MAN=y +CONFIG_MICROCOM=y +CONFIG_MT=y +# CONFIG_NANDWRITE is not set +# CONFIG_NANDDUMP is not set +CONFIG_PARTPROBE=y +CONFIG_RAIDAUTORUN=y +CONFIG_READAHEAD=y +CONFIG_RFKILL=y # CONFIG_RUNLEVEL is not set -# CONFIG_RX is not set -# CONFIG_SETSID is not set +CONFIG_RX=y +CONFIG_SETFATTR=y +CONFIG_SETSERIAL=y CONFIG_STRINGS=y CONFIG_TIME=y -# CONFIG_TIMEOUT is not set -# CONFIG_TTYSIZE is not set -# CONFIG_VOLNAME is not set -# CONFIG_WATCHDOG is not set +CONFIG_TTYSIZE=y +CONFIG_UBIATTACH=y +CONFIG_UBIDETACH=y +CONFIG_UBIMKVOL=y +CONFIG_UBIRMVOL=y +CONFIG_UBIRSVOL=y +CONFIG_UBIUPDATEVOL=y +CONFIG_UBIRENAME=y +CONFIG_VOLNAME=y +CONFIG_WATCHDOG=y # # Networking Utilities # -# CONFIG_NAMEIF is not set -# CONFIG_FEATURE_NAMEIF_EXTENDED is not set -CONFIG_NBDCLIENT=y -# CONFIG_NC is not set -# CONFIG_NC_SERVER is not set -# CONFIG_NC_EXTRA is not set -# CONFIG_NC_110_COMPAT is not set -CONFIG_PING=y -# CONFIG_PING6 is not set -CONFIG_FEATURE_FANCY_PING=y -# CONFIG_WGET is not set -# CONFIG_FEATURE_WGET_STATUSBAR is not set -# CONFIG_FEATURE_WGET_AUTHENTICATION is not set -# CONFIG_FEATURE_WGET_LONG_OPTIONS is not set -# CONFIG_FEATURE_WGET_TIMEOUT is not set -# CONFIG_FEATURE_WGET_OPENSSL is not set -# CONFIG_FEATURE_WGET_SSL_HELPER is not set -CONFIG_WHOIS=y -# CONFIG_FEATURE_IPV6 is not set -# CONFIG_FEATURE_UNIX_LOCAL is not set -# CONFIG_FEATURE_PREFER_IPV4_ADDRESS is not set +CONFIG_FEATURE_IPV6=y +CONFIG_FEATURE_UNIX_LOCAL=y +CONFIG_FEATURE_PREFER_IPV4_ADDRESS=y # CONFIG_VERBOSE_RESOLUTION_ERRORS is not set -# CONFIG_ARP is not set -# CONFIG_ARPING is not set -# CONFIG_BRCTL is not set -# CONFIG_FEATURE_BRCTL_FANCY is not set -# CONFIG_FEATURE_BRCTL_SHOW is not set -# CONFIG_DNSD is not set -# CONFIG_ETHER_WAKE is not set -# CONFIG_FAKEIDENTD is not set -# CONFIG_FTPD is not set -# CONFIG_FEATURE_FTP_WRITE is not set -# CONFIG_FEATURE_FTPD_ACCEPT_BROKEN_LIST is not set -# CONFIG_FEATURE_FTP_AUTHENTICATION is not set -# CONFIG_FTPGET is not set -# CONFIG_FTPPUT is not set -# CONFIG_FEATURE_FTPGETPUT_LONG_OPTIONS is not set +# CONFIG_FEATURE_TLS_SHA1 is not set +CONFIG_ARP=y +CONFIG_ARPING=y +CONFIG_BRCTL=y +CONFIG_FEATURE_BRCTL_FANCY=y +CONFIG_FEATURE_BRCTL_SHOW=y +CONFIG_DNSD=y +CONFIG_ETHER_WAKE=y +CONFIG_FTPD=y +CONFIG_FEATURE_FTPD_WRITE=y +CONFIG_FEATURE_FTPD_ACCEPT_BROKEN_LIST=y +CONFIG_FEATURE_FTPD_AUTHENTICATION=y +CONFIG_FTPGET=y +CONFIG_FTPPUT=y +CONFIG_FEATURE_FTPGETPUT_LONG_OPTIONS=y CONFIG_HOSTNAME=y -# CONFIG_HTTPD is not set -# CONFIG_FEATURE_HTTPD_RANGES is not set -# CONFIG_FEATURE_HTTPD_SETUID is not set -# CONFIG_FEATURE_HTTPD_BASIC_AUTH is not set -# CONFIG_FEATURE_HTTPD_AUTH_MD5 is not set -# CONFIG_FEATURE_HTTPD_CGI is not set -# CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR is not set -# CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV is not set -# CONFIG_FEATURE_HTTPD_ENCODE_URL_STR is not set -# CONFIG_FEATURE_HTTPD_ERROR_PAGES is not set -# CONFIG_FEATURE_HTTPD_PROXY is not set -# CONFIG_FEATURE_HTTPD_GZIP is not set +CONFIG_DNSDOMAINNAME=y +CONFIG_HTTPD=y +CONFIG_FEATURE_HTTPD_RANGES=y +CONFIG_FEATURE_HTTPD_SETUID=y +CONFIG_FEATURE_HTTPD_BASIC_AUTH=y +CONFIG_FEATURE_HTTPD_AUTH_MD5=y +CONFIG_FEATURE_HTTPD_CGI=y +CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR=y +CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV=y +CONFIG_FEATURE_HTTPD_ENCODE_URL_STR=y +CONFIG_FEATURE_HTTPD_ERROR_PAGES=y +CONFIG_FEATURE_HTTPD_PROXY=y +CONFIG_FEATURE_HTTPD_GZIP=y CONFIG_IFCONFIG=y CONFIG_FEATURE_IFCONFIG_STATUS=y CONFIG_FEATURE_IFCONFIG_SLIP=y CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ=y CONFIG_FEATURE_IFCONFIG_HW=y CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS=y -# CONFIG_IFENSLAVE is not set -# CONFIG_IFPLUGD is not set -# CONFIG_IFUPDOWN is not set -CONFIG_IFUPDOWN_IFSTATE_PATH="" -# CONFIG_FEATURE_IFUPDOWN_IP is not set -# CONFIG_FEATURE_IFUPDOWN_IP_BUILTIN is not set -# CONFIG_FEATURE_IFUPDOWN_IFCONFIG_BUILTIN is not set -# CONFIG_FEATURE_IFUPDOWN_IPV4 is not set -# CONFIG_FEATURE_IFUPDOWN_IPV6 is not set -# CONFIG_FEATURE_IFUPDOWN_MAPPING is not set +CONFIG_IFENSLAVE=y +CONFIG_IFPLUGD=y +CONFIG_IFUP=y +CONFIG_IFDOWN=y +CONFIG_IFUPDOWN_IFSTATE_PATH="/var/run/ifstate" +CONFIG_FEATURE_IFUPDOWN_IP=y +CONFIG_FEATURE_IFUPDOWN_IPV4=y +CONFIG_FEATURE_IFUPDOWN_IPV6=y +CONFIG_FEATURE_IFUPDOWN_MAPPING=y # CONFIG_FEATURE_IFUPDOWN_EXTERNAL_DHCP is not set -# CONFIG_INETD is not set -# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO is not set -# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD is not set -# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_TIME is not set -# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME is not set -# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN is not set +CONFIG_INETD=y +CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO=y +CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD=y +CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_TIME=y +CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME=y +CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN=y # CONFIG_FEATURE_INETD_RPC is not set -# CONFIG_IP is not set -# CONFIG_FEATURE_IP_ADDRESS is not set -# CONFIG_FEATURE_IP_LINK is not set -# CONFIG_FEATURE_IP_ROUTE is not set -CONFIG_FEATURE_IP_ROUTE_DIR="" -# CONFIG_FEATURE_IP_TUNNEL is not set -# CONFIG_FEATURE_IP_RULE is not set -# CONFIG_FEATURE_IP_SHORT_FORMS is not set +CONFIG_IP=y +CONFIG_IPADDR=y +CONFIG_IPLINK=y +CONFIG_IPROUTE=y +CONFIG_IPTUNNEL=y +CONFIG_IPRULE=y +CONFIG_IPNEIGH=y +CONFIG_FEATURE_IP_ADDRESS=y +CONFIG_FEATURE_IP_LINK=y +CONFIG_FEATURE_IP_ROUTE=y +CONFIG_FEATURE_IP_ROUTE_DIR="y" +CONFIG_FEATURE_IP_TUNNEL=y +CONFIG_FEATURE_IP_RULE=y +CONFIG_FEATURE_IP_NEIGH=y # CONFIG_FEATURE_IP_RARE_PROTOCOLS is not set -# CONFIG_IPADDR is not set -# CONFIG_IPLINK is not set -# CONFIG_IPROUTE is not set -# CONFIG_IPTUNNEL is not set -# CONFIG_IPRULE is not set -# CONFIG_IPCALC is not set -# CONFIG_FEATURE_IPCALC_FANCY is not set -# CONFIG_FEATURE_IPCALC_LONG_OPTIONS is not set -# CONFIG_NETSTAT is not set -# CONFIG_FEATURE_NETSTAT_WIDE is not set -# CONFIG_FEATURE_NETSTAT_PRG is not set -# CONFIG_NSLOOKUP is not set -# CONFIG_NTPD is not set -# CONFIG_FEATURE_NTPD_SERVER is not set -# CONFIG_FEATURE_NTPD_CONF is not set -# CONFIG_PSCAN is not set +CONFIG_IPCALC=y +CONFIG_FEATURE_IPCALC_LONG_OPTIONS=y +CONFIG_FEATURE_IPCALC_FANCY=y +CONFIG_FAKEIDENTD=y +CONFIG_NAMEIF=y +# CONFIG_FEATURE_NAMEIF_EXTENDED is not set +CONFIG_NBDCLIENT=y +CONFIG_NC=y +# CONFIG_NETCAT is not set +CONFIG_NC_SERVER=y +CONFIG_NC_EXTRA=y +CONFIG_NC_110_COMPAT=y +CONFIG_NETSTAT=y +CONFIG_FEATURE_NETSTAT_WIDE=y +CONFIG_FEATURE_NETSTAT_PRG=y +CONFIG_NSLOOKUP=y +CONFIG_FEATURE_NSLOOKUP_BIG=y +CONFIG_FEATURE_NSLOOKUP_LONG_OPTIONS=y +CONFIG_NTPD=y +CONFIG_FEATURE_NTPD_SERVER=y +CONFIG_FEATURE_NTPD_CONF=y +CONFIG_FEATURE_NTP_AUTH=y +CONFIG_PING=y +CONFIG_PING6=y +CONFIG_FEATURE_FANCY_PING=y +CONFIG_PSCAN=y CONFIG_ROUTE=y -# CONFIG_SLATTACH is not set -# CONFIG_TCPSVD is not set -# CONFIG_TELNET is not set -# CONFIG_FEATURE_TELNET_TTYPE is not set -# CONFIG_FEATURE_TELNET_AUTOLOGIN is not set -# CONFIG_TELNETD is not set -# CONFIG_FEATURE_TELNETD_STANDALONE is not set +CONFIG_SLATTACH=y +CONFIG_SSL_CLIENT=y +CONFIG_TC=y +CONFIG_FEATURE_TC_INGRESS=y +CONFIG_TCPSVD=y +CONFIG_UDPSVD=y +CONFIG_TELNET=y +CONFIG_FEATURE_TELNET_TTYPE=y +CONFIG_FEATURE_TELNET_AUTOLOGIN=y +CONFIG_FEATURE_TELNET_WIDTH=y +CONFIG_TELNETD=y +CONFIG_FEATURE_TELNETD_STANDALONE=y # CONFIG_FEATURE_TELNETD_INETD_WAIT is not set -# CONFIG_TFTP is not set -# CONFIG_TFTPD is not set -# CONFIG_FEATURE_TFTP_GET is not set -# CONFIG_FEATURE_TFTP_PUT is not set -# CONFIG_FEATURE_TFTP_BLOCKSIZE is not set +CONFIG_TFTP=y # CONFIG_FEATURE_TFTP_PROGRESS_BAR is not set +CONFIG_TFTPD=y +CONFIG_FEATURE_TFTP_GET=y +CONFIG_FEATURE_TFTP_PUT=y +CONFIG_FEATURE_TFTP_BLOCKSIZE=y # CONFIG_TFTP_DEBUG is not set -# CONFIG_TRACEROUTE is not set -# CONFIG_TRACEROUTE6 is not set +CONFIG_TLS=y +CONFIG_TRACEROUTE=y +CONFIG_TRACEROUTE6=y # CONFIG_FEATURE_TRACEROUTE_VERBOSE is not set -# CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE is not set # CONFIG_FEATURE_TRACEROUTE_USE_ICMP is not set -# CONFIG_TUNCTL is not set -# CONFIG_FEATURE_TUNCTL_UG is not set -# CONFIG_UDHCPC6 is not set -# CONFIG_UDHCPD is not set -# CONFIG_DHCPRELAY is not set -# CONFIG_DUMPLEASES is not set -# CONFIG_FEATURE_UDHCPD_WRITE_LEASES_EARLY is not set -# CONFIG_FEATURE_UDHCPD_BASE_IP_ON_MAC is not set -CONFIG_DHCPD_LEASES_FILE="" +CONFIG_TUNCTL=y +CONFIG_FEATURE_TUNCTL_UG=y +CONFIG_VCONFIG=y +CONFIG_WGET=y +CONFIG_FEATURE_WGET_LONG_OPTIONS=y +CONFIG_FEATURE_WGET_STATUSBAR=y +CONFIG_FEATURE_WGET_AUTHENTICATION=y +CONFIG_FEATURE_WGET_TIMEOUT=y +# CONFIG_FEATURE_WGET_HTTPS is not set +# CONFIG_FEATURE_WGET_OPENSSL is not set +CONFIG_WHOIS=y +CONFIG_ZCIP=y +CONFIG_UDHCPD=y +CONFIG_FEATURE_UDHCPD_BASE_IP_ON_MAC=y +CONFIG_FEATURE_UDHCPD_WRITE_LEASES_EARLY=y +CONFIG_DHCPD_LEASES_FILE="/var/lib/misc/udhcpd.leases" +CONFIG_DUMPLEASES=y +CONFIG_DHCPRELAY=y CONFIG_UDHCPC=y CONFIG_FEATURE_UDHCPC_ARPING=y CONFIG_FEATURE_UDHCPC_SANITIZEOPT=y -# CONFIG_FEATURE_UDHCP_PORT is not set -CONFIG_UDHCP_DEBUG=0 +CONFIG_UDHCPC_DEFAULT_SCRIPT="/usr/share/udhcpc/default.script" +CONFIG_UDHCPC6=y +CONFIG_FEATURE_UDHCPC6_RFC3646=y +CONFIG_FEATURE_UDHCPC6_RFC4704=y +CONFIG_FEATURE_UDHCPC6_RFC4833=y +CONFIG_FEATURE_UDHCPC6_RFC5970=y + +# +# Common options for DHCP applets +# +CONFIG_FEATURE_UDHCP_PORT=y +CONFIG_UDHCP_DEBUG=9 +CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS=80 CONFIG_FEATURE_UDHCP_RFC3397=y CONFIG_FEATURE_UDHCP_8021Q=y -CONFIG_UDHCPC_DEFAULT_SCRIPT="/usr/share/udhcpc/default.script" -CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS=80 CONFIG_IFUPDOWN_UDHCPC_CMD_OPTIONS="" -# CONFIG_UDPSVD is not set -# CONFIG_VCONFIG is not set -# CONFIG_ZCIP is not set # # Print Utilities # -# CONFIG_LPD is not set -# CONFIG_LPR is not set -# CONFIG_LPQ is not set +CONFIG_LPD=y +CONFIG_LPR=y +CONFIG_LPQ=y # # Mail Utilities # -# CONFIG_MAKEMIME is not set -CONFIG_FEATURE_MIME_CHARSET="" -# CONFIG_POPMAILDIR is not set -# CONFIG_FEATURE_POPMAILDIR_DELIVERY is not set -# CONFIG_REFORMIME is not set -# CONFIG_FEATURE_REFORMIME_COMPAT is not set -# CONFIG_SENDMAIL is not set +CONFIG_MAKEMIME=y +CONFIG_POPMAILDIR=y +CONFIG_FEATURE_POPMAILDIR_DELIVERY=y +CONFIG_REFORMIME=y +CONFIG_FEATURE_REFORMIME_COMPAT=y +CONFIG_SENDMAIL=y +CONFIG_FEATURE_MIME_CHARSET="us-ascii" # # Process Utilities # -CONFIG_IOSTAT=y -CONFIG_LSOF=y -CONFIG_MPSTAT=y -# CONFIG_NMETER is not set -CONFIG_PMAP=y -CONFIG_POWERTOP=y -CONFIG_PSTREE=y -CONFIG_PWDX=y -# CONFIG_SMEMCAP is not set -# CONFIG_TOP is not set -# CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE is not set -# CONFIG_FEATURE_TOP_CPU_GLOBAL_PERCENTS is not set -# CONFIG_FEATURE_TOP_SMP_CPU is not set -# CONFIG_FEATURE_TOP_DECIMALS is not set -# CONFIG_FEATURE_TOP_SMP_PROCESS is not set -# CONFIG_FEATURE_TOPMEM is not set -# CONFIG_UPTIME is not set -# CONFIG_FEATURE_UPTIME_UTMP_SUPPORT is not set CONFIG_FREE=y CONFIG_FUSER=y +CONFIG_IOSTAT=y CONFIG_KILL=y CONFIG_KILLALL=y -# CONFIG_KILLALL5 is not set -# CONFIG_PGREP is not set +CONFIG_KILLALL5=y +CONFIG_LSOF=y +CONFIG_MPSTAT=y +CONFIG_NMETER=y +CONFIG_PGREP=y +CONFIG_PKILL=y CONFIG_PIDOF=y -# CONFIG_FEATURE_PIDOF_SINGLE is not set -# CONFIG_FEATURE_PIDOF_OMIT is not set -# CONFIG_PKILL is not set +CONFIG_FEATURE_PIDOF_SINGLE=y +CONFIG_FEATURE_PIDOF_OMIT=y +CONFIG_PMAP=y +CONFIG_POWERTOP=y +CONFIG_FEATURE_POWERTOP_INTERACTIVE=y CONFIG_PS=y # CONFIG_FEATURE_PS_WIDE is not set # CONFIG_FEATURE_PS_LONG is not set -# CONFIG_FEATURE_PS_TIME is not set -# CONFIG_FEATURE_PS_ADDITIONAL_COLUMNS is not set +CONFIG_FEATURE_PS_TIME=y # CONFIG_FEATURE_PS_UNUSUAL_SYSTEMS is not set -# CONFIG_RENICE is not set -# CONFIG_BB_SYSCTL is not set -# CONFIG_FEATURE_SHOW_THREADS is not set -# CONFIG_WATCH is not set +CONFIG_FEATURE_PS_ADDITIONAL_COLUMNS=y +CONFIG_PSTREE=y +CONFIG_PWDX=y +CONFIG_SMEMCAP=y +CONFIG_BB_SYSCTL=y +CONFIG_TOP=y +CONFIG_FEATURE_TOP_INTERACTIVE=y +CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE=y +CONFIG_FEATURE_TOP_CPU_GLOBAL_PERCENTS=y +CONFIG_FEATURE_TOP_SMP_CPU=y +CONFIG_FEATURE_TOP_DECIMALS=y +CONFIG_FEATURE_TOP_SMP_PROCESS=y +CONFIG_FEATURE_TOPMEM=y +CONFIG_UPTIME=y +# CONFIG_FEATURE_UPTIME_UTMP_SUPPORT is not set +CONFIG_WATCH=y +CONFIG_FEATURE_SHOW_THREADS=y # # Runit Utilities # -# CONFIG_RUNSV is not set -# CONFIG_RUNSVDIR is not set +CONFIG_CHPST=y +CONFIG_SETUIDGID=y +CONFIG_ENVUIDGID=y +CONFIG_ENVDIR=y +CONFIG_SOFTLIMIT=y +CONFIG_RUNSV=y +CONFIG_RUNSVDIR=y # CONFIG_FEATURE_RUNSVDIR_LOG is not set -# CONFIG_SV is not set -CONFIG_SV_DEFAULT_SERVICE_DIR="" -# CONFIG_SVLOGD is not set -# CONFIG_CHPST is not set -# CONFIG_SETUIDGID is not set -# CONFIG_ENVUIDGID is not set -# CONFIG_ENVDIR is not set -# CONFIG_SOFTLIMIT is not set +CONFIG_SV=y +CONFIG_SV_DEFAULT_SERVICE_DIR="/var/service" +CONFIG_SVC=y +CONFIG_SVOK=y +CONFIG_SVLOGD=y # CONFIG_CHCON is not set -# CONFIG_FEATURE_CHCON_LONG_OPTIONS is not set # CONFIG_GETENFORCE is not set # CONFIG_GETSEBOOL is not set # CONFIG_LOAD_POLICY is not set # CONFIG_MATCHPATHCON is not set -# CONFIG_RESTORECON is not set # CONFIG_RUNCON is not set -# CONFIG_FEATURE_RUNCON_LONG_OPTIONS is not set # CONFIG_SELINUXENABLED is not set +# CONFIG_SESTATUS is not set # CONFIG_SETENFORCE is not set # CONFIG_SETFILES is not set # CONFIG_FEATURE_SETFILES_CHECK_OPTION is not set +# CONFIG_RESTORECON is not set # CONFIG_SETSEBOOL is not set -# CONFIG_SESTATUS is not set # # Shells # +CONFIG_SH_IS_ASH=y +# CONFIG_SH_IS_HUSH is not set +# CONFIG_SH_IS_NONE is not set +# CONFIG_BASH_IS_ASH is not set +# CONFIG_BASH_IS_HUSH is not set +CONFIG_BASH_IS_NONE=y CONFIG_ASH=y +CONFIG_ASH_OPTIMIZE_FOR_SIZE=y +CONFIG_ASH_INTERNAL_GLOB=y CONFIG_ASH_BASH_COMPAT=y -# CONFIG_ASH_IDLE_TIMEOUT is not set +CONFIG_ASH_BASH_SOURCE_CURDIR=y +CONFIG_ASH_BASH_NOT_FOUND_HOOK=y CONFIG_ASH_JOB_CONTROL=y CONFIG_ASH_ALIAS=y -CONFIG_ASH_GETOPTS=y -# CONFIG_ASH_BUILTIN_ECHO is not set -CONFIG_ASH_BUILTIN_PRINTF=y -CONFIG_ASH_BUILTIN_TEST=y -CONFIG_ASH_HELP=y -CONFIG_ASH_CMDCMD=y -CONFIG_ASH_MAIL=y -# CONFIG_ASH_OPTIMIZE_FOR_SIZE is not set CONFIG_ASH_RANDOM_SUPPORT=y -# CONFIG_ASH_EXPAND_PRMT is not set -# CONFIG_CTTYHACK is not set +CONFIG_ASH_EXPAND_PRMT=y +CONFIG_ASH_IDLE_TIMEOUT=y +CONFIG_ASH_MAIL=y +CONFIG_ASH_ECHO=y +CONFIG_ASH_PRINTF=y +CONFIG_ASH_TEST=y +CONFIG_ASH_HELP=y +CONFIG_ASH_GETOPTS=y +CONFIG_ASH_CMDCMD=y +CONFIG_CTTYHACK=y # CONFIG_HUSH is not set # CONFIG_HUSH_BASH_COMPAT is not set # CONFIG_HUSH_BRACE_EXPANSION is not set -# CONFIG_HUSH_HELP is not set +# CONFIG_HUSH_LINENO_VAR is not set +# CONFIG_HUSH_BASH_SOURCE_CURDIR is not set # CONFIG_HUSH_INTERACTIVE is not set # CONFIG_HUSH_SAVEHISTORY is not set # CONFIG_HUSH_JOB is not set @@ -1030,36 +1128,58 @@ CONFIG_ASH_RANDOM_SUPPORT=y # CONFIG_HUSH_FUNCTIONS is not set # CONFIG_HUSH_LOCAL is not set # CONFIG_HUSH_RANDOM_SUPPORT is not set -# CONFIG_HUSH_EXPORT_N is not set # CONFIG_HUSH_MODE_X is not set -# CONFIG_MSH is not set -CONFIG_FEATURE_SH_IS_ASH=y -# CONFIG_FEATURE_SH_IS_HUSH is not set -# CONFIG_FEATURE_SH_IS_NONE is not set -# CONFIG_FEATURE_BASH_IS_ASH is not set -# CONFIG_FEATURE_BASH_IS_HUSH is not set -CONFIG_FEATURE_BASH_IS_NONE=y -CONFIG_SH_MATH_SUPPORT=y -# CONFIG_SH_MATH_SUPPORT_64 is not set +# CONFIG_HUSH_ECHO is not set +# CONFIG_HUSH_PRINTF is not set +# CONFIG_HUSH_TEST is not set +# CONFIG_HUSH_HELP is not set +# CONFIG_HUSH_EXPORT is not set +# CONFIG_HUSH_EXPORT_N is not set +# CONFIG_HUSH_READONLY is not set +# CONFIG_HUSH_KILL is not set +# CONFIG_HUSH_WAIT is not set +# CONFIG_HUSH_COMMAND is not set +# CONFIG_HUSH_TRAP is not set +# CONFIG_HUSH_TYPE is not set +# CONFIG_HUSH_TIMES is not set +# CONFIG_HUSH_READ is not set +# CONFIG_HUSH_SET is not set +# CONFIG_HUSH_UNSET is not set +# CONFIG_HUSH_ULIMIT is not set +# CONFIG_HUSH_UMASK is not set +# CONFIG_HUSH_GETOPTS is not set +# CONFIG_HUSH_MEMLEAK is not set + +# +# Options common to all shells +# +CONFIG_FEATURE_SH_MATH=y +CONFIG_FEATURE_SH_MATH_64=y CONFIG_FEATURE_SH_EXTRA_QUIET=y -# CONFIG_FEATURE_SH_STANDALONE is not set +CONFIG_FEATURE_SH_STANDALONE=y # CONFIG_FEATURE_SH_NOFORK is not set +CONFIG_FEATURE_SH_READ_FRAC=y CONFIG_FEATURE_SH_HISTFILESIZE=y +# CONFIG_FEATURE_SH_EMBEDDED_SCRIPTS is not set # # System Logging Utilities # -# CONFIG_SYSLOGD is not set -# CONFIG_FEATURE_ROTATE_LOGFILE is not set -# CONFIG_FEATURE_REMOTE_LOG is not set -# CONFIG_FEATURE_SYSLOGD_DUP is not set -# CONFIG_FEATURE_SYSLOGD_CFG is not set -CONFIG_FEATURE_SYSLOGD_READ_BUFFER_SIZE=0 -# CONFIG_FEATURE_IPC_SYSLOG is not set -CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE=0 -# CONFIG_LOGREAD is not set -# CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING is not set -# CONFIG_FEATURE_KMSG_SYSLOG is not set -# CONFIG_KLOGD is not set -# CONFIG_FEATURE_KLOGD_KLOGCTL is not set -# CONFIG_LOGGER is not set +CONFIG_KLOGD=y + +# +# klogd should not be used together with syslog to kernel printk buffer +# +CONFIG_FEATURE_KLOGD_KLOGCTL=y +CONFIG_LOGGER=y +CONFIG_LOGREAD=y +CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING=y +CONFIG_SYSLOGD=y +CONFIG_FEATURE_ROTATE_LOGFILE=y +CONFIG_FEATURE_REMOTE_LOG=y +CONFIG_FEATURE_SYSLOGD_DUP=y +CONFIG_FEATURE_SYSLOGD_CFG=y +CONFIG_FEATURE_SYSLOGD_READ_BUFFER_SIZE=256 +CONFIG_FEATURE_IPC_SYSLOG=y +CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE=16 +CONFIG_FEATURE_KMSG_SYSLOG=y diff --git a/system/base/busybox/pspec.xml b/system/base/busybox/pspec.xml index 4ce5e0a5..be46519b 100644 --- a/system/base/busybox/pspec.xml +++ b/system/base/busybox/pspec.xml @@ -12,7 +12,7 @@ app:console Statically linked binary providing simplified versions of system commands busybox is a single binary which includes versions of a large number of system commands, including a shell. - http://busybox.net/downloads/busybox-1.24.1.tar.bz2 + https://busybox.net/downloads/busybox-1.30.1.tar.bz2 config @@ -20,7 +20,7 @@ udhcp-rootpath-rq.patch suppress-job-control-warning.patch - fix-include.patch + @@ -33,6 +33,13 @@ + + 2019-12-27 + 1.30.1 + Version bump + Idris Kalp + idriskalp@gmail.com + 2018-07-15 1.24.1 From 4d1519127f359bc3867776f09f2d532a37306f3c Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 19:07:23 +0300 Subject: [PATCH 156/160] module-bbswitch rebuild --- kernel/drivers/module-bbswitch/pspec.xml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/kernel/drivers/module-bbswitch/pspec.xml b/kernel/drivers/module-bbswitch/pspec.xml index 80902fa6..9c075e05 100644 --- a/kernel/drivers/module-bbswitch/pspec.xml +++ b/kernel/drivers/module-bbswitch/pspec.xml @@ -13,7 +13,7 @@ Kernel module allowing to switch dedicated graphics card on Optimus laptops kernel module allowing to switch dedicated graphics card on Optimus laptops - kernel-module-headers + kernel-module-headers https://github.com/Bumblebee-Project/bbswitch/archive/v0.8.tar.gz @@ -22,7 +22,7 @@ module-bbswitch - kernel + kernel /lib/modules @@ -36,6 +36,13 @@ + + 2019-12-27 + 0.8 + Rebuild. + Idris Kalp + idriskalp@gmail.com + 2019-06-26 0.8 From 0dd774a74c5c7673489dcf8bc414571c7409589c Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 19:10:26 +0300 Subject: [PATCH 157/160] module-broadcom-wl rebuild --- .../module-broadcom-wl/files/linux-5.1.patch | 15 +++++++++++++++ kernel/drivers/module-broadcom-wl/pspec.xml | 12 ++++++++++-- 2 files changed, 25 insertions(+), 2 deletions(-) create mode 100755 kernel/drivers/module-broadcom-wl/files/linux-5.1.patch diff --git a/kernel/drivers/module-broadcom-wl/files/linux-5.1.patch b/kernel/drivers/module-broadcom-wl/files/linux-5.1.patch new file mode 100755 index 00000000..692f02dd --- /dev/null +++ b/kernel/drivers/module-broadcom-wl/files/linux-5.1.patch @@ -0,0 +1,15 @@ +diff --git a/src/wl/sys/wl_cfg80211_hybrid.c b/src/wl/sys/wl_cfg80211_hybrid.c +index cdf8c01..63b5650 100644 +--- a/src/wl/sys/wl_cfg80211_hybrid.c ++++ b/src/wl/sys/wl_cfg80211_hybrid.c +@@ -52,6 +52,10 @@ u32 wl_dbg_level = WL_DBG_ERR | WL_DBG_INFO; + u32 wl_dbg_level = WL_DBG_ERR; + #endif + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0) ++#define get_ds() ((mm_segment_t) { (-1UL) }) ++#endif ++ + #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) + static s32 wl_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, + enum nl80211_iftype type, struct vif_params *params); \ No newline at end of file diff --git a/kernel/drivers/module-broadcom-wl/pspec.xml b/kernel/drivers/module-broadcom-wl/pspec.xml index 9ee63cba..cd1755ae 100755 --- a/kernel/drivers/module-broadcom-wl/pspec.xml +++ b/kernel/drivers/module-broadcom-wl/pspec.xml @@ -15,7 +15,7 @@ https://docs.broadcom.com/docs-and-downloads/docs/linux_sta/hybrid-v35-nodebug-pcoem-6_30_223_271.tar.gz https://docs.broadcom.com/docs-and-downloads/docs/linux_sta/hybrid-v35_64-nodebug-pcoem-6_30_223_271.tar.gz - kernel-module-headers + kernel-module-headers patch/license.patch @@ -25,13 +25,14 @@ linux-4.11.patch linux-4.12.patch linux-4.15.patch + linux-5.1.patch module-broadcom-wl - kernel + kernel module-broadcom-wl-userspace @@ -60,6 +61,13 @@ + + 2019-12-27 + 6.30.223.271 + Rebuild. + Idris Kalp + idriskalp@gmail.com + 2019-06-26 6.30.223.271 From ed5530cad4465cf5b52722cb3f8d80cba404fc14 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 19:10:41 +0300 Subject: [PATCH 158/160] module-virtualbox 6.1.0 --- kernel/drivers/module-virtualbox/pspec.xml | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/kernel/drivers/module-virtualbox/pspec.xml b/kernel/drivers/module-virtualbox/pspec.xml index 7bee915f..a72622f9 100644 --- a/kernel/drivers/module-virtualbox/pspec.xml +++ b/kernel/drivers/module-virtualbox/pspec.xml @@ -12,9 +12,9 @@ driver Kernel modules for VirtualBox This package provides the kernel support for VirtualBox. - https://sourceforge.net/projects/pisilinux/files/source/module-virtualbox-6.0.14.tar.xz + https://sourceforge.net/projects/pisilinux/files/source/module-virtualbox-6.1.0.tar.xz - kernel-module-headers + kernel-module-headers @@ -24,7 +24,7 @@ module-virtualbox-guest - kernel + kernel baselayout module-virtualbox-guest-userspace @@ -55,6 +55,13 @@ + + 2019-12-27 + 6.1.0 + Version bump. + Idris Kalp + idriskalp@gmail.com + 2019-10-29 6.0.14 From 027652977a65df39c160b775cfeb395869f38b03 Mon Sep 17 00:00:00 2001 From: idriskalp Date: Fri, 27 Dec 2019 19:15:14 +0300 Subject: [PATCH 160/160] ndiswrapper rebuild --- .../ndiswrapper/files/kernel-5.3.patch | 69 +++++++++++++++++++ .../ndiswrapper/files/kernel-5.4.patch | 22 ++++++ kernel/drivers/ndiswrapper/pspec.xml | 20 ++++-- 3 files changed, 104 insertions(+), 7 deletions(-) create mode 100644 kernel/drivers/ndiswrapper/files/kernel-5.3.patch create mode 100644 kernel/drivers/ndiswrapper/files/kernel-5.4.patch diff --git a/kernel/drivers/ndiswrapper/files/kernel-5.3.patch b/kernel/drivers/ndiswrapper/files/kernel-5.3.patch new file mode 100644 index 00000000..33e3ed3b --- /dev/null +++ b/kernel/drivers/ndiswrapper/files/kernel-5.3.patch @@ -0,0 +1,69 @@ +diff --git a/ndiswrapper/driver/ntoskernel.c b/ndiswrapper/driver/ntoskernel.c +index 4fe0dc1..4dd7a89 100644 +--- a/ndiswrapper/driver/ntoskernel.c ++++ b/ndiswrapper/driver/ntoskernel.c +@@ -2524,7 +2524,11 @@ int ntoskernel_init(void) + info->task = NULL; + info->count = 0; + #ifdef CONFIG_SMP ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5,3,0) + cpumask_setall(&info->cpus_allowed); ++#else ++ cpumask_setall(&info->cpus_mask); ++#endif + #endif + } + } while (0); +diff --git a/ndiswrapper/driver/ntoskernel.h b/ndiswrapper/driver/ntoskernel.h +index 3c4c6ff..8a71ae3 100644 +--- a/ndiswrapper/driver/ntoskernel.h ++++ b/ndiswrapper/driver/ntoskernel.h +@@ -107,7 +107,11 @@ static cpumask_t cpumasks[NR_CPUS]; + #endif /* CONFIG_SMP */ + + #ifndef tsk_cpus_allowed ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5,3,0) + #define tsk_cpus_allowed(tsk) (&(tsk)->cpus_allowed) ++#else ++#define tsk_cpus_allowed(tsk) (&(tsk)->cpus_mask) ++#endif + #endif + + #ifndef __packed +@@ -631,7 +635,12 @@ struct irql_info { + int count; + struct mutex lock; + #ifdef CONFIG_SMP ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5,3,0) + cpumask_t cpus_allowed; ++#else ++ const cpumask_t *cpus_ptr; ++ cpumask_t cpus_mask; ++#endif + #endif + struct task_struct *task; + }; +@@ -658,7 +667,11 @@ static inline KIRQL raise_irql(KIRQL newirql) + /* TODO: is this enough to pin down to current cpu? */ + #ifdef CONFIG_SMP + assert(task_cpu(current) == smp_processor_id()); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5,3,0) + cpumask_copy(&info->cpus_allowed, tsk_cpus_allowed(current)); ++#else ++ cpumask_copy(&info->cpus_mask, tsk_cpus_allowed(current)); ++#endif + set_cpus_allowed_ptr(current, cpumask_of(smp_processor_id())); + #endif + put_cpu_var(irql_info); +@@ -682,7 +695,11 @@ static inline void lower_irql(KIRQL oldirql) + if (--info->count == 0) { + info->task = NULL; + #ifdef CONFIG_SMP ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5,3,0) + set_cpus_allowed_ptr(current, &info->cpus_allowed); ++#else ++ set_cpus_allowed_ptr(current, &info->cpus_mask); ++#endif + #endif + mutex_unlock(&info->lock); + } diff --git a/kernel/drivers/ndiswrapper/files/kernel-5.4.patch b/kernel/drivers/ndiswrapper/files/kernel-5.4.patch new file mode 100644 index 00000000..9e3212d8 --- /dev/null +++ b/kernel/drivers/ndiswrapper/files/kernel-5.4.patch @@ -0,0 +1,22 @@ +diff -u -r ndiswrapper-1.62/driver/wrapndis.c ndiswrapper-1.62-5.4/driver/wrapndis.c +--- ndiswrapper-1.62/driver/wrapndis.c 2019-02-11 04:11:14.000000000 +0000 ++++ ndiswrapper-1.62-5.4/driver/wrapndis.c 2019-11-26 00:02:39.035464963 +0000 +@@ -457,10 +457,18 @@ + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; + sg_element++; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5,4,0) + sg_element->length = frag->size; ++#else ++ sg_element->length = skb_frag_size(frag); ++#endif + sg_element->address = + pci_map_page(wnd->wd->pci.pdev, skb_frag_page(frag), ++#if LINUX_VERSION_CODE < KERNEL_VERSION(5,4,0) + frag->page_offset, frag->size, ++#else ++ skb_frag_off(frag), skb_frag_size(frag), ++#endif + PCI_DMA_TODEVICE); + TRACE3("%llx, %u", sg_element->address, sg_element->length); + } diff --git a/kernel/drivers/ndiswrapper/pspec.xml b/kernel/drivers/ndiswrapper/pspec.xml index 2fd06b2f..0be562de 100644 --- a/kernel/drivers/ndiswrapper/pspec.xml +++ b/kernel/drivers/ndiswrapper/pspec.xml @@ -15,19 +15,18 @@ module-ndiswrapper allows you to use Windows XP drivers for WLAN cards without proper Linux drivers. http://download.sourceforge.net/ndiswrapper/ndiswrapper-1.62.tar.gz - kernel-module-headers + kernel-module-headers - + + kernel-5.3.patch + kernel-5.4.patch + ndiswrapper - kernel + kernel /lib/modules @@ -43,6 +42,13 @@ + + 2019-12-27 + 1.62 + Rebuild + Idris Kalp + idriskalp@gmail.com + 2019-06-26 1.62

JQagd74#EtsqoRz3+|9 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